{"_id":"@alexstansfield/nestjs-state-machine","_rev":"2-8785aa21079ec35c5cbb03ac58726f84","name":"@alexstansfield/nestjs-state-machine","dist-tags":{"latest":"0.0.4"},"versions":{"0.0.3":{"name":"@alexstansfield/nestjs-state-machine","version":"0.0.3","description":"Finite State Machine for Nestjs framework","author":{"name":"Tomasz Felczyk"},"license":"MIT","url":"https://github.com/depthlabs-io/nestjs-state-machine","main":"./dist/index.js","types":"./dist/index.d.ts","scripts":{"build":"rimraf -rf dist && tsc -p tsconfig.json","dev":"tsc -p tsconfig.json -w","lint":"eslint 'lib/**/*.ts' --fix","prepublish:npm":"npm run build","publish:npm":"npm publish --access public","prepublish:next":"npm run build","publish:next":"npm publish --access public --tag next","test:e2e":"jest --config ./tests/jest-e2e.json --runInBand","prerelease":"npm run build","release":"release-it"},"dependencies":{"@nestjs/event-emitter":"^1.0.0"},"devDependencies":{"@nestjs/common":"8.2.6","@nestjs/core":"8.2.6","@nestjs/platform-express":"8.2.6","@nestjs/testing":"8.2.6","@types/jest":"27.4.0","@types/node":"^14.18.9","@typescript-eslint/eslint-plugin":"5.10.0","@typescript-eslint/parser":"5.10.0","eslint":"8.7.0","eslint-config-prettier":"8.3.0","eslint-plugin-import":"2.25.4","husky":"7.0.4","jest":"27.4.7","lint-staged":"12.2.2","prettier":"2.5.1","reflect-metadata":"0.1.13","release-it":"14.12.3","rimraf":"3.0.2","rxjs":"7.5.2","ts-jest":"27.1.3","typescript":"4.5.5"},"peerDependencies":{"@nestjs/common":"^8.2.0","reflect-metadata":"^0.1.13","rxjs":"^7.5.0"},"lint-staged":{"*.ts":["prettier --write"]},"husky":{"hooks":{"pre-commit":"lint-staged"}},"repository":{"type":"git","url":"git+https://github.com/alexstansfield/nestjs-state-machine.git"},"gitHead":"472dadc66b59711029bcafa34729eb06db38facb","bugs":{"url":"https://github.com/alexstansfield/nestjs-state-machine/issues"},"homepage":"https://github.com/alexstansfield/nestjs-state-machine#readme","_id":"@alexstansfield/nestjs-state-machine@0.0.3","_nodeVersion":"14.18.3","_npmVersion":"6.14.15","dist":{"integrity":"sha512-2nGmipw6AVVDQZJIYaqOocNkH5EeliTOfD6RIuNus2rCjg6JuhDXa/6YGfIIJJ4cBmt2vOJ3k63dXcg5PfaTZg==","shasum":"a1146fdfa28f5d56513079b10a8d642d3327753d","tarball":"https://registry.npmjs.org/@alexstansfield/nestjs-state-machine/-/nestjs-state-machine-0.0.3.tgz","fileCount":73,"unpackedSize":113704,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh67tVCRA9TVsSAnZWagAAX4sP/1Y71fwz4/lUUke0Me3X\nx9uwxBL4ISMAxqFXHQw0VfMD4XnptB70v7E90HpB+0IqDkz+ldb9eSVviLA1\nenae7uS5+/d0YX5CoUWUdO+kv99A0ctVEKEQzVuFNe+wQn9hZhE4730Cra4k\nk60AOzHVQTItzgQE3a+MfmqfYicHNtQrbOqpJrw3rc4fudSIY96JcuboQveq\nqPNfjB4ZdSWnjUzUA+sA2ERj68Ab132GJ5KFZWz5HA8gRhODU7HnDnJQ+YLs\nGOurhv3RPN1g6OauSLRv5F3oqJezFTj9SLNs/BOGigIna9s4GeAAmOFZSSZB\nnFmhF6VV4Otv9s33nu/czc0YoLcH7Yrer4ZKheSxR3+k5Us/54VXcvWQrQwk\nteEPq1RsLd+gBnJBDR7yhTye/K0pmoI/Uzs7a2m5iJLKEVJE0pHKPWGRzfhX\nV0wvVwgqnF77kVfJ/9Yt9wNx3EJEuEQtV5rIeyunPTo1qJNakvMcRKYsiI75\nEC0sTRPxGg6W/L31xCViZd94euPGAR1duda/U2skOKGIaiE2ht0rLRYvW8F/\ni9+E0PVi0mkm8x6sHdxEfep0dbaBpSlq0hACDnCBjc68774FIvM5jTiacDgC\noudpwjjGrnzqif8qyNs+qTRIoENNvjiZXbvf2BLPMK1VtYQksooWUOUxyrYY\nSU5W\r\n=TCBs\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDUoWJhX5mDSYjVA3Ihw1TdTf+XGs0vIfx16A2A6KeSfAiBvZnzbyWZauH1Mn8zS28lhX/6pRoukmZ4iuaYUTthahg=="}]},"_npmUser":{"name":"alexstansfield","email":"alex.stansfield@gmail.com"},"directories":{},"maintainers":[{"name":"alexstansfield","email":"alex.stansfield@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/nestjs-state-machine_0.0.3_1642838869609_0.3666889289316646"},"_hasShrinkwrap":false},"0.0.4":{"name":"@alexstansfield/nestjs-state-machine","version":"0.0.4","description":"Finite State Machine for Nestjs framework","author":{"name":"Tomasz Felczyk"},"license":"MIT","url":"https://github.com/depthlabs-io/nestjs-state-machine","main":"./dist/index.js","types":"./dist/index.d.ts","scripts":{"build":"rimraf -rf dist && tsc -p tsconfig.json","dev":"tsc -p tsconfig.json -w","lint":"eslint 'lib/**/*.ts' --fix","prepublish:npm":"npm run build","publish:npm":"npm publish --access public","prepublish:next":"npm run build","publish:next":"npm publish --access public --tag next","test:e2e":"jest --config ./tests/jest-e2e.json --runInBand","prerelease":"npm run build","release":"release-it"},"dependencies":{"@nestjs/event-emitter":"^1.0.0"},"devDependencies":{"@nestjs/common":"8.2.6","@nestjs/core":"8.2.6","@nestjs/platform-express":"8.2.6","@nestjs/testing":"8.2.6","@types/jest":"27.4.0","@types/node":"^14.18.9","@typescript-eslint/eslint-plugin":"5.10.0","@typescript-eslint/parser":"5.10.0","eslint":"8.7.0","eslint-config-prettier":"8.3.0","eslint-plugin-import":"2.25.4","husky":"7.0.4","jest":"27.4.7","lint-staged":"12.2.2","prettier":"2.5.1","reflect-metadata":"0.1.13","release-it":"14.12.3","rimraf":"3.0.2","rxjs":"7.5.2","ts-jest":"27.1.3","typescript":"4.5.5"},"peerDependencies":{"@nestjs/common":"^8.2.0","reflect-metadata":"^0.1.13","rxjs":"^7.5.0"},"lint-staged":{"*.ts":["prettier --write"]},"husky":{"hooks":{"pre-commit":"lint-staged"}},"repository":{"type":"git","url":"git+https://github.com/alexstansfield/nestjs-state-machine.git"},"gitHead":"ac7bb71ee5ece1e54b3c101856a89ec1d4281c78","bugs":{"url":"https://github.com/alexstansfield/nestjs-state-machine/issues"},"homepage":"https://github.com/alexstansfield/nestjs-state-machine#readme","_id":"@alexstansfield/nestjs-state-machine@0.0.4","_nodeVersion":"14.18.3","_npmVersion":"6.14.15","dist":{"integrity":"sha512-mgBFytUQ/4nfIp8QKvWFu+gt49iUCnsGkxeY+hsZJQpt0AZ5VU+ucDj5KxcTYXqeLOKOWVTvZ2gQYvaORX4QMw==","shasum":"3f9286e4e73a5610b593732299ddcbf48daba7d9","tarball":"https://registry.npmjs.org/@alexstansfield/nestjs-state-machine/-/nestjs-state-machine-0.0.4.tgz","fileCount":73,"unpackedSize":114319,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh7ArDCRA9TVsSAnZWagAAlI8QAIYwVkdbBSy3rZs14/nj\nll8xxHn+zxFaPvROyRff3CX2x0kZR+rGsxk/lMLk4io0aT8PXkqDB+glNMrP\nPPULd5klRNIWCsPCFBfx7oZnNPMwt73QcQ24GVWnDW/HjJdTxglknDPInedX\n/0YV76syATO4SuCYYmAmLLb94Kv42Q8qYePegcOTktciEepQ2cVlqIrnkkxS\noW2+ok2mWeX89XkIvzhCWynyRWDv8IWx7c09P56GooNPVh10ucuWRa5Fdict\nlrAhXEhFuoXJjtRDUlpMt3DPjhzl828e/jeN3YKdbM2VSbzYlszUA71BiTZd\nFBrdRRsuQacrbKN3PwJM0EcghaE7plXJSHx39kgqUZDmsQIOWIayvi0ghVpw\nH1I5OTFUpOBUZ4x6lWXbRj4ycFGElavEpLoFPob/j3SgiTdu5iOOXy90weBP\nEcKcyXFjfka0gubUV/P9Lznb5UeJXVdMIgBUloP0jERae0h0Kwx7TRxkTiLk\nzdVRd0+vv9E6kWP3ojhyn2ze0mUfxihHAqm3X1pRwfGf3YGSuzQFNUdhwyvP\nQrGTLhb9ma6exAeyklYQ1onRxiVl7nO+z/Nk/l4TMoOLtGocKjqzw/l5rVYL\n8nUDOYV3J7zYngf0b85JZcgTQnSTJdw+JSUEOREvwvOPMQQlLcXKRxrtrjAn\nIqQz\r\n=cHhA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEzg8TcsutROSzuVKxS8fJPSBRdEbBXRYOMw/MfQEAzrAiEAwe0+vod1aC4DyMPofoBWO8wZCyD13IVg8DzugVu+cIA="}]},"_npmUser":{"name":"alexstansfield","email":"alex.stansfield@gmail.com"},"directories":{},"maintainers":[{"name":"alexstansfield","email":"alex.stansfield@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/nestjs-state-machine_0.0.4_1642859203808_0.8543438647747612"},"_hasShrinkwrap":false}},"time":{"created":"2022-01-22T08:07:49.547Z","0.0.3":"2022-01-22T08:07:49.808Z","modified":"2022-04-04T12:41:48.328Z","0.0.4":"2022-01-22T13:46:43.986Z"},"maintainers":[{"name":"alexstansfield","email":"alex.stansfield@gmail.com"}],"description":"Finite State Machine for Nestjs framework","homepage":"https://github.com/alexstansfield/nestjs-state-machine#readme","repository":{"type":"git","url":"git+https://github.com/alexstansfield/nestjs-state-machine.git"},"author":{"name":"Tomasz Felczyk"},"bugs":{"url":"https://github.com/alexstansfield/nestjs-state-machine/issues"},"license":"MIT","readme":"## Description\n\nFinite State Machine module for [Nest](https://github.com/nestjs/nest).\n\n## Getting started\n\nInstall package:\n```bash\n$ npm i --save @depthlabs/nestjs-state-machine\n```\n\nFor example, we will map the following state machine:\n\n![example state machine](https://github.com/depthlabs-io/nestjs-state-machine/blob/main/example.jpg?raw=true)\n\n\nAfter installation, import StateMachineModule into your root module with state machine graph configurations:\n```typescript\n// app.module.ts\nimport { StateMachineModule } from '@depthlabs/nestjs-state-machine';\n\n@Module({\n  imports: [\n    // .forRoot takes array of graph configurations\n    StateMachineModule.forRoot([\n        {\n            // Name of graph\n            name: 'project-graph',\n            // Initial state of graph\n            initialState: 'new',\n            // Available states in graph\n            states: [\n                'new',\n                'in-progress',\n                'done'\n            ],\n            // Available transitions in graph\n            transitions: [\n                {\n                    // Name of transistion\n                    name: 'start',\n                    // Source states\n                    from: ['new'],\n                    // Target state of transition\n                    to: 'in-progress',\n                },\n                {\n                    name: 'finish',\n                    from: ['in-progress'],\n                    to: 'done',\n                }\n            ],\n        },\n    ]),\n  ]\n})\nexport class AppModule {}\n```\n\nIt's good idea to define graph, state and transition names in one place e.g.:\n```typescript\n// constants.ts\nexport const PROJECT_GRAPH = 'project-graph'\n\nexport enum ProjectState {\n    NEW = 'new',\n    IN_PROGRESS = 'in-progress',\n    DONE = 'done'\n}\n\nexport enum ProjectTransition {\n    START = 'start',\n    FINISH = 'finish'\n}\n\n```\n\nand then:\n\n```typescript\nimport { StateMachineModule } from '@depthlabs/nestjs-state-machine';\nimport { PROJECT_GRAPH, ProjectState, ProjectTransition } from './constants';\n\n// ...\n\nStateMachineModule.forRoot([\n    {\n        name: PROJECT_GRAPH,\n        initialState: ProjectState.NEW,\n        states: [\n            ProjectState.NEW,\n            ProjectState.IN_PROGRESS,\n            ProjectState.DONE\n        ],\n        transitions: [\n            {\n                name: ProjectTransition.START,\n                from: [ProjectState.NEW],\n                to: ProjectState.IN_PROGRESS,\n            },\n            {\n                name: ProjectTransition.FINISH,\n                from: [ProjectState.IN_PROGRESS],\n                to: ProjectState.DONE,\n            }\n        ],\n    }\n]);\n```\n\nNext, create model or use your exisiting model and decorate property which will be responsible for storing state of model:\n```typescript\n// project.model.ts\nimport { StateStore } from '@depthlabs/nestjs-state-machine';\nimport { PROJECT_GRAPH, ProjectState } from './constants';\n\nexport class Project {\n    name: string;\n\n    @StateStore(PROJECT_GRAPH)\n    state: string = ProjectState.NEW;\n\n}\n```\n`@StateStore` takes one argument with graph name (string). Thanks to this one model can handle more then many graphs: \n```typescript\n@StateStore(PROJECT_GRAPH)\nstate: string = ProjectState.NEW;\n\n@StateStore(PROJECT_STATUS_GRAPH)\nstatus: string = ProjectStatusState.ACTIVE;\n```\n\nAt this point we can create our state machine. First inject `StateMachineFactory` using standard constructor injection:\n\n\n```typescript\nimport { StateMachineFactory } from '@depthlabs/nestjs-state-machine';\n\n// ...\n\nconstructor(\n    private readonly stateMachineFactory: StateMachineFactory,\n) {}\n```\n\nCreate state machine with instance of `Project` model as subject in first argument of factory and with graph name in second.\n```typescript\nconst projectStateMachine = this.stateMachineFactory.create<Project>(project, PROJECT_GRAPH)\n```\n    \n## State Machine methods\n\nApply transition:\n```typescript\n// takes transition name in argument\nawait projectStateMachine.apply(ProjectTransition.START)\n// return void but project.state is now equal ProjectState.IN_PROGRESS\n```\n\nCheck if transition is possible:\n```typescript\n// takes transition name in argument\nawait projectStateMachine.can(ProjectTransition.START)\n// return true or false, can() don't throw Errors\n```\n\nGet all possible transitions:\n```typescript\nawait projectStateMachine.getAvailableTransitions()\n// return TransitionInterface[];\n```\n    \n## Guards\n\nYou can create guards to block transitions.  \nTo declare an `Guard`, decorate a method with the `@OnGuard()` decorator:\n\n```typescript\nimport { GuardEvent, OnGuard } from '@depthlabs/nestjs-state-machine';\nimport { ProjectTransition, PROJECT_GRAPH } from '../constance';\nimport { Project } from '../project.model';\n\nexport class ProjectCantBeNamedBlockmeGuard {\n\n    // Graph name in first argument, transition name in second\n    @OnGuard(PROJECT_GRAPH, ProjectTransition.START)\n    handle(event: GuardEvent<Project>) {\n        // event.subject is our Project instance\n        if (event.subject.name == 'blockme') { // if name isn't allowed for some reasons\n            event.setBlocked('transition-blocked'); // block transition using setBlocked() method\n        }\n    }\n\n}\n```\nThan you need to register `ProjectCantBeNamedBlockmeGuard` in module as provider:\n```typescript\n@Module({\n    imports: [\n        StateMachineModule.forRoot([\n            // ...\n        ])\n    ],\n    providers: [\n        ProjectCantBeNamedBlockmeGuard\n    ],\n})\nexport class AppModule {}\n```\n\nNow, if you create `StateMachine` instance and try to apply `START` transition you will get:\n```typescript\nconst project = new Project()\nproject.name = 'blockme'\n\nconst projectStateMachine = this.stateMachineFactory.create<Project>(project, PROJECT_GRAPH);\n\nawait projectStateMachine.can(ProjectTransition.START)\n// false\n\nawait projectStateMachine.apply(ProjectTransition.START)\n// Throw TransitionBlockedByGuardException with .blockingReasons property that contain ['transition-blocked']\n\nprojectStateMachine.getAvailableTransitions()\n// [] - empty\n```\n\n## Transition Events\n\nYou can create transition event listeners to do additional actions when a state machine operation happened (e.g. sending emails, recalculate)\n\nWhen a state transition is initiated, the events are dispatched in the following order:  \n\n| Order | Event | Decorator | Decorator second argument |\n|-|-|-|-|\n| 1 | LeaveState<br><small><small>(The subject is about to leave a place). | OnLeaveState | State name |\n| 2 | BeginTransition<br><small>(The subject is going through this transition.)</small> | OnBeginTransition | Transition name |\n| 3 | EnterState<br><small>(The subject is about to enter a new place. This event is triggered right before the subject places are updated.)</small> | OnEnterState | State name |\n| 4 | -> Change of state \n| 5 | EnteredState<br><small>(The subject has entered in the places and the marking is updated.)</small> | OnEnteredState | State name |\n| 6 | CompletedTransition<br><small>(The object has completed this transition.)</small> | OnCompletedTransition | Transition name |\n| 7 | AnnounceTransitions<br><small>(Triggered for each transition that now is accessible for the subject.)</small> | OnAnnounceTransitions | State name |\n\n\nExample:\n```typescript\nimport { OnCompletedTransition, CompletedTransitionEvent } from '@depthlabs/nestjs-state-machine';\nimport { ProjectTransition, PROJECT_GRAPH } from '../constance';\nimport { Project } from '../project.model';\n\nexport class NotifyTeamAboutFinishedTask {\n\n    // Graph name in first argument, transition name in second. Third if truem method is async.\n    @OnCompletedTransition(PROJECT_GRAPH, ProjectTransition.FINISH, true)\n    async handle(event: CompletedTransitionEvent<Project>) {\n        // Send emails to all users in team\n    }\n\n}\n```\nand of course:\n```typescript\n@Module({\n    // ...\n    providers: [\n        NotifyTeamAboutFinishedTask\n    ],\n    // ...\n})\nexport class AppModule {}\n```\n\n\n## License\n\nNestjs State Machine is [MIT licensed](LICENSE).","readmeFilename":"README.md"}