@wooksjs/event-wf 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -0
- package/dist/index.cjs +188 -0
- package/dist/index.d.ts +151 -0
- package/dist/index.mjs +180 -0
- package/package.json +39 -0
package/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# @wooksjs/event-wf
|
|
2
|
+
|
|
3
|
+
**!!! This is work-in-progress library, breaking changes are expected !!!**
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<img src="../../wooks-logo.png" width="450px"><br>
|
|
7
|
+
<a href="https://github.com/wooksjs/wooksjs/blob/main/LICENSE">
|
|
8
|
+
<img src="https://img.shields.io/badge/License-MIT-green?style=for-the-badge" />
|
|
9
|
+
</a>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
The `@wooksjs/event-wf` is a component of the `wooks` event processing framework built on top of [@prostojs/wf](https://github.com/prostojs/wf). It provides a way to manage complex workflows and processes using the underlying workflow engine.
|
|
13
|
+
|
|
14
|
+
The primary features of `@wooksjs/event-wf` include:
|
|
15
|
+
|
|
16
|
+
- Support for conditional workflow branching based on dynamic conditions.
|
|
17
|
+
- Support for parametric steps and workflows.
|
|
18
|
+
- Support for user input requirements and interaction during the workflows.
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
To install `@wooksjs/event-wf`, you can use npm:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
npm install wooks @wooksjs/event-wf
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```js
|
|
31
|
+
import { useRouteParams } from '@wooksjs/event-core'
|
|
32
|
+
import { createWfApp } from '@wooksjs/event-wf'
|
|
33
|
+
|
|
34
|
+
const app = createWfApp<{ result: number }>()
|
|
35
|
+
|
|
36
|
+
app.step('add', {
|
|
37
|
+
input: 'number',
|
|
38
|
+
handler: 'ctx.result += input',
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
app.step('add/:n', {
|
|
42
|
+
handler: (ctx) => {
|
|
43
|
+
ctx.result += Number(useRouteParams().get('n'))
|
|
44
|
+
},
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
app.flow('adding', [
|
|
48
|
+
{ id: 'add', input: 5 },
|
|
49
|
+
{ id: 'add', input: 2 },
|
|
50
|
+
{
|
|
51
|
+
condition: 'result < 10',
|
|
52
|
+
steps: [{ id: 'add', input: 3 }, { id: 'add', input: 4 }],
|
|
53
|
+
},
|
|
54
|
+
])
|
|
55
|
+
|
|
56
|
+
app.flow('adding-parametric', [
|
|
57
|
+
'add/5',
|
|
58
|
+
'add/2',
|
|
59
|
+
{
|
|
60
|
+
condition: 'result < 10',
|
|
61
|
+
steps: ['add/3', 'add/4'],
|
|
62
|
+
},
|
|
63
|
+
])
|
|
64
|
+
|
|
65
|
+
app.run()
|
|
66
|
+
|
|
67
|
+
// Run the 'adding' workflow
|
|
68
|
+
app.start('adding', { result: 0 })
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Documentation
|
|
72
|
+
|
|
73
|
+
For more detailed documentation, please visit [wooks.moost.org](https://wooks.moost.org/wfapp/).
|
|
74
|
+
|
|
75
|
+
## Contributing
|
|
76
|
+
|
|
77
|
+
Contributions to the `@wooksjs/event-wf` project are welcome. If you find any bugs or have a feature request, please open an issue on [the GitHub repository](https://github.com/wooksjs/wooksjs).
|
|
78
|
+
|
|
79
|
+
## License
|
|
80
|
+
|
|
81
|
+
`@wooksjs/event-wf` is licensed under the [MIT license](https://github.com/wooksjs/wooksjs/blob/main/LICENSE).
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var eventCore = require('@wooksjs/event-core');
|
|
4
|
+
var wooks = require('wooks');
|
|
5
|
+
var wf = require('@prostojs/wf');
|
|
6
|
+
|
|
7
|
+
function createWfContext(data, options) {
|
|
8
|
+
return eventCore.createEventContext({
|
|
9
|
+
event: Object.assign(Object.assign({}, data), { type: 'WF' }),
|
|
10
|
+
resume: false,
|
|
11
|
+
options,
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
function resumeWfContext(data, options) {
|
|
15
|
+
return eventCore.createEventContext({
|
|
16
|
+
event: Object.assign(Object.assign({}, data), { type: 'WF' }),
|
|
17
|
+
resume: true,
|
|
18
|
+
options,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Wrapper on top of useEventContext that provides
|
|
23
|
+
* proper context types for WF event
|
|
24
|
+
* @returns set of hooks { getCtx, restoreCtx, clearCtx, hookStore, getStore, setStore }
|
|
25
|
+
*/
|
|
26
|
+
function useWFContext() {
|
|
27
|
+
return eventCore.useEventContext('CLI');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/******************************************************************************
|
|
31
|
+
Copyright (c) Microsoft Corporation.
|
|
32
|
+
|
|
33
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
34
|
+
purpose with or without fee is hereby granted.
|
|
35
|
+
|
|
36
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
37
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
38
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
39
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
40
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
41
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
42
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
43
|
+
***************************************************************************** */
|
|
44
|
+
/* global Reflect, Promise */
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
48
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
49
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
50
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
51
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
52
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
53
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
class WooksWorkflow extends wf.Workflow {
|
|
58
|
+
constructor(wooks) {
|
|
59
|
+
super([]);
|
|
60
|
+
this.wooks = wooks;
|
|
61
|
+
}
|
|
62
|
+
resolveStep(stepId) {
|
|
63
|
+
var _a, _b, _c;
|
|
64
|
+
try {
|
|
65
|
+
useWFContext();
|
|
66
|
+
const found = this.wooks.lookup('WF_STEP', '/' + stepId);
|
|
67
|
+
if ((_a = found === null || found === void 0 ? void 0 : found.handlers) === null || _a === void 0 ? void 0 : _a.length) {
|
|
68
|
+
return found.handlers[0]();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
const router = this.wooks.getRouter();
|
|
73
|
+
const found = router.lookup('WF_STEP', '/' + stepId);
|
|
74
|
+
if ((_c = (_b = found === null || found === void 0 ? void 0 : found.route) === null || _b === void 0 ? void 0 : _b.handlers) === null || _c === void 0 ? void 0 : _c.length) {
|
|
75
|
+
return found.route.handlers[0]();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
throw new Error(`Step "${stepId}" not found.`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const wfShortcuts = {
|
|
83
|
+
flow: 'WF_FLOW',
|
|
84
|
+
step: 'WF_STEP',
|
|
85
|
+
};
|
|
86
|
+
class WooksWf extends wooks.WooksAdapterBase {
|
|
87
|
+
constructor(opts, wooks) {
|
|
88
|
+
super(wooks, opts === null || opts === void 0 ? void 0 : opts.logger, opts === null || opts === void 0 ? void 0 : opts.router);
|
|
89
|
+
this.opts = opts;
|
|
90
|
+
this.logger = (opts === null || opts === void 0 ? void 0 : opts.logger) || this.getLogger('wooks-wf');
|
|
91
|
+
this.wf = new WooksWorkflow(this.wooks);
|
|
92
|
+
}
|
|
93
|
+
step(id, opts) {
|
|
94
|
+
const step = wf.createStep(id, opts);
|
|
95
|
+
return this.on('WF_STEP', id, () => step);
|
|
96
|
+
}
|
|
97
|
+
flow(id, schema) {
|
|
98
|
+
this.wf.register(id, schema);
|
|
99
|
+
return this.on('WF_FLOW', id, () => id);
|
|
100
|
+
}
|
|
101
|
+
start(schemaId, inputContext, input) {
|
|
102
|
+
return this._start(schemaId, inputContext, undefined, input);
|
|
103
|
+
}
|
|
104
|
+
resume(schemaId, inputContext, indexes, input) {
|
|
105
|
+
return this._start(schemaId, inputContext, indexes, input);
|
|
106
|
+
}
|
|
107
|
+
_start(schemaId, inputContext, indexes, input) {
|
|
108
|
+
var _a, _b;
|
|
109
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
110
|
+
const resume = !!(indexes === null || indexes === void 0 ? void 0 : indexes.length);
|
|
111
|
+
const { restoreCtx, clearCtx } = (resume ? resumeWfContext : createWfContext)({
|
|
112
|
+
inputContext,
|
|
113
|
+
schemaId,
|
|
114
|
+
indexes,
|
|
115
|
+
input,
|
|
116
|
+
}, this.mergeEventOptions((_a = this.opts) === null || _a === void 0 ? void 0 : _a.eventOptions));
|
|
117
|
+
const { handlers: foundHandlers } = this.wooks.lookup('WF_FLOW', '/' + schemaId);
|
|
118
|
+
const handlers = foundHandlers ||
|
|
119
|
+
(((_b = this.opts) === null || _b === void 0 ? void 0 : _b.onNotFound) && [this.opts.onNotFound]) ||
|
|
120
|
+
null;
|
|
121
|
+
if (handlers && handlers.length) {
|
|
122
|
+
let result = {};
|
|
123
|
+
for (const handler of handlers) {
|
|
124
|
+
restoreCtx();
|
|
125
|
+
const schemaId = (yield handler());
|
|
126
|
+
if (resume) {
|
|
127
|
+
result = yield this.wf.resume(schemaId, { context: inputContext, indexes }, input);
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
result = yield this.wf.start(schemaId, inputContext, input);
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
clearCtx();
|
|
136
|
+
return result;
|
|
137
|
+
}
|
|
138
|
+
clearCtx();
|
|
139
|
+
throw new Error('Unknown schemaId: ' + schemaId);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
onError(e) {
|
|
143
|
+
var _a;
|
|
144
|
+
if ((_a = this.opts) === null || _a === void 0 ? void 0 : _a.onError) {
|
|
145
|
+
this.opts.onError(e);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
this.error(e.message);
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
error(e) {
|
|
153
|
+
if (typeof e === 'string') {
|
|
154
|
+
console.error('[31m' + 'ERROR: ' + '[0m' + e);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
console.error('[31m' + 'ERROR: ' + '[0m' + e.message);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Factory for WooksWf App
|
|
163
|
+
* @param opts TWooksWfOptions
|
|
164
|
+
* @param wooks Wooks | WooksAdapterBase
|
|
165
|
+
* @returns WooksWf
|
|
166
|
+
*/
|
|
167
|
+
function createWfApp(opts, wooks) {
|
|
168
|
+
return new WooksWf(opts, wooks);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function useWfState() {
|
|
172
|
+
const { store } = useWFContext();
|
|
173
|
+
const event = store('event');
|
|
174
|
+
return {
|
|
175
|
+
ctx: () => event.get('inputContext'),
|
|
176
|
+
input: () => event.get('input'),
|
|
177
|
+
schemaId: event.get('schemaId'),
|
|
178
|
+
indexes: () => event.get('indexes'),
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
exports.WooksWf = WooksWf;
|
|
183
|
+
exports.createWfApp = createWfApp;
|
|
184
|
+
exports.createWfContext = createWfContext;
|
|
185
|
+
exports.resumeWfContext = resumeWfContext;
|
|
186
|
+
exports.useWFContext = useWFContext;
|
|
187
|
+
exports.useWfState = useWfState;
|
|
188
|
+
exports.wfShortcuts = wfShortcuts;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { Step } from '@prostojs/wf';
|
|
2
|
+
import { TConsoleBase } from '@prostojs/logger';
|
|
3
|
+
import { TEmpty } from '@wooksjs/event-core';
|
|
4
|
+
import { TEventOptions } from '@wooksjs/event-core';
|
|
5
|
+
import { TFlowOutput } from '@prostojs/wf';
|
|
6
|
+
import { TGenericContextStore } from '@wooksjs/event-core';
|
|
7
|
+
import { TProstoRouterPathHandle } from '@prostojs/router';
|
|
8
|
+
import { TStepHandler } from '@prostojs/wf';
|
|
9
|
+
import { TWooksHandler } from 'wooks';
|
|
10
|
+
import { TWooksOptions } from 'wooks';
|
|
11
|
+
import { TWorkflowSchema } from '@prostojs/wf';
|
|
12
|
+
import { Wooks } from 'wooks';
|
|
13
|
+
import { WooksAdapterBase } from 'wooks';
|
|
14
|
+
import { Workflow } from '@prostojs/wf';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Factory for WooksWf App
|
|
18
|
+
* @param opts TWooksWfOptions
|
|
19
|
+
* @param wooks Wooks | WooksAdapterBase
|
|
20
|
+
* @returns WooksWf
|
|
21
|
+
*/
|
|
22
|
+
export declare function createWfApp<T>(opts?: TWooksWfOptions, wooks?: Wooks | WooksAdapterBase): WooksWf<T>;
|
|
23
|
+
|
|
24
|
+
export declare function createWfContext(data: Omit<TWFEventData, 'type'>, options: TEventOptions): {
|
|
25
|
+
getCtx: () => TWFContextStore & TGenericContextStore<TWFEventData>;
|
|
26
|
+
restoreCtx: () => TGenericContextStore<TEmpty>;
|
|
27
|
+
clearCtx: () => null;
|
|
28
|
+
store: <K extends "resume" | keyof TGenericContextStore<TWFEventData>>(key: K) => {
|
|
29
|
+
value: (TWFContextStore & TGenericContextStore<TWFEventData>)[K];
|
|
30
|
+
hook: <K2 extends keyof Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K]>(key2: K2) => {
|
|
31
|
+
value: Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K][K2];
|
|
32
|
+
isDefined: boolean;
|
|
33
|
+
};
|
|
34
|
+
init: <K2_1 extends keyof Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K]>(key2: K2_1, getter: () => Required<Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K]>[K2_1]) => Required<Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K]>[K2_1];
|
|
35
|
+
set: <K2_2 extends keyof Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K]>(key2: K2_2, v: Required<(TWFContextStore & TGenericContextStore<TWFEventData>)[K]>[K2_2]) => Required<(TWFContextStore & TGenericContextStore<TWFEventData>)[K]>[K2_2];
|
|
36
|
+
get: <K2_3 extends keyof Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K]>(key2: K2_3) => Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K][K2_3];
|
|
37
|
+
has: <K2_4 extends keyof Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K]>(key2: K2_4) => boolean;
|
|
38
|
+
del: <K2_5 extends keyof Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K]>(key2: K2_5) => void;
|
|
39
|
+
entries: () => [string, unknown][];
|
|
40
|
+
clear: () => void;
|
|
41
|
+
};
|
|
42
|
+
getStore: <K_1 extends "resume" | keyof TGenericContextStore<TWFEventData>>(key: K_1) => (TWFContextStore & TGenericContextStore<TWFEventData>)[K_1];
|
|
43
|
+
setStore: <K_2 extends "resume" | keyof TGenericContextStore<TWFEventData>>(key: K_2, v: (TWFContextStore & TGenericContextStore<TWFEventData>)[K_2]) => void;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export declare function resumeWfContext(data: Omit<TWFEventData, 'type'>, options: TEventOptions): {
|
|
47
|
+
getCtx: () => TWFContextStore & TGenericContextStore<TWFEventData>;
|
|
48
|
+
restoreCtx: () => TGenericContextStore<TEmpty>;
|
|
49
|
+
clearCtx: () => null;
|
|
50
|
+
store: <K extends "resume" | keyof TGenericContextStore<TWFEventData>>(key: K) => {
|
|
51
|
+
value: (TWFContextStore & TGenericContextStore<TWFEventData>)[K];
|
|
52
|
+
hook: <K2 extends keyof Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K]>(key2: K2) => {
|
|
53
|
+
value: Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K][K2];
|
|
54
|
+
isDefined: boolean;
|
|
55
|
+
};
|
|
56
|
+
init: <K2_1 extends keyof Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K]>(key2: K2_1, getter: () => Required<Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K]>[K2_1]) => Required<Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K]>[K2_1];
|
|
57
|
+
set: <K2_2 extends keyof Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K]>(key2: K2_2, v: Required<(TWFContextStore & TGenericContextStore<TWFEventData>)[K]>[K2_2]) => Required<(TWFContextStore & TGenericContextStore<TWFEventData>)[K]>[K2_2];
|
|
58
|
+
get: <K2_3 extends keyof Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K]>(key2: K2_3) => Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K][K2_3];
|
|
59
|
+
has: <K2_4 extends keyof Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K]>(key2: K2_4) => boolean;
|
|
60
|
+
del: <K2_5 extends keyof Required<TWFContextStore & TGenericContextStore<TWFEventData>>[K]>(key2: K2_5) => void;
|
|
61
|
+
entries: () => [string, unknown][];
|
|
62
|
+
clear: () => void;
|
|
63
|
+
};
|
|
64
|
+
getStore: <K_1 extends "resume" | keyof TGenericContextStore<TWFEventData>>(key: K_1) => (TWFContextStore & TGenericContextStore<TWFEventData>)[K_1];
|
|
65
|
+
setStore: <K_2 extends "resume" | keyof TGenericContextStore<TWFEventData>>(key: K_2, v: (TWFContextStore & TGenericContextStore<TWFEventData>)[K_2]) => void;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export declare interface TWFContextStore {
|
|
69
|
+
resume: boolean;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export declare interface TWFEventData {
|
|
73
|
+
schemaId: string;
|
|
74
|
+
inputContext: unknown;
|
|
75
|
+
indexes?: number[];
|
|
76
|
+
input?: unknown;
|
|
77
|
+
type: 'WF';
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export declare interface TWooksWfOptions {
|
|
81
|
+
onError?(e: Error): void;
|
|
82
|
+
onNotFound?: TWooksHandler<unknown>;
|
|
83
|
+
onUnknownFlow?: (schemaId: string, raiseError: () => void) => unknown;
|
|
84
|
+
logger?: TConsoleBase;
|
|
85
|
+
eventOptions?: TEventOptions;
|
|
86
|
+
router?: TWooksOptions['router'];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Wrapper on top of useEventContext that provides
|
|
91
|
+
* proper context types for WF event
|
|
92
|
+
* @returns set of hooks { getCtx, restoreCtx, clearCtx, hookStore, getStore, setStore }
|
|
93
|
+
*/
|
|
94
|
+
export declare function useWFContext<T extends TEmpty>(): {
|
|
95
|
+
getCtx: () => TWFContextStore & T & TGenericContextStore<TWFEventData>;
|
|
96
|
+
restoreCtx: () => TGenericContextStore<TEmpty>;
|
|
97
|
+
clearCtx: () => null;
|
|
98
|
+
store: <K extends "resume" | keyof TGenericContextStore<TWFEventData> | keyof T>(key: K) => {
|
|
99
|
+
value: (TWFContextStore & T & TGenericContextStore<TWFEventData>)[K];
|
|
100
|
+
hook: <K2 extends keyof Required<TWFContextStore & T & TGenericContextStore<TWFEventData>>[K]>(key2: K2) => {
|
|
101
|
+
value: Required<TWFContextStore & T & TGenericContextStore<TWFEventData>>[K][K2];
|
|
102
|
+
isDefined: boolean;
|
|
103
|
+
};
|
|
104
|
+
init: <K2_1 extends keyof Required<TWFContextStore & T & TGenericContextStore<TWFEventData>>[K]>(key2: K2_1, getter: () => Required<Required<TWFContextStore & T & TGenericContextStore<TWFEventData>>[K]>[K2_1]) => Required<Required<TWFContextStore & T & TGenericContextStore<TWFEventData>>[K]>[K2_1];
|
|
105
|
+
set: <K2_2 extends keyof Required<TWFContextStore & T & TGenericContextStore<TWFEventData>>[K]>(key2: K2_2, v: Required<(TWFContextStore & T & TGenericContextStore<TWFEventData>)[K]>[K2_2]) => Required<(TWFContextStore & T & TGenericContextStore<TWFEventData>)[K]>[K2_2];
|
|
106
|
+
get: <K2_3 extends keyof Required<TWFContextStore & T & TGenericContextStore<TWFEventData>>[K]>(key2: K2_3) => Required<TWFContextStore & T & TGenericContextStore<TWFEventData>>[K][K2_3];
|
|
107
|
+
has: <K2_4 extends keyof Required<TWFContextStore & T & TGenericContextStore<TWFEventData>>[K]>(key2: K2_4) => boolean;
|
|
108
|
+
del: <K2_5 extends keyof Required<TWFContextStore & T & TGenericContextStore<TWFEventData>>[K]>(key2: K2_5) => void;
|
|
109
|
+
entries: () => [string, unknown][];
|
|
110
|
+
clear: () => void;
|
|
111
|
+
};
|
|
112
|
+
getStore: <K_1 extends "resume" | keyof TGenericContextStore<TWFEventData> | keyof T>(key: K_1) => (TWFContextStore & T & TGenericContextStore<TWFEventData>)[K_1];
|
|
113
|
+
setStore: <K_2 extends "resume" | keyof TGenericContextStore<TWFEventData> | keyof T>(key: K_2, v: (TWFContextStore & T & TGenericContextStore<TWFEventData>)[K_2]) => void;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export declare function useWfState(): {
|
|
117
|
+
ctx: <T>() => T;
|
|
118
|
+
input: <I>() => I | undefined;
|
|
119
|
+
schemaId: string;
|
|
120
|
+
indexes: () => number[] | undefined;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export declare const wfShortcuts: {
|
|
124
|
+
flow: string;
|
|
125
|
+
step: string;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export declare class WooksWf<T> extends WooksAdapterBase {
|
|
129
|
+
protected opts?: TWooksWfOptions | undefined;
|
|
130
|
+
protected logger: TConsoleBase;
|
|
131
|
+
protected wf: WooksWorkflow<T>;
|
|
132
|
+
constructor(opts?: TWooksWfOptions | undefined, wooks?: Wooks | WooksAdapterBase);
|
|
133
|
+
step<I = any, D = any>(id: string, opts: {
|
|
134
|
+
input?: D;
|
|
135
|
+
handler: string | TStepHandler<T, I, D>;
|
|
136
|
+
}): TProstoRouterPathHandle<Record<string, string | string[]>>;
|
|
137
|
+
flow(id: string, schema: TWorkflowSchema<T>): TProstoRouterPathHandle<Record<string, string | string[]>>;
|
|
138
|
+
start<I>(schemaId: string, inputContext: T, input?: I): Promise<TFlowOutput<T, I>>;
|
|
139
|
+
resume<I>(schemaId: string, inputContext: T, indexes: number[], input?: I): Promise<TFlowOutput<T, I>>;
|
|
140
|
+
protected _start<I>(schemaId: string, inputContext: T, indexes?: number[], input?: I): Promise<TFlowOutput<T, I>>;
|
|
141
|
+
protected onError(e: Error): void;
|
|
142
|
+
protected error(e: string | Error): void;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
declare class WooksWorkflow<T> extends Workflow<T> {
|
|
146
|
+
protected wooks: Wooks;
|
|
147
|
+
constructor(wooks: Wooks);
|
|
148
|
+
protected resolveStep<I, D>(stepId: string): Step<T, I, D>;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export { }
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { createEventContext, useEventContext } from '@wooksjs/event-core';
|
|
2
|
+
import { WooksAdapterBase } from 'wooks';
|
|
3
|
+
import { Workflow, createStep } from '@prostojs/wf';
|
|
4
|
+
|
|
5
|
+
function createWfContext(data, options) {
|
|
6
|
+
return createEventContext({
|
|
7
|
+
event: Object.assign(Object.assign({}, data), { type: 'WF' }),
|
|
8
|
+
resume: false,
|
|
9
|
+
options,
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function resumeWfContext(data, options) {
|
|
13
|
+
return createEventContext({
|
|
14
|
+
event: Object.assign(Object.assign({}, data), { type: 'WF' }),
|
|
15
|
+
resume: true,
|
|
16
|
+
options,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Wrapper on top of useEventContext that provides
|
|
21
|
+
* proper context types for WF event
|
|
22
|
+
* @returns set of hooks { getCtx, restoreCtx, clearCtx, hookStore, getStore, setStore }
|
|
23
|
+
*/
|
|
24
|
+
function useWFContext() {
|
|
25
|
+
return useEventContext('CLI');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/******************************************************************************
|
|
29
|
+
Copyright (c) Microsoft Corporation.
|
|
30
|
+
|
|
31
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
32
|
+
purpose with or without fee is hereby granted.
|
|
33
|
+
|
|
34
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
35
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
36
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
37
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
38
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
39
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
40
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
41
|
+
***************************************************************************** */
|
|
42
|
+
/* global Reflect, Promise */
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
46
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
47
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
48
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
49
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
50
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
51
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
class WooksWorkflow extends Workflow {
|
|
56
|
+
constructor(wooks) {
|
|
57
|
+
super([]);
|
|
58
|
+
this.wooks = wooks;
|
|
59
|
+
}
|
|
60
|
+
resolveStep(stepId) {
|
|
61
|
+
var _a, _b, _c;
|
|
62
|
+
try {
|
|
63
|
+
useWFContext();
|
|
64
|
+
const found = this.wooks.lookup('WF_STEP', '/' + stepId);
|
|
65
|
+
if ((_a = found === null || found === void 0 ? void 0 : found.handlers) === null || _a === void 0 ? void 0 : _a.length) {
|
|
66
|
+
return found.handlers[0]();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (e) {
|
|
70
|
+
const router = this.wooks.getRouter();
|
|
71
|
+
const found = router.lookup('WF_STEP', '/' + stepId);
|
|
72
|
+
if ((_c = (_b = found === null || found === void 0 ? void 0 : found.route) === null || _b === void 0 ? void 0 : _b.handlers) === null || _c === void 0 ? void 0 : _c.length) {
|
|
73
|
+
return found.route.handlers[0]();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
throw new Error(`Step "${stepId}" not found.`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const wfShortcuts = {
|
|
81
|
+
flow: 'WF_FLOW',
|
|
82
|
+
step: 'WF_STEP',
|
|
83
|
+
};
|
|
84
|
+
class WooksWf extends WooksAdapterBase {
|
|
85
|
+
constructor(opts, wooks) {
|
|
86
|
+
super(wooks, opts === null || opts === void 0 ? void 0 : opts.logger, opts === null || opts === void 0 ? void 0 : opts.router);
|
|
87
|
+
this.opts = opts;
|
|
88
|
+
this.logger = (opts === null || opts === void 0 ? void 0 : opts.logger) || this.getLogger('wooks-wf');
|
|
89
|
+
this.wf = new WooksWorkflow(this.wooks);
|
|
90
|
+
}
|
|
91
|
+
step(id, opts) {
|
|
92
|
+
const step = createStep(id, opts);
|
|
93
|
+
return this.on('WF_STEP', id, () => step);
|
|
94
|
+
}
|
|
95
|
+
flow(id, schema) {
|
|
96
|
+
this.wf.register(id, schema);
|
|
97
|
+
return this.on('WF_FLOW', id, () => id);
|
|
98
|
+
}
|
|
99
|
+
start(schemaId, inputContext, input) {
|
|
100
|
+
return this._start(schemaId, inputContext, undefined, input);
|
|
101
|
+
}
|
|
102
|
+
resume(schemaId, inputContext, indexes, input) {
|
|
103
|
+
return this._start(schemaId, inputContext, indexes, input);
|
|
104
|
+
}
|
|
105
|
+
_start(schemaId, inputContext, indexes, input) {
|
|
106
|
+
var _a, _b;
|
|
107
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
108
|
+
const resume = !!(indexes === null || indexes === void 0 ? void 0 : indexes.length);
|
|
109
|
+
const { restoreCtx, clearCtx } = (resume ? resumeWfContext : createWfContext)({
|
|
110
|
+
inputContext,
|
|
111
|
+
schemaId,
|
|
112
|
+
indexes,
|
|
113
|
+
input,
|
|
114
|
+
}, this.mergeEventOptions((_a = this.opts) === null || _a === void 0 ? void 0 : _a.eventOptions));
|
|
115
|
+
const { handlers: foundHandlers } = this.wooks.lookup('WF_FLOW', '/' + schemaId);
|
|
116
|
+
const handlers = foundHandlers ||
|
|
117
|
+
(((_b = this.opts) === null || _b === void 0 ? void 0 : _b.onNotFound) && [this.opts.onNotFound]) ||
|
|
118
|
+
null;
|
|
119
|
+
if (handlers && handlers.length) {
|
|
120
|
+
let result = {};
|
|
121
|
+
for (const handler of handlers) {
|
|
122
|
+
restoreCtx();
|
|
123
|
+
const schemaId = (yield handler());
|
|
124
|
+
if (resume) {
|
|
125
|
+
result = yield this.wf.resume(schemaId, { context: inputContext, indexes }, input);
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
result = yield this.wf.start(schemaId, inputContext, input);
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
clearCtx();
|
|
134
|
+
return result;
|
|
135
|
+
}
|
|
136
|
+
clearCtx();
|
|
137
|
+
throw new Error('Unknown schemaId: ' + schemaId);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
onError(e) {
|
|
141
|
+
var _a;
|
|
142
|
+
if ((_a = this.opts) === null || _a === void 0 ? void 0 : _a.onError) {
|
|
143
|
+
this.opts.onError(e);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
this.error(e.message);
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
error(e) {
|
|
151
|
+
if (typeof e === 'string') {
|
|
152
|
+
console.error('[31m' + 'ERROR: ' + '[0m' + e);
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
console.error('[31m' + 'ERROR: ' + '[0m' + e.message);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Factory for WooksWf App
|
|
161
|
+
* @param opts TWooksWfOptions
|
|
162
|
+
* @param wooks Wooks | WooksAdapterBase
|
|
163
|
+
* @returns WooksWf
|
|
164
|
+
*/
|
|
165
|
+
function createWfApp(opts, wooks) {
|
|
166
|
+
return new WooksWf(opts, wooks);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function useWfState() {
|
|
170
|
+
const { store } = useWFContext();
|
|
171
|
+
const event = store('event');
|
|
172
|
+
return {
|
|
173
|
+
ctx: () => event.get('inputContext'),
|
|
174
|
+
input: () => event.get('input'),
|
|
175
|
+
schemaId: event.get('schemaId'),
|
|
176
|
+
indexes: () => event.get('indexes'),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export { WooksWf, createWfApp, createWfContext, resumeWfContext, useWFContext, useWfState, wfShortcuts };
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wooksjs/event-wf",
|
|
3
|
+
"version": "0.3.7",
|
|
4
|
+
"description": "@wooksjs/event-wf",
|
|
5
|
+
"main": "dist/index.cjs",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/wooksjs/wooksjs.git",
|
|
14
|
+
"directory": "packages/event-wf"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"http",
|
|
18
|
+
"wooks",
|
|
19
|
+
"composables",
|
|
20
|
+
"framework",
|
|
21
|
+
"app",
|
|
22
|
+
"workflow",
|
|
23
|
+
"prostojs"
|
|
24
|
+
],
|
|
25
|
+
"author": "Artem Maltsev",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"wooks": "0.3.7",
|
|
29
|
+
"@wooksjs/event-core": "0.3.7"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@prostojs/logger": "^0.3.6",
|
|
33
|
+
"@prostojs/wf": "^0.0.2"
|
|
34
|
+
},
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/wooksjs/wooksjs/issues"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/wooksjs/wooksjs/tree/main/packages/event-wf#readme"
|
|
39
|
+
}
|