{"id":15685486,"url":"https://github.com/js2me/stonex","last_synced_at":"2025-05-07T17:13:18.466Z","repository":{"id":44138694,"uuid":"172989330","full_name":"js2me/stonex","owner":"js2me","description":"💡 Simple state container for JavaScript/TypeScript applications 💡","archived":false,"fork":false,"pushed_at":"2023-01-03T17:37:21.000Z","size":1074,"stargazers_count":9,"open_issues_count":16,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-07T17:13:13.250Z","etag":null,"topics":["data-storage","predictable","predictable-state","redux","state","state-container","state-management","stonex-store"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/js2me.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2019-02-27T20:59:16.000Z","updated_at":"2023-12-08T12:13:53.000Z","dependencies_parsed_at":"2023-02-01T08:16:38.804Z","dependency_job_id":null,"html_url":"https://github.com/js2me/stonex","commit_stats":null,"previous_names":["acacode/stonex"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/js2me%2Fstonex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/js2me%2Fstonex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/js2me%2Fstonex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/js2me%2Fstonex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/js2me","download_url":"https://codeload.github.com/js2me/stonex/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252922339,"owners_count":21825639,"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","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":["data-storage","predictable","predictable-state","redux","state","state-container","state-management","stonex-store"],"created_at":"2024-10-03T17:25:30.474Z","updated_at":"2025-05-07T17:13:18.440Z","avatar_url":"https://github.com/js2me.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n  [![stonex](./logo.png)](https://www.npmjs.com/package/stonex) \n\n  [![](https://img.shields.io/badge/license-MIT-red.svg)](./LICENSE)\n  [![](https://img.shields.io/npm/v/stonex.svg)](https://www.npmjs.com/package/stonex)\n  [![](https://img.shields.io/travis/acacode/stonex.svg)](https://travis-ci.org/acacode/stonex)\n  [![](https://img.shields.io/npm/dm/stonex.svg)](http://npm-stat.com/charts.html?package=stonex)\n  [![](https://badgen.net/bundlephobia/min/stonex)](https://bundlephobia.com/result?p=stonex)\n  [![](https://badgen.net/bundlephobia/minzip/stonex)](https://bundlephobia.com/result?p=stonex)\n\n  \u003cp\u003e\n    🌀 State container for JavaScript/TypeScript applications 🌀️\n  \u003c/p\u003e\n\u003c/div\u003e\n\n#### Table of Contents  \n\n[What is that ?](#what-is-that)  \n[How to use](#-how-to-use)  \n[Documentation](#-documentation):  \n    - [Stonex Store](#stonexstoresource-link)  \n    - [Stonex Module](#stonexmodulesource-link)  \n    - [StateWorker](#stateworkersource-link)  \n    - [createStoreBinder](#createstorebindersource-link)  \n[License](#-license)  \n\n\n## ❓ What is that ?\n\nThis is a simple and easy library for managing/storing data.  \nIt allows you to store and manage data correctly, and also combine all business logic into separated `Stonex` modules.\n\nEasily configurable, most things can be overridden if necessary.\n\nAs well as in other similar libraries, each `Stonex` module has its own **state** and **actions**. But, unlike other libraries, most of the `Stonex` features are provided \"out of the box\", for example, the creating asynchronous actions.\n\nThe syntax of the modules is almost identical to the syntax of the `ReactJS` component.\n\nAlso currently `Stonex` is supporting integrations with: [ReactJS (react-stonex)](https://github.com/acacode/react-stonex)\n\n## 💡 How to use\n\n**1.** Needs to install it:\n\n```shell\n\n  npm i -S stonex\n\n  # or using yarn\n\n  yarn add stonex\n\n```\n\n**2.** Create a `StonexModule` which will contains actions and state\n\n`StonexModule` gives methods `setState`, `getState` (the same as `this.state`), `resetState`\n\n```js\n  // UsersModule.js\n\n  import { StonexModule } from 'stonex'\n\n  export default class UsersModule extends StonexModule {\n\n    // required field\n    state = {}\n\n    createUser = async (id, userData) =\u003e {\n      this.setState({\n        ...this.state,\n        [id]: {...userData}\n      })\n\n      return this.state\n    }\n\n  }\n\n```\n\n**3.** Create a store using class `StonexStore`:\n\n```js\n  // store.js\n\n  import { StonexStore } from 'stonex'\n  import UsersModule from './UsersModule'\n\n  const store = new StonexStore({\n    users: UsersModule,\n  })\n\n```\n\n**4.** Use `store` to work with modules:\n\n```js\n  // store.js\n\n  store.modules.users.createUser('123', { firstName: 'Foo' })\n\n  console.log(store.modules.users.state) // { '123': { firstName: 'Foo' } }\n\n  // you can reset state of your user module using\n  store.modules.users.resetState()\n\n  // after 'resetState' methodd your state will have initial value\n  console.log(store.modules.users.state) // {}\n\n```\n\n\n## 📚 Documentation\n\n\n### `StonexStore`[[Source link]](./src/StonexStore.ts#L33)  \n`import { StonexStore } from 'stonex'`  \n\nCreates a new stonex store. Combining all your stonex modules together and allows to use them in your application.  \n\n\nHave two arguments:  \n\n 1. **modules** - Map of modules which will contains in stonex store.  \n  Each module should be extended from `StonexModule` class or you can create a [[pure stonex module]](./README#L229)  \n 2. **configuration** - Configuration object which need to override something inside stonex.  \n  Object with keys: `stateWorker`, `modifiers`  \n    - `stateWorker`[[Source link]](./src/StateWorker.ts#L4)\n        Default value is [`StateWorker`](./src/StateWorker.ts#L4)  \n        Needs for overriding of all behaviour with working with state of each module.(`this.setState`, `this.getState`, etc)  \n    - `modifiers`[[Source link]](./src/StateWorker.ts#L4)\n        Default value is `[]`  \n        This list of functions where function is [Modifier](./src/ModifiersWorker.ts#L9)  \n        Simple description about `Modifier` type:  \n        ```js\n          const yourModifier = (store) =\u003e {\n            // it has been called when store will be created\n            return (module) =\u003e {\n              // it has been called when module will be created\n\n              return (actionArgs, moduleName, methodName) =\u003e {\n                // it has been called when some action will be called\n\n              }\n            }\n          }\n        ```\n\nInstance of `StonexStore` have properties:  \n\n- `connectModule(moduleName: string, module: StonexModule | ModuleConfiguration | PureStonexModule)`  \n  Connect Stonex Module to store  \n- `createStateSnapshot()`  \n  Return snapshot of states of all modules connected to store \n- `getState(moduleName: string)`  \n  Returns state of module  \n- `modules: StonexModules`  \n  Object with stonex modules where key is name of module \n- `resetState(moduleName: string, callback: (state: any) =\u003e any = noop)`  \n  Reset state of module to initial value  \n- `setState(moduleName: string, changes: any, callback: (state: any) =\u003e any = noop)`  \n  Update state of module  \n- `storeId: number`  \n  Unique identifier of store  \n\nUsings:  \n\n```js\nconst store = new StonexStore({\n  key1: StonexModule1,\n  key2: StonexModule2\n}, {\n  stateWorker: YourStateWorker,\n  modifiers: [\n    YourModifier,\n    SomeLogger,\n    SomeStoreModifier,\n  ]\n})\n```\n\n\n  \u003chr\u003e\n\n\n\n### `StonexModule`[[Source link]](./src/StonexModule.ts#L30)  \n`import { StonexModule } from 'stonex'`  \n\nThe important parent class of your stonex modules.  \nProvide linking store information to your stonex module and specific methods which allows to work with `state`.  \n\n\n`StonexModule` provides properties: `this.setState`, `this.getState`, `this.resetState`, `this.moduleName`, `this.modules`\n\n`setState` - Update module's state  \n`getState` - Same as `this.state`. Returns fresh state of module  \n`resetState` - Reset state of module to the initial value  \n`moduleName` - Name of that stonex module containing in your store  \n`modules` - Reference to store modules. It allows to use other store modules inside module  \n\n\nUsings:  \n\n```js\nimport { StonexModule } from 'stonex'\n\nexport default class AnimalsModule extends StonexModule{\n\n  /* state */\n  state = {}\n\n\n  /* methods */\n\n  createAnimal = (type, name) =\u003e {\n    this.setState({\n      ...this.state,\n      [type]: [\n        ...(this.state[type] || []),\n        { name }\n      ]\n    })\n    return this.state\n  }\n\n  createDog = (name) =\u003e this.createAnimal('dogs', name)\n\n  createCat = (name) =\u003e this.createAnimal('cats', name)\n\n}\n\n```\n\nBesides using `StonexModule` class you can create [Pure Stonex module](./src/StonexModule.ts#L3).  \nIt is a simple object, which works the same as class which has been extended from StonexModule.  \n\nExample:  \n[Pure Stonex Module](./src/StonexModule.ts#L3) implementation of above `AnimalsModule` class  \n```js\nexport default {\n  /* state */\n  state: {},\n  /* methods */\n  createAnimal(type, name) {\n    this.setState({\n      ...this.state,\n      [type]: [\n        ...(this.state[type] || []),\n        { name }\n      ]\n    })\n    return this.state\n  },\n  createDog(name){ return this.createAnimal('dogs', name) },\n  createCat(name){ return this.createAnimal('cats', name) },\n}\n\n```\nNote: all methods should be not arrow functions.\n\n\n\n  \u003chr\u003e\n\n\n\n### `StateWorker`[[Source link]](./src/StateWorker.ts#L33)  \n`import { StateWorker } from 'stonex'`  \n\nThis is a class which do all things linked with state of each module. It provides initializing, updating and reseting state.  \nIf will need to change behaviour of things like `resetState` or `setState` then it can helps you.  \n\nOverridden `State Worker` needs to send where you creating a store:  \n```js\nimport { StonexStore, StateWorker } from 'stonex'\n\n\nclass YourStateWorker extends StateWorker {\n\n  resetState(moduleInstance, callback){\n    console.log(`Resetting state of ${moduleInstance.moduleName} module`)\n    return super.resetState(moduleInstance, callback)\n  }\n}\n\n\nconst store = new StonexStore({\n  key1: StonexModule1,\n  key2: StonexModule2\n}, {\n  stateWorker: YourStateWorker, // HERE\n  modifiers: []\n})\n\n```\n\n\n\n  \u003chr\u003e\n\n\n\n### `createStoreBinder`[[Source link]](./src/StoreBinder.ts#L21)  \n`import { createStoreBinder } from 'stonex'`  \n\nThis function create an [`StoreBinder`](./src/StoreBinder.ts#L7) which needed if you want to change/override behaviour of all things which sends from store and add common methods/properties.  \nFactically its more needed for creating some middleware.  \n\nExample of usage:\n\n```js\n\nimport { createStoreBinder, StateWorker, StonexStore } from 'stonex'\nimport modules, { Modules } from './modules'\nimport Items from './modules/Items'\n\nconst store = new StonexStore(modules)\n\n\nconst modifiedStoreBinder = {\n  ...createStoreBinder('items', store),\n  cacheState: () =\u003e {\n    sessionStorage.setItem('items-cache', JSON.stringify(store.modules.items.state))\n  }\n}\n\nstore.connectModule('items', {\n  module: Items,\n  storeBinder: modifiedStoreBinder\n},)\n\nstore.modules.items.cacheState()\n\n\n```\n\n\u003c!-- And maybe currently you have a question why you need to use that ?  \n\nSometimes in big applications in places where code work with application data gonna need to process data of application --\u003e\n\n\n## 📝 License\n\nLicensed under the [MIT License](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjs2me%2Fstonex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjs2me%2Fstonex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjs2me%2Fstonex/lists"}