npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@onehat/data

v1.21.20

Published

JS data modeling package with adapters for many storage mediums.

Downloads

423

Readme

Overview

@onehat/data A robust ORM for Javascript. Can CRUD, search, sort, filter, paginate your data. Integrates with many front- and back-end storage mediums.

  • Repositories. A Repository stores many Entities in a storage medium. Corresponds to a database table. Repositories can sort, search/filter, and add/edit/delete their constituent Entities.
  • Storage Mediums. Repositories are specialized to store their data in a single type of storage medium. Available types of Repositories include: Memory, Ajax, Rest, LocalStorage (Browser), SessionStorage (Browser), IndexedDB (Browser), AsyncStorage (React Native/Expo), SecureStore (React Native/Expo). One special type of Repository—LocalFromRemote—combines two different Repository types (one local and one remote) into a single Repository, thereby allowing autosyncing between the local and remote repositories, enabling true offline-first capability.
  • Entities. An Entity is a single record of data, organized into properties. Corresponds to a database row. Entity data can be accessed directly (entity.username), via specific properties and their formatted values (entity.properties.username.displayValue), or by obtaining a JS object of the whole Entity (entity.getDisplayValues(), or entity.getSubmitValues()).
  • Properties. A Property is a single unit of data. Corresponds to a database field. Properties are differentiated into different Property types (e.g. Integer, String, Boolean, etc), and thereby allow for easy formatting of "display" or "submit" values. For example, a date might be set to display as "Wed, Feb 5, 2020" but submit as "2020-02-05".
  • Schemas. A Schema defines the configuration of a Repository. Corresponds roughly to the database table schema. The Schema defines the name and type of Repository, the Properties that exist, and which are "id" and "display" Properties.

Install

npm i @onehat/data

Usage

Comprehensive unit tests can be found in ./cypress/integration. These are an excellent source of code examples. Comprehensive API documentation can be found in ./docs.

1. Define a Schema

For every type of Entity you will use (e.g. Users or Animals or Invoices), define a Schema. A Schema determines the various Properties that each Entity will have, as well as the medium where the Entities will be stored.

const Users = {
	name: 'Users',
	model: {
		idProperty: 'id',
		displayProperty: 'username',
		properties: [
			{ name: 'id', type: 'int', },
			{ name: 'username', type: 'string', }, // explicitly set property type
			{ name: 'password', }, // type: 'string' is assumed, if not explicitly set
			{ name: 'first_name', },
			{ name: 'last_name', },
			{ name: 'email', allowNull: false, }, // make it a required field
			{ name: 'last_login', type: 'datetime', defaultValue: 'now', }, // give it a default value.
		],
		sorters: [
			{
				name: 'last_name',
				direction: 'ASC',
			},
			{
				name: 'first_name',
				direction: 'ASC',
			},
		],
	},
	repository: 'memory', // Repository type. Can be string name or config object
};
export default Users;

Every Property must have a unique name. All other attributes are optional. Common Property attributes include:

  • name - The name of the Property
  • type - The type of the Property (e.g. 'string', 'bool', 'int', etc)
  • allowNull - Is this Property required to have a value?
  • defaultValue - Default value for this Property if none is supplied
  • isSortable - Whether this Property type is sortable

Other Property attributes exist and can be found in the API.

2. Create a Repository

The easiest way to create one or more Repositories is to use the global oneHatData singleton object. Each schema will have a bound repository of the same name (e.g. "Users", or "Groups").

import oneHatData from '@onehat/data';
import Groups from './Groups';
import Users from './Users';

oneHatData
	.createSchemas([
		Groups,
		Users,
	])
	.createBoundRepositories()
	.then(() => {
		setIsReady(true);
		
		const UsersRepository = oneHatData.getRepository('Users');

		// Do something with your data

	});

3. Add / Edit / Delete an Entity

Once you have a Repository initialized, you can start adding data to it. Data is manipulated asynchronously, so you may optionally wait for it to complete.

const UsersRepository = oneHatData.getRepository('Users');

// 1. Add an Entity
const userEntity = await UsersRepository.add({
	username: 'ajones',
	password: '12345',
	first_name: 'Alice',
	last_name: 'Jones',
	email: '[email protected]',
});


// 2. Edit an Entity
// Use assignment to change the value of a particular Property.
userEntity.password = 'mypass';

// Or you can be more verbose about it
userEntity.getProperty('password').setValue('mypass');


// 3. Delete an Entity
userEntity.delete();

// Or delete it from the Repository
await UsersRepository.delete(userEntity);

4. Filter and Sort the Entities in a Repository

There are lots of filtering and sorting methods available on Repositories.

// Add a single filter
UsersRepository.filter('first_name', 'Alice');
const foundEntities = UsersRepository.entities;

// Or search by an id or function
const myEntity = UsersRepository.getById(1);
const results = UsersRepository.getBy((entity) => {
	return entity.id > 2;
});

// Sort the entities by a particular Property
UsersRepository.sort('last_name', 'DESC');
const sortedEntities = UsersRepository.entities;

5. Listen for events and respond to them

Repositories, Entities, and Properties emit many different kinds of events.

// The 'change' event, emitted from an Entity, is relayed through the Repository and becomes 'entity_change'
UsersRepository.on('entity_change', (entity) => {
	console.log('changed entity');
});
userEntity.first_name = 'Joe';
// prints 'changed entity' to console


// The 'changeData' event is fired from the Repository after multiple Entities are loaded at once
UsersRepository.on('changeData', (entities) => {
	console.log('entities changed');
});
UsersRepository.load([
	{ email: '[email protected]' },
	{ email: '[email protected]' },
	{ email: '[email protected]' },
]);
// prints 'entities changed' to console