Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/monojack/state-clerk
Easy CRUD operations for managing your state in an immutable way
https://github.com/monojack/state-clerk
crud immutable state-management
Last synced: about 1 month ago
JSON representation
Easy CRUD operations for managing your state in an immutable way
- Host: GitHub
- URL: https://github.com/monojack/state-clerk
- Owner: monojack
- License: mit
- Created: 2017-11-09T10:36:39.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2017-11-16T09:27:57.000Z (about 7 years ago)
- Last Synced: 2024-10-13T23:47:22.721Z (2 months ago)
- Topics: crud, immutable, state-management
- Language: JavaScript
- Size: 310 KB
- Stars: 9
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# State-Clerk
Perform immutable CRUD operation on your application state.
[![Build Status](https://travis-ci.org/monojack/state-clerk.svg?branch=master)](https://travis-ci.org/monojack/state-clerk)
## Table of contents
- [Installation](#installation)
- [Creating an instance](#creating-an-instance)
- [Methods](#methods)
- [get](#get)
- [post](#post)
- [put](#put)
- [patch](#patch)
- [delete](#delete)
- [getCollection](#getcollection)
- [addCollection](#addcollection)
- [removeCollection](#removecollection)### Installation
```bash
npm install state-clerk
```### Creating an instance
Creating a clerk instance is straight-forward.
```js
import Clerk from 'state-clerk'const clerk = new Clerk(state /* the state object */)
```### Methods
The following mock data will be used in the examples:
```js
import Clerk from 'state-clerk'const state = {
todos: {
a: {
_id: 'a',
label: 'Buy milk',
completed: false
},
b: {
_id: 'b',
label: 'Use state-clerk',
completed: true
},
c: {
_id: 'c',
label: 'Do stuff',
completed: true
}
},
lists: [
{
_id: 'x',
name: 'Shopping',
todos: ['a']
},
{
_id: 'y',
name: 'Dev',
todos: ['b']
},
{
_id: 'z',
name: 'Random',
todos: ['c']
}
],
foo: 'bar'
}const clerk = new Clerk(state)
```Throughout the examples we'll be referring to:
- `collection object`: a collection of type Object ({})
- `collection array`: a collection of type Array ([])
- `payload`: resource or data to be created/updated/patched
- `identifier`: a _string|number_ or an _object_ (`{ id: 1 }`) used to identify a specific resource.
- _string|number_ would represent a key inside a collection object
- _object_ is a _key/value_ pair used for matching a resource inside a collection arrayThe **Clerk** instance has the following API:
#### get
_`clerk.get(collection [, identifier])`_
- It throws if the specified collection doesn't exist or it's not a collection.
- It returns the entire collection if identifier is null or undefined.For collection objects:
- It returns the resource found at the specified key (identifier).
- It returns an object of resources that have a matching key/value pair with the one of the identifier object (e.g.: `{ completed: true }`).
- It returns undefined if no resource found with the provided identifier.For collection arrays:
- It returns a list of resources that have a matching key/value pair with the one of the identifier object (e.g.: { completed: true }).
- It returns an empty list if identifier is not an object.
- It returns an empty list if no resource found with the provided identifier.```js
// Valid:
clerk.get('todos', 'a')
// Returns: { id: 'a', label: 'Buy milk', completed: false }clerk.get('todos', { completed: true })
// Returns:
// {
// b: { _id: 'b', label: 'Use state-clerk', completed: true },
// c: { _id: 'c', label: 'Do stuff', completed: true }
// }clerk.get('todos')
// Returns:
// {
// a: { _id: 'a', label: 'Buy milk', completed: false },
// b: { _id: 'b', label: 'Use state-clerk', completed: true },
// c: { _id: 'c', label: 'Do stuff', completed: true }
// }clerk.get('lists', {name: 'Shopping'})
// Returns: [{ _id: 'x', name: 'Shopping', todos: ['a'] }]clerk.get('lists', 'y'})
// not a valid identifier for lists
// Returns: []clerk.get('lists')
// Returns:
// [
// { _id: 'x', name: 'Shopping', todos: ['a'] },
// { _id: 'y', name: 'Dev', todos: ['b'] },
// { _id: 'z', name: 'Random', todos: ['c'] }
// ]// Invalid:
clerk.get('users')
// Throws: The "users" collection does not exist. You can create one using your clerk instance by running(clerk.addCollection('users'))clerk.get('foo')
// Throws: "foo" is not a collection. You can access it like any other property on the state object```
#### post
_`clerk.post(collection, payload [, identifier])`_
- It throws if the specified collection doesn't exist or it's not a collection.
- It throws if not providing a payload.For collection objects:
- It throws if trying to post to a collection object without specifying an identifier.
- It adds to the collection at the specified identifier and returns the new resource.
- It adds the resource for any type of identifier.For collection arrays:
- It adds the resource without the need of an identifier.```js
// Valid:clerk.post('todos', { label: 'Git gud!' }, 'd')
// Returns: { _id: 'd', label: 'Git gud!', completed: false }
//
// state.todos:
// {
// a: { _id: 'a', label: 'Buy milk', completed: false },
// b: { _id: 'b', label: 'Use state-clerk', completed: true },
// c: { _id: 'c', label: 'Do stuff', completed: true },
// d: { _id: 'd', label: 'Git gud!' },
// }clerk.post('lists', { _id: 'w', name: 'Groceries' })
// Returns: { _id: 'w', name: 'Groceries' }
//
// state.lists:
// [
// { _id: 'x', name: 'Shopping', todos: ['a'] },
// { _id: 'y', name: 'Dev', todos: ['b'] },
// { _id: 'z', name: 'Random', todos: ['c'] },
// { _id: 'w', name: 'Groceries' }
// ]// Invalid:
clerk.post('users')
// Throws: The "users" collection does not exist. You can create one using your clerk instance by running(clerk.addCollection('users'))clerk.post('foo')
// Throws: "foo" is not a collection. You can access it like any other property on the state objectclerk.post('todos')
// Throws: You forgot to specify the payloadclerk.post('todos', {...})
// Throws: You are trying to post to a collection object but haven't specified an identifier. Try again with "clerk.post('todos', payload, identifier)"```
#### put
_`clerk.put(collection, payload, identifier)`_
- It throws if the specified collection doesn't exist or it's not a collection.
For collection objects:
- It throws when trying to update a resource without specifying an identifier.
- It creates and returns the resource if no match found.
- It replaces an existing resource and returns the new data.For collection arrays:
- It throws if the identifier is not an object.
- It creates and returns the resource if no identifier provided.
- It creates and returns the resource if no match found.
- It replaces an existing resource and returns the new data.```js
// Valid:clerk.put('todos', { label: 'Buy food', }, 'a')
// Returns: { id: 'a', label: 'Buy food' }
//
// state.todos:
// {
// a: { label: 'Buy food' },
// b: { _id: 'b', label: 'Use state-clerk', completed: true },
// c: { _id: 'c', label: 'Do stuff', completed: true },
// }clerk.put('list', { name: 'Foobar', }, { name: 'Random' })
// Returns: { name: 'Foobar' }
//
// state.lists:
// [
// { _id: 'x', name: 'Shopping', todos: ['a'] },
// { _id: 'y', name: 'Dev', todos: ['b'] }
// { name: 'Foobar' }
// ]// Invalid:
clerk.put('users')
// Throws: The "users" collection does not exist. You can create one using your clerk instance by running(clerk.addCollection('users'))clerk.put('foo')
// Throws: "foo" is not a collection. You can access it like any other property on the state objectclerk.put('todos', {...})
// You are trying to update a resource but haven't specified the identifier. Try again with "clerk.put('todos', payload, identifier)"clerk.put('lists', {...}, 'x')
// Throws: When updating a resource inside a list you have to specify an identifier object containing the key/value pair you want to match.```
#### patch
_`clerk.patch(collection, payload, identifier)`_
- It throws if the specified collection doesn't exist or it's not a collection.
- It throws if no identifier provided.
- It returns undefined if no match found.For collection objects:
- It partially updates an existing resource and returns it.For collection arrays:
- It throws if the identifier is not an object.
- It partially updates an existing resource and returns it.```js
// Valid:clerk.patch('todos', { completed: true }, 'e')
// Returns: undefined
//
// state.todos:
// {
// a: { _id: 'a', label: 'Buy milk', completed: false },
// b: { _id: 'b', label: 'Use state-clerk', completed: true },
// c: { _id: 'c', label: 'Do stuff', completed: true },
// }clerk.patch('todos', { completed: true }, 'a')
// Returns: { _id: 'a', label: 'Buy milk', completed: true }
//
// state.todos:
// {
// a: { _id: 'a', label: 'Buy milk', completed: true },
// b: { _id: 'b', label: 'Use state-clerk', completed: true },
// c: { _id: 'c', label: 'Do stuff', completed: true },
// }clerk.patch('list', { name: 'Programming', }, { name: 'Dev' })
// Returns: { name: 'Foobar' }
//
// state.lists:
// [
// { _id: 'x', name: 'Shopping', todos: ['a'] },
// { _id: 'y', name: 'Programming', todos: ['b'] },
// { _id: 'z', name: 'Random', todos: ['c'] }
// ]// Invalid:
clerk.patch('users')
// Throws: The "users" collection does not exist. You can create one using your clerk instance by running(clerk.addCollection('users'))clerk.patch('foo')
// Throws: "foo" is not a collection. You can access it like any other property on the state objectclerk.patch('todos', {...})
// You are trying to patch a resource but haven't specified the identifier. Try again with "clerk.patch('todos', payload, identifier)"clerk.patch('lists', {...}, 'x')
// Throws: When patching a resource inside a list you have to specify an identifier object containing the key/value pair you want to match.```
#### delete
_`clerk.delete(collection, identifier)`_
- It throws if the specified collection doesn't exist or it's not a collection.
- It returns undefined and doesn't remove anything if no identifier provided.
- It returns undefined and doesn't remove anything if no match found.For collection objects:
- It removes the matching resource from the collectionFor collection arrays:
- It returns undefined and doesn't remove anything if identifier is not an object
- It removes the matching resource from the collection```js
// Valid:clerk.delete('todos') || clerk.delete('todos', 'e')
// Returns: undefined
//
// state.todos:
// {
// a: { _id: 'a', label: 'Buy milk', completed: false },
// b: { _id: 'b', label: 'Use state-clerk', completed: true },
// c: { _id: 'c', label: 'Do stuff', completed: true }
// }
//
clerk.delete('todos', 'a')
// Returns: { _id: 'a', label: 'Buy milk', completed: false }
//
// state.todos:
// {
// b: { _id: 'b', label: 'Use state-clerk', completed: true },
// c: { _id: 'c', label: 'Do stuff', completed: true }
// }clerk.delete('lists') || clerk.delete('lists', { _id: 'w' }) || clerk.delete('lists', 'x')
// Returns: undefined
//
// state.lists
// [
// { _id: 'x', name: 'Shopping', todos: ['a'] },
// { _id: 'y', name: 'Dev', todos: ['b'] },
// { _id: 'z', name: 'Random', todos: ['c'] }
// ]clerk.delete('lists', { _id: 'x' })
// Returns: { _id: 'x', name: 'Shopping', todos: ['a'] }
//
// state.lists
// [
// { _id: 'y', name: 'Dev', todos: ['b'] },
// { _id: 'z', name: 'Random', todos: ['c'] }
// ]// Invalid:
clerk.delete('users')
// Throws: The "users" collection does not exist. You can create one using your clerk instance by running(clerk.addCollection('users'))clerk.delete('foo')
// Throws: "foo" is not a collection. You can access it like any other property on the state object
```#### getCollection
_`clerk.getCollection(collectionName)`_
```js
clerk.getCollection('todos')
// Returns:
// {
// a: { _id: 'a', label: 'Buy milk', completed: false },
// b: { _id: 'b', label: 'Use state-clerk', completed: true },
// c: { _id: 'c', label: 'Do stuff', completed: true }
// }clerk.getCollection('users')
// Returns: undefined
```#### addCollection
_`clerk.addCollection(collectionName [, type = Object])`_
```js
clerk.addCollection('users')
// state:
// {
// todos: {...},
// lists: [...],
// foo: 'bar',
// users: {},
// }clerk.addCollection('comments', Array)
// state:
// {
// todos: {...},
// lists: [...],
// foo: 'bar',
// users: {},
// comments: [],
// }
```#### removeCollection
_`clerk.removeCollection(collectionName [, type = Object])`_
```js
clerk.removeCollection('todos')
// Returns:
// {
// a: { _id: 'a', label: 'Buy milk', completed: false },
// b: { _id: 'b', label: 'Use state-clerk', completed: true },
// c: { _id: 'c', label: 'Do stuff', completed: true }
// }
//
// state:
// {
// lists: [...],
// foo: 'bar'
// }clerk.removeCollection('users')
// Returns: undefined
//
// state:
// {
// todos: {...},
// lists: [...],
// foo: 'bar'
// }
```