{"id":24594284,"url":"https://github.com/freewheel/modulajs","last_synced_at":"2025-03-17T03:08:55.697Z","repository":{"id":57300624,"uuid":"112780225","full_name":"freewheel/modulajs","owner":"freewheel","description":"A modularization framework to manage application states using an immutable model tree","archived":false,"fork":false,"pushed_at":"2024-09-23T09:41:33.000Z","size":1461,"stargazers_count":40,"open_issues_count":2,"forks_count":11,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-03-04T22:30:02.715Z","etag":null,"topics":["application-state","immutable","model","modulajs","modularization","state-management"],"latest_commit_sha":null,"homepage":"https://github.com/freewheel/modulajs","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/freewheel.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2017-12-01T19:46:41.000Z","updated_at":"2024-10-02T19:59:21.000Z","dependencies_parsed_at":"2022-09-10T21:11:08.488Z","dependency_job_id":"7e5ff37d-6286-4d82-8909-857949cda92c","html_url":"https://github.com/freewheel/modulajs","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freewheel%2Fmodulajs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freewheel%2Fmodulajs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freewheel%2Fmodulajs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freewheel%2Fmodulajs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/freewheel","download_url":"https://codeload.github.com/freewheel/modulajs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243965774,"owners_count":20375917,"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":["application-state","immutable","model","modulajs","modularization","state-management"],"created_at":"2025-01-24T11:14:10.312Z","updated_at":"2025-03-17T03:08:55.678Z","avatar_url":"https://github.com/freewheel.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ModulaJS\n\n[![NPM version][npm-image]][npm-url]\n[![Build Status][travis-image]][travis-url]\n[![Coverage Status][coverage-image]][coverage-url]\n[![Node version][node-image]][node-url]\n[![Apache V2 License][apache-2.0]](LICENSE)\n\nModulaJS is created to provide an intuitive and simple way of manage complex state. It introduces Model (an immutable tree) to represent the application state tree. Both actions and reactions are handled inside Model, as well as the communications and side effects. It makes the components in view layer very simple, pure and stateless.\n\nModulaJS works perfectly with [React](https://reactjs.org/), or any other view library, or vanilla JavaScript.\n\n## Influences\n\nModulaJS is inspired by [Elm](http://elm-lang.org/) and [Redux](http://redux.js.org/), and built upon redux. Most redux middlewares and the redux dev tools should work seamlessly with ModulaJS.\n\n## Installation\n\nPrerequisites: Node.js (\u003e=6.0), npm version 3+.\n\n```sh\nyarn add modulajs\n```\n\nOr use NPM\n\n```sh\nnpm install --save modulajs\n```\n\n## Documentation\n\n[Introduction](/docs/modula.md)\n* [Store](/docs/store.md)\n* [Model](/docs/model.md)\n  * [Model Side Effects](/docs/model_side_effects.md)\n  * [Model Communications](/docs/model_communications.md)\n  * [Model Life Cycle](/docs/model_life_cycle.md)\n  * [Model Services](/docs/model_services.md)\n* [Constants](/docs/constants.md)\n* [APIs](/docs/api/README.md)\n  * [Model API](/docs/api/model_api.md)\n  * [Constants API](/docs/api/constants_api.md)\n  * [Test Util API](/docs/api/test_util_api.md)\n\n## Examples\n\nTaking the [*counter example in redux*](https://github.com/reactjs/redux#the-gist), the following code implements a ModulaJS version.\n\nThe whole state is stored in Model tree of the single store, and the ONLY way to mutate a state is dispatching an action in [model sender](/docs/model.md). The receiver, which handles the corresponding reaction, usually appear in pair of the sender, in the same Model class.\n\n```js\n// counter_model.js\nimport { createModel, createConstants } from 'modulajs';\nimport PropTypes from 'prop-types';\n\nexport const ActionTypes = createConstants('COUNTER', {\n  INCREMENT: null,\n  DECREMENT: null\n});\n\nexport const CounterModel = createModel({\n  displayName: 'CounterModel',\n\n  propTypes: {\n    value: PropTypes.number.isRequired\n  },\n\n  defaults: {\n    value: 0\n  },\n\n  sendIncrement() {\n    this.dispatch({ type: ActionTypes.INCREMENT });\n  },\n\n  recvIncrement() {\n    return {\n      type: ActionTypes.INCREMENT,\n      update(model) {\n        const newModel = model.set('value', value =\u003e value + 1);\n\n        return [ newModel ];\n      }\n    };\n  },\n\n  sendDecrement() {\n    if (this.get('value') \u003e 0) {\n      this.dispatch({ type: ActionTypes.DECREMENT });\n    }\n  },\n\n  recvDecrement() {\n    return {\n      type: ActionTypes.DECREMENT,\n      update(model) {\n        const newModel = model.set('value', value =\u003e value - 1);\n\n        return [ newModel ];\n      }\n    };\n  }\n});\n\n// app.js\nimport { createStore } from 'modulajs';\nimport { CounterModel } from './counter_model';\n\n// Create a ModulaJS store to hold state in the decorated model\nconst store = createStore(CounterModel);\n\n// Subscribe to store changing, then notify the listeners\nstore.subscribe(() =\u003e {\n  console.log('Store has changed. The new state is:', store.getState());\n});\n\n// Bootstrap the state tree in root model\nstore.getState().sendInit();\n\n// Dispatch an action with a model instance\n// This is the ONLY way to mutate a state in the Store.\nconst getCounterModel = () =\u003e store.getState().get('decoratedModel');\n\ngetCounterModel().sendIncrement();\ngetCounterModel().get('value'); // 1\n\ngetCounterModel().sendDecrement();\ngetCounterModel().get('value'); // 0\n```\n\n## Contributing\n\nPlease read our [contributing guide](CONTRIBUTING.md) for details on how to contribute to our project.\n\n## License\n\n[Apache-2.0](LICENSE)\n\n[npm-url]: https://www.npmjs.com/package/modulajs\n[npm-image]: https://img.shields.io/npm/v/modulajs.svg\n\n[travis-url]: https://travis-ci.org/freewheel/modulajs\n[travis-image]: https://img.shields.io/travis/freewheel/modulajs/master.svg\n\n[coverage-url]: https://coveralls.io/github/freewheel/modulajs\n[coverage-image]: https://img.shields.io/coveralls/freewheel/modulajs/master.svg\n\n[node-url]: https://nodejs.org\n[node-image]: https://img.shields.io/node/v/modulajs.svg\n\n[apache-2.0]: http://img.shields.io/badge/license-Apache%20V2-blue.svg\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffreewheel%2Fmodulajs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffreewheel%2Fmodulajs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffreewheel%2Fmodulajs/lists"}