Store your items of data in a store powered by immutability
$ npm install immutable-item-store
import { ItemStore } from 'immutable-item-store';
// Declare your item class
class User {
id = 'some-id';
name = 'user name';
isAdmin = false;
}
// Create an instance and pass item interface
const userStore = new ItemStore<User>();
const newUser = new User();
// Add new item
const { itemsDraft, patches, inversePatches, confirm } = userStore.add(newUser);
console.log('items size:', userStore.items.size); // items size: 0
console.log('items draft size:', itemsDraft.size); // items draft size: 1
confirm(); // or userStore.applyPatches(patches)
console.log('items size:', userStore.items.size); // items size: 1
userStore.applyPatches(inversePatches);
console.log('items size:', userStore.items.size); // items size: 0
// Update item
userStore.update('some-id', { isAdmin: true }).confirm();
// Batch update items
const updates: BatchUpdate<User>[] = [
{ id: 'some-id', itemProps: { name: 'user name 2' } },
{ id: 'some-id-2', itemProps: { name: 'user name 3', isAdmin: true } },
];
userStore.batchUpdate(updates).confirm();
// Remove item
userStore.remove('some-id').confirm();
import { ItemStore } from 'immutable-item-store';
// Declare your item class
class User {
id = 'id';
name = 'user name';
isAdmin = false;
}
class UserStore extends ItemStore<User> {
public applyPatches(patches: Patch[]): User {
const userId = patch.path[0] as string;
const fieldName = patch.path[1];
// Whenever user data changes we can identify what exactly has changed
if (userId && fieldName) {
console.log(`UserClient "${clientId}" changed "${fieldName}" to `, patch.value);
} else if (clientId) {
console.log(`UserClient "${clientId}" was ${patch.op}(e)d`);
}
// Do some data hanling (e.g. validation, emit event) and then apply the patches
// if (validate(patches)) {
const user = super.applyPatches(patches);
// } else {
// throw new Error('Not valid');
// }
return user;
}
}
const userStore = new UserStore();
const newUser = new User();
userStore.add(newUser).confirm();
const { itemsDraft, patches, inversePatches, confirm } = userStore.update(newUser.id, { name: 'new name' });
// Optimistic update
confirm();
api.users.create(newUser).catch((e) => {
// If operation failed - reverse changes
userStore.applyPatches(inversePatches);
});
Gets an item by id
Creates a draft of adding a new item to the store. Returned value.
Creates a draft of updating an item with new values. Returned value.
Creates a draft of removing an item from the store. Returned value.
.batchUpdate(updates: BatchUpdate[])
Creates a draft of batch updating items with new values. Returned value.
.applyPatches(patches: Patch)
Applies patches to stored items. More on patches.
Transforms map of items to an array when required
of add, update, remove, batchUpdate methods
type OpReturnType<T> = {
itemsDraft: Items<Immutable<ItemType>>;
patches: Patch[];
inversePatches: Patch[];
confirm: () => Items<ItemType>;
};
The draft of changes that were initiated
Describes changes that were initiated
Describes inverse changes
Saves the draft by appling patches
interface Patch {
op: "replace" | "remove" | "add";
path: (string | number)[];
value?: any;
}