{"id":21076545,"url":"https://github.com/monojack/state-clerk","last_synced_at":"2025-08-04T01:34:37.744Z","repository":{"id":57369945,"uuid":"110101931","full_name":"monojack/state-clerk","owner":"monojack","description":"Easy CRUD operations for managing your state in an immutable way","archived":false,"fork":false,"pushed_at":"2017-11-16T09:27:57.000Z","size":317,"stargazers_count":9,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-28T13:46:13.250Z","etag":null,"topics":["crud","immutable","state-management"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/monojack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-11-09T10:36:39.000Z","updated_at":"2024-01-25T14:27:28.000Z","dependencies_parsed_at":"2022-09-09T16:40:14.498Z","dependency_job_id":null,"html_url":"https://github.com/monojack/state-clerk","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/monojack/state-clerk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monojack%2Fstate-clerk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monojack%2Fstate-clerk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monojack%2Fstate-clerk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monojack%2Fstate-clerk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/monojack","download_url":"https://codeload.github.com/monojack/state-clerk/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monojack%2Fstate-clerk/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268636601,"owners_count":24282131,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-03T02:00:12.545Z","response_time":2577,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["crud","immutable","state-management"],"created_at":"2024-11-19T19:28:59.920Z","updated_at":"2025-08-04T01:34:37.719Z","avatar_url":"https://github.com/monojack.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# State-Clerk\n\nPerform immutable CRUD operation on your application state.\n\n[![Build Status](https://travis-ci.org/monojack/state-clerk.svg?branch=master)](https://travis-ci.org/monojack/state-clerk)\n\n## Table of contents\n  - [Installation](#installation)\n  - [Creating an instance](#creating-an-instance)\n  - [Methods](#methods)\n    - [get](#get)\n    - [post](#post)\n    - [put](#put)\n    - [patch](#patch)\n    - [delete](#delete)\n    - [getCollection](#getcollection)\n    - [addCollection](#addcollection)\n    - [removeCollection](#removecollection)\n\n### Installation\n```bash\nnpm install state-clerk\n```\n\n\n### Creating an instance\n\nCreating a clerk instance is straight-forward.\n\n```js\nimport Clerk from 'state-clerk'\n\nconst clerk = new Clerk(state /* the state object */)\n```\n\n### Methods\n\nThe following mock data will be used in the examples:\n\n```js\nimport Clerk from 'state-clerk'\n\nconst state = {\n  todos: {\n    a: {\n      _id: 'a',\n      label: 'Buy milk',\n      completed: false\n    },\n    b: {\n      _id: 'b',\n      label: 'Use state-clerk',\n      completed: true\n    },\n    c: {\n      _id: 'c',\n      label: 'Do stuff',\n      completed: true\n    }\n  },\n  lists: [\n    {\n      _id: 'x',\n      name: 'Shopping',\n      todos: ['a']\n    },\n    {\n      _id: 'y',\n      name: 'Dev',\n      todos: ['b']\n    },\n    {\n      _id: 'z',\n      name: 'Random',\n      todos: ['c']\n    }\n  ],\n  foo: 'bar'\n}\n\nconst clerk = new Clerk(state)\n```\n\nThroughout the examples we'll be referring to:\n- `collection object`: a collection of type Object ({})\n- `collection array`: a collection of type Array ([])\n- `payload`: resource or data to be created/updated/patched\n- `identifier`: a _string|number_ or an _object_ (`{ id: 1 }`) used to identify a specific resource.\n  - _string|number_ would represent a key inside a collection object\n  - _object_ is a _key/value_ pair used for matching a resource inside a collection array\n\nThe **Clerk** instance has the following API:\n\n#### get\n\n_`clerk.get(collection [, identifier])`_\n\n- It throws if the specified collection doesn't exist or it's not a collection.\n- It returns the entire collection if identifier is null or undefined.\n\nFor collection objects:\n- It returns the resource found at the specified key (identifier).\n- It returns an object of resources that have a matching key/value pair with the one of the identifier object (e.g.: `{ completed: true }`).\n- It returns undefined if no resource found with the provided identifier.\n\nFor collection arrays:\n- It returns a list of resources that have a matching key/value pair with the one of the identifier object (e.g.: { completed: true }).\n- It returns an empty list if identifier is not an object.\n- It returns an empty list if no resource found with the provided identifier.\n\n\n```js\n\n// Valid:\n\nclerk.get('todos', 'a')\n// Returns: { id: 'a', label: 'Buy milk', completed: false }\n\nclerk.get('todos', { completed: true })\n// Returns:\n//  {\n//    b: { _id: 'b', label: 'Use state-clerk', completed: true },\n//    c: { _id: 'c', label: 'Do stuff', completed: true }\n//  }\n\nclerk.get('todos')\n// Returns:\n//  {\n//    a: { _id: 'a', label: 'Buy milk', completed: false },\n//    b: { _id: 'b', label: 'Use state-clerk', completed: true },\n//    c: { _id: 'c', label: 'Do stuff', completed: true }\n//  }\n\nclerk.get('lists', {name: 'Shopping'})\n// Returns: [{ _id: 'x', name: 'Shopping', todos: ['a'] }]\n\nclerk.get('lists', 'y'})\n//  not a valid identifier for lists\n// Returns: []\n\nclerk.get('lists')\n// Returns:\n//  [\n//    { _id: 'x', name: 'Shopping', todos: ['a'] },\n//    { _id: 'y', name: 'Dev', todos: ['b'] },\n//    { _id: 'z', name: 'Random', todos: ['c'] }\n//  ]\n\n\n// Invalid:\n\nclerk.get('users')\n// Throws: The \"users\" collection does not exist. You can create one using your clerk instance by running(clerk.addCollection('users'))\n\nclerk.get('foo')\n// Throws: \"foo\" is not a collection. You can access it like any other property on the state object\n\n```\n\n#### post\n\n_`clerk.post(collection, payload [, identifier])`_\n\n- It throws if the specified collection doesn't exist or it's not a collection.\n- It throws if not providing a payload.\n\nFor collection objects:\n- It throws if trying to post to a collection object without specifying an identifier.\n- It adds to the collection at the specified identifier and returns the new resource.\n- It adds the resource for any type of identifier.\n\nFor collection arrays:\n- It adds the resource without the need of an identifier.\n\n```js\n// Valid:\n\nclerk.post('todos', { label: 'Git gud!' }, 'd')\n// Returns: { _id: 'd', label: 'Git gud!', completed: false }\n//\n// state.todos:\n// {\n//    a: { _id: 'a', label: 'Buy milk', completed: false },\n//    b: { _id: 'b', label: 'Use state-clerk', completed: true },\n//    c: { _id: 'c', label: 'Do stuff', completed: true },\n//    d: { _id: 'd', label: 'Git gud!' },\n//  }\n\nclerk.post('lists', { _id: 'w', name: 'Groceries' })\n// Returns: { _id: 'w', name: 'Groceries' }\n//\n// state.lists:\n//  [\n//    { _id: 'x', name: 'Shopping', todos: ['a'] },\n//    { _id: 'y', name: 'Dev', todos: ['b'] },\n//    { _id: 'z', name: 'Random', todos: ['c'] },\n//    { _id: 'w', name: 'Groceries' }\n//  ]\n\n\n// Invalid:\n\nclerk.post('users')\n// Throws: The \"users\" collection does not exist. You can create one using your clerk instance by running(clerk.addCollection('users'))\n\nclerk.post('foo')\n// Throws: \"foo\" is not a collection. You can access it like any other property on the state object\n\nclerk.post('todos')\n// Throws: You forgot to specify the payload\n\nclerk.post('todos', {...})\n// Throws: You are trying to post to a collection object but haven't specified an identifier. Try again with \"clerk.post('todos', payload, identifier)\"\n\n```\n\n#### put\n\n_`clerk.put(collection, payload, identifier)`_\n\n- It throws if the specified collection doesn't exist or it's not a collection.\n\nFor collection objects:\n- It throws when trying to update a resource without specifying an identifier.\n- It creates and returns the resource if no match found.\n- It replaces an existing resource and returns the new data.\n\nFor collection arrays:\n- It throws if the identifier is not an object.\n- It creates and returns the resource if no identifier provided.\n- It creates and returns the resource if no match found.\n- It replaces an existing resource and returns the new data.\n\n```js\n// Valid:\n\nclerk.put('todos', { label: 'Buy food', }, 'a')\n// Returns: { id: 'a', label: 'Buy food' }\n//\n// state.todos:\n// {\n//    a: { label: 'Buy food' },\n//    b: { _id: 'b', label: 'Use state-clerk', completed: true },\n//    c: { _id: 'c', label: 'Do stuff', completed: true },\n//  }\n\nclerk.put('list', { name: 'Foobar', }, { name: 'Random' })\n// Returns: { name: 'Foobar' }\n//\n// state.lists:\n//  [\n//    { _id: 'x', name: 'Shopping', todos: ['a'] },\n//    { _id: 'y', name: 'Dev', todos: ['b'] }\n//    { name: 'Foobar' }\n//  ]\n\n\n// Invalid:\n\nclerk.put('users')\n// Throws: The \"users\" collection does not exist. You can create one using your clerk instance by running(clerk.addCollection('users'))\n\nclerk.put('foo')\n// Throws: \"foo\" is not a collection. You can access it like any other property on the state object\n\nclerk.put('todos', {...})\n// You are trying to update a resource but haven't specified the identifier. Try again with \"clerk.put('todos', payload, identifier)\"\n\nclerk.put('lists', {...}, 'x')\n// Throws: When updating a resource inside a list you have to specify an identifier object containing the key/value pair you want to match.\n\n```\n\n#### patch\n\n_`clerk.patch(collection, payload, identifier)`_\n\n- It throws if the specified collection doesn't exist or it's not a collection.\n- It throws if no identifier provided.\n- It returns undefined if no match found.\n\nFor collection objects:\n- It partially updates an existing resource and returns it.\n\nFor collection arrays:\n- It throws if the identifier is not an object.\n- It partially updates an existing resource and returns it.\n\n```js\n// Valid:\n\nclerk.patch('todos', { completed: true }, 'e')\n// Returns: undefined\n//\n// state.todos:\n// {\n//    a: { _id: 'a', label: 'Buy milk', completed: false },\n//    b: { _id: 'b', label: 'Use state-clerk', completed: true },\n//    c: { _id: 'c', label: 'Do stuff', completed: true },\n//  }\n\nclerk.patch('todos', { completed: true }, 'a')\n// Returns: { _id: 'a', label: 'Buy milk', completed: true }\n//\n// state.todos:\n// {\n//    a: { _id: 'a', label: 'Buy milk', completed: true },\n//    b: { _id: 'b', label: 'Use state-clerk', completed: true },\n//    c: { _id: 'c', label: 'Do stuff', completed: true },\n//  }\n\nclerk.patch('list', { name: 'Programming', }, { name: 'Dev' })\n// Returns: { name: 'Foobar' }\n//\n// state.lists:\n//  [\n//    { _id: 'x', name: 'Shopping', todos: ['a'] },\n//    { _id: 'y', name: 'Programming', todos: ['b'] },\n//    { _id: 'z', name: 'Random', todos: ['c'] }\n//  ]\n\n// Invalid:\n\nclerk.patch('users')\n// Throws: The \"users\" collection does not exist. You can create one using your clerk instance by running(clerk.addCollection('users'))\n\nclerk.patch('foo')\n// Throws: \"foo\" is not a collection. You can access it like any other property on the state object\n\nclerk.patch('todos', {...})\n// You are trying to patch a resource but haven't specified the identifier. Try again with \"clerk.patch('todos', payload, identifier)\"\n\nclerk.patch('lists', {...}, 'x')\n// Throws: When patching a resource inside a list you have to specify an identifier object containing the key/value pair you want to match.\n\n```\n\n#### delete\n\n_`clerk.delete(collection, identifier)`_\n\n- It throws if the specified collection doesn't exist or it's not a collection.\n- It returns undefined and doesn't remove anything if no identifier provided.\n- It returns undefined and doesn't remove anything if no match found.\n\nFor collection objects:\n- It removes the matching resource from the collection\n\nFor collection arrays:\n- It returns undefined and doesn't remove anything if identifier is not an object\n- It removes the matching resource from the collection\n\n```js\n// Valid:\n\nclerk.delete('todos') || clerk.delete('todos', 'e')\n// Returns: undefined\n//\n// state.todos:\n//  {\n//    a: { _id: 'a', label: 'Buy milk', completed: false },\n//    b: { _id: 'b', label: 'Use state-clerk', completed: true },\n//    c: { _id: 'c', label: 'Do stuff', completed: true }\n//  }\n//  \nclerk.delete('todos', 'a')\n// Returns: { _id: 'a', label: 'Buy milk', completed: false }\n//\n// state.todos:\n//  {\n//    b: { _id: 'b', label: 'Use state-clerk', completed: true },\n//    c: { _id: 'c', label: 'Do stuff', completed: true }\n//  }\n\nclerk.delete('lists') || clerk.delete('lists', { _id: 'w' }) || clerk.delete('lists', 'x')\n// Returns: undefined\n//\n// state.lists\n//  [\n//    { _id: 'x', name: 'Shopping', todos: ['a'] },\n//    { _id: 'y', name: 'Dev', todos: ['b'] },\n//    { _id: 'z', name: 'Random', todos: ['c'] }\n//  ]\n\nclerk.delete('lists', { _id: 'x' })\n// Returns: { _id: 'x', name: 'Shopping', todos: ['a'] }\n//\n// state.lists\n//  [\n//    { _id: 'y', name: 'Dev', todos: ['b'] },\n//    { _id: 'z', name: 'Random', todos: ['c'] }\n//  ]\n\n\n// Invalid:\n\nclerk.delete('users')\n// Throws: The \"users\" collection does not exist. You can create one using your clerk instance by running(clerk.addCollection('users'))\n\nclerk.delete('foo')\n// Throws: \"foo\" is not a collection. You can access it like any other property on the state object\n```\n\n#### getCollection\n\n_`clerk.getCollection(collectionName)`_\n\n```js\nclerk.getCollection('todos')\n// Returns:\n//  {\n//    a: { _id: 'a', label: 'Buy milk', completed: false },\n//    b: { _id: 'b', label: 'Use state-clerk', completed: true },\n//    c: { _id: 'c', label: 'Do stuff', completed: true }\n//  }\n\nclerk.getCollection('users')\n// Returns: undefined\n```\n\n#### addCollection\n\n_`clerk.addCollection(collectionName [, type = Object])`_\n\n```js\nclerk.addCollection('users')\n// state:\n// {\n//  todos: {...},\n//  lists: [...],\n//  foo: 'bar',\n//  users: {},\n// }\n\nclerk.addCollection('comments', Array)\n// state:\n// {\n//  todos: {...},\n//  lists: [...],\n//  foo: 'bar',\n//  users: {},\n//  comments: [],\n// }\n```\n\n#### removeCollection\n\n_`clerk.removeCollection(collectionName [, type = Object])`_\n\n```js\nclerk.removeCollection('todos')\n// Returns:\n//  {\n//    a: { _id: 'a', label: 'Buy milk', completed: false },\n//    b: { _id: 'b', label: 'Use state-clerk', completed: true },\n//    c: { _id: 'c', label: 'Do stuff', completed: true }\n//  }\n//  \n// state:\n// {\n//  lists: [...],\n//  foo: 'bar'\n// }\n\nclerk.removeCollection('users')\n// Returns: undefined\n//\n// state:\n// {\n//  todos: {...},\n//  lists: [...],\n//  foo: 'bar'\n// }\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmonojack%2Fstate-clerk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmonojack%2Fstate-clerk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmonojack%2Fstate-clerk/lists"}