@gesslar/actioneer 2.2.0 → 2.3.1
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/package.json +4 -4
- package/src/browser/lib/ActionBuilder.js +73 -62
- package/src/browser/lib/ActionHooks.js +19 -21
- package/src/browser/lib/ActionRunner.js +49 -40
- package/src/browser/lib/ActionWrapper.js +10 -5
- package/src/browser/lib/Activity.js +16 -12
- package/src/browser/lib/Piper.js +37 -17
- package/src/types/browser/lib/ActionBuilder.d.ts +71 -58
- package/src/types/browser/lib/ActionBuilder.d.ts.map +1 -1
- package/src/types/browser/lib/ActionHooks.d.ts +24 -25
- package/src/types/browser/lib/ActionHooks.d.ts.map +1 -1
- package/src/types/browser/lib/ActionRunner.d.ts +7 -5
- package/src/types/browser/lib/ActionRunner.d.ts.map +1 -1
- package/src/types/browser/lib/ActionWrapper.d.ts +6 -4
- package/src/types/browser/lib/ActionWrapper.d.ts.map +1 -1
- package/src/types/browser/lib/Activity.d.ts +20 -14
- package/src/types/browser/lib/Activity.d.ts.map +1 -1
- package/src/types/browser/lib/Piper.d.ts +7 -5
- package/src/types/browser/lib/Piper.d.ts.map +1 -1
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"name": "gesslar",
|
|
6
6
|
"url": "https://gesslar.dev"
|
|
7
7
|
},
|
|
8
|
-
"version": "2.
|
|
8
|
+
"version": "2.3.1",
|
|
9
9
|
"license": "Unlicense",
|
|
10
10
|
"homepage": "https://github.com/gesslar/toolkit#readme",
|
|
11
11
|
"repository": {
|
|
@@ -49,11 +49,11 @@
|
|
|
49
49
|
"node": ">=22"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@gesslar/toolkit": "^3.
|
|
52
|
+
"@gesslar/toolkit": "^3.34.0"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@gesslar/uglier": "^1.
|
|
56
|
-
"eslint": "^
|
|
55
|
+
"@gesslar/uglier": "^1.4.1",
|
|
56
|
+
"eslint": "^10.0.0",
|
|
57
57
|
"typescript": "^5.9.3"
|
|
58
58
|
},
|
|
59
59
|
"scripts": {
|
|
@@ -4,36 +4,29 @@ import ActionWrapper from "./ActionWrapper.js"
|
|
|
4
4
|
import ActionHooks from "./ActionHooks.js"
|
|
5
5
|
import {ACTIVITY} from "./Activity.js"
|
|
6
6
|
|
|
7
|
-
/** @typedef {import("./ActionRunner.js").default} ActionRunner */
|
|
8
|
-
/** @typedef {typeof import("./Activity.js").ACTIVITY} ActivityFlags */
|
|
9
|
-
|
|
10
7
|
/**
|
|
8
|
+
* Type imports and definitions.
|
|
9
|
+
*
|
|
10
|
+
* @import {default as ActionRunner} from "./ActionRunner.js"
|
|
11
|
+
*
|
|
11
12
|
* @typedef {(message: string, level?: number, ...args: Array<unknown>) => void} DebugFn
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
/**
|
|
13
|
+
*
|
|
15
14
|
* @typedef {object} ActionBuilderAction
|
|
16
|
-
* @property {(builder: ActionBuilder) => void} setup Function invoked during {@link ActionBuilder
|
|
17
|
-
* @property {symbol} [tag] Optional tag to reuse when reconstructing builders.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
/**
|
|
15
|
+
* @property {(builder: ActionBuilder) => void} setup - Function invoked during {@link ActionBuilder} to register activities.
|
|
16
|
+
* @property {symbol} [tag] - Optional tag to reuse when reconstructing builders.
|
|
17
|
+
*
|
|
21
18
|
* @typedef {object} ActionBuilderConfig
|
|
22
|
-
* @property {symbol} [tag] Optional tag for the builder instance.
|
|
23
|
-
* @property {DebugFn} [debug] Logger used by the pipeline internals.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
/**
|
|
19
|
+
* @property {symbol} [tag] - Optional tag for the builder instance.
|
|
20
|
+
* @property {DebugFn} [debug] - Logger used by the pipeline internals.
|
|
21
|
+
*
|
|
27
22
|
* @typedef {object} ActivityDefinition
|
|
28
|
-
* @property {ActionBuilderAction|null} action Parent action instance when available.
|
|
29
|
-
* @property {DebugFn|null} debug Logger function.
|
|
30
|
-
* @property {string|symbol} name Activity identifier.
|
|
31
|
-
* @property {ActionFunction|import("./ActionWrapper.js").default} op Operation to execute.
|
|
32
|
-
* @property {number} [kind] Optional kind flags from {@link
|
|
33
|
-
* @property {(context: unknown) => boolean|Promise<boolean>} [pred] Loop predicate.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
/**
|
|
23
|
+
* @property {ActionBuilderAction|null} action - Parent action instance when available.
|
|
24
|
+
* @property {DebugFn|null} debug - Logger function.
|
|
25
|
+
* @property {string|symbol} name - Activity identifier.
|
|
26
|
+
* @property {ActionFunction|import("./ActionWrapper.js").default} op - Operation to execute.
|
|
27
|
+
* @property {number} [kind] - Optional kind flags from {@link ACTIVITY}.
|
|
28
|
+
* @property {(context: unknown) => boolean|Promise<boolean>} [pred] - Loop predicate.
|
|
29
|
+
*
|
|
37
30
|
* @typedef {(context: unknown) => unknown|Promise<unknown>} ActionFunction
|
|
38
31
|
*/
|
|
39
32
|
|
|
@@ -58,28 +51,28 @@ import {ACTIVITY} from "./Activity.js"
|
|
|
58
51
|
* @class ActionBuilder
|
|
59
52
|
*/
|
|
60
53
|
export default class ActionBuilder {
|
|
61
|
-
/** @type {ActionBuilderAction
|
|
54
|
+
/** @type {ActionBuilderAction?} */
|
|
62
55
|
#action = null
|
|
63
56
|
/** @type {Map<string|symbol, ActivityDefinition>} */
|
|
64
57
|
#activities = new Map([])
|
|
65
|
-
/** @type {DebugFn
|
|
58
|
+
/** @type {DebugFn?} */
|
|
66
59
|
#debug = null
|
|
67
|
-
/** @type {symbol
|
|
60
|
+
/** @type {symbol?} */
|
|
68
61
|
#tag = null
|
|
69
|
-
/** @type {string
|
|
62
|
+
/** @type {string?} */
|
|
70
63
|
#hooksFile = null
|
|
71
|
-
/** @type {string
|
|
64
|
+
/** @type {string?} */
|
|
72
65
|
#hooksKind = null
|
|
73
|
-
/** @type {
|
|
66
|
+
/** @type {ActionHooks?} */
|
|
74
67
|
#hooks = null
|
|
75
|
-
/** @type {ActionFunction
|
|
68
|
+
/** @type {ActionFunction?} */
|
|
76
69
|
#done = null
|
|
77
70
|
|
|
78
71
|
/**
|
|
79
72
|
* Creates a new ActionBuilder instance with the provided action callback.
|
|
80
73
|
*
|
|
81
|
-
* @param {ActionBuilderAction} [action] Base action invoked by the runner when a block satisfies the configured structure.
|
|
82
|
-
* @param {ActionBuilderConfig} [config] Options
|
|
74
|
+
* @param {ActionBuilderAction} [action] - Base action invoked by the runner when a block satisfies the configured structure.
|
|
75
|
+
* @param {ActionBuilderConfig} [config] - Options
|
|
83
76
|
*/
|
|
84
77
|
constructor(
|
|
85
78
|
action,
|
|
@@ -89,6 +82,9 @@ export default class ActionBuilder {
|
|
|
89
82
|
this.#tag = this.#tag || tag
|
|
90
83
|
|
|
91
84
|
if(action) {
|
|
85
|
+
if(action.tag)
|
|
86
|
+
throw Sass.new("Action has already been consumed by a builder and cannot be reused.")
|
|
87
|
+
|
|
92
88
|
if(Data.typeOf(action.setup) !== "Function")
|
|
93
89
|
throw Sass.new("Setup must be a function.")
|
|
94
90
|
|
|
@@ -110,44 +106,44 @@ export default class ActionBuilder {
|
|
|
110
106
|
* - do(name, kind, splitter, rejoiner, opOrWrapper) - SPLIT with parallel execution
|
|
111
107
|
*
|
|
112
108
|
* @overload
|
|
113
|
-
* @param {string|symbol} name Activity name
|
|
114
|
-
* @param {ActionFunction} op Operation to execute once.
|
|
109
|
+
* @param {string|symbol} name - Activity name
|
|
110
|
+
* @param {ActionFunction} op - Operation to execute once.
|
|
115
111
|
* @returns {ActionBuilder}
|
|
116
112
|
*/
|
|
117
113
|
|
|
118
114
|
/**
|
|
119
115
|
* @overload
|
|
120
|
-
* @param {string|symbol} name Activity name
|
|
121
|
-
* @param {number} kind ACTIVITY.BREAK or ACTIVITY.CONTINUE flag.
|
|
122
|
-
* @param {(context: unknown) => boolean|Promise<boolean>} pred Predicate to evaluate for control flow.
|
|
116
|
+
* @param {string|symbol} name - Activity name
|
|
117
|
+
* @param {number} kind - ACTIVITY.BREAK or ACTIVITY.CONTINUE flag.
|
|
118
|
+
* @param {(context: unknown) => boolean|Promise<boolean>} pred - Predicate to evaluate for control flow.
|
|
123
119
|
* @returns {ActionBuilder}
|
|
124
120
|
*/
|
|
125
121
|
|
|
126
122
|
/**
|
|
127
123
|
* @overload
|
|
128
|
-
* @param {string|symbol} name Activity name
|
|
129
|
-
* @param {number} kind Activity kind (WHILE, UNTIL, or IF) from {@link
|
|
130
|
-
* @param {(context: unknown) => boolean|Promise<boolean>} pred Predicate executed before/after the op.
|
|
131
|
-
* @param {ActionFunction|ActionBuilder} op Operation or nested builder to execute.
|
|
124
|
+
* @param {string|symbol} name - Activity name
|
|
125
|
+
* @param {number} kind - Activity kind (WHILE, UNTIL, or IF) from {@link ACTIVITY}.
|
|
126
|
+
* @param {(context: unknown) => boolean|Promise<boolean>} pred - Predicate executed before/after the op.
|
|
127
|
+
* @param {ActionFunction|ActionBuilder} op - Operation or nested builder to execute.
|
|
132
128
|
* @returns {ActionBuilder}
|
|
133
129
|
*/
|
|
134
130
|
|
|
135
131
|
/**
|
|
136
132
|
* @overload
|
|
137
|
-
* @param {string|symbol} name Activity name
|
|
138
|
-
* @param {number} kind ACTIVITY.SPLIT flag.
|
|
139
|
-
* @param {(context: unknown) => unknown} splitter Splitter function for SPLIT mode.
|
|
140
|
-
* @param {(originalContext: unknown, splitResults: unknown) => unknown} rejoiner Rejoiner function for SPLIT mode.
|
|
141
|
-
* @param {ActionFunction|ActionBuilder} op Operation or nested builder to execute.
|
|
133
|
+
* @param {string|symbol} name - Activity name
|
|
134
|
+
* @param {number} kind - ACTIVITY.SPLIT flag.
|
|
135
|
+
* @param {(context: unknown) => unknown} splitter - Splitter function for SPLIT mode.
|
|
136
|
+
* @param {(originalContext: unknown, splitResults: unknown) => unknown} rejoiner - Rejoiner function for SPLIT mode.
|
|
137
|
+
* @param {ActionFunction|ActionBuilder} op - Operation or nested builder to execute.
|
|
142
138
|
* @returns {ActionBuilder}
|
|
143
139
|
*/
|
|
144
140
|
|
|
145
141
|
/**
|
|
146
142
|
* Handles runtime dispatch across the documented overloads.
|
|
147
143
|
*
|
|
148
|
-
* @param {string|symbol} name Activity name
|
|
149
|
-
* @param {...unknown} args See overloads
|
|
150
|
-
* @returns {ActionBuilder} The builder instance for chaining
|
|
144
|
+
* @param {string|symbol} name - Activity name
|
|
145
|
+
* @param {...unknown} args - See overloads
|
|
146
|
+
* @returns {ActionBuilder} - The builder instance for chaining
|
|
151
147
|
*/
|
|
152
148
|
do(name, ...args) {
|
|
153
149
|
this.#dupeActivityCheck(name)
|
|
@@ -209,9 +205,9 @@ export default class ActionBuilder {
|
|
|
209
205
|
/**
|
|
210
206
|
* Configure hooks to be loaded from a file when the action is built.
|
|
211
207
|
*
|
|
212
|
-
* @param {string} hooksFile Path to the hooks module file.
|
|
213
|
-
* @param {string} hooksKind Name of the exported hooks class to instantiate.
|
|
214
|
-
* @returns {ActionBuilder} The builder instance for chaining.
|
|
208
|
+
* @param {string} hooksFile - Path to the hooks module file.
|
|
209
|
+
* @param {string} hooksKind - Name of the exported hooks class to instantiate.
|
|
210
|
+
* @returns {ActionBuilder} - The builder instance for chaining.
|
|
215
211
|
* @throws {Sass} If hooks have already been configured.
|
|
216
212
|
*/
|
|
217
213
|
withHooksFile(hooksFile, hooksKind) {
|
|
@@ -228,8 +224,8 @@ export default class ActionBuilder {
|
|
|
228
224
|
/**
|
|
229
225
|
* Configure hooks using a pre-instantiated hooks object.
|
|
230
226
|
*
|
|
231
|
-
* @param {
|
|
232
|
-
* @returns {ActionBuilder} The builder instance for chaining.
|
|
227
|
+
* @param {ActionHooks} hooks - An already-instantiated hooks instance.
|
|
228
|
+
* @returns {ActionBuilder} - The builder instance for chaining.
|
|
233
229
|
* @throws {Sass} If hooks have already been configured with a different instance.
|
|
234
230
|
*/
|
|
235
231
|
withHooks(hooks) {
|
|
@@ -251,7 +247,7 @@ export default class ActionBuilder {
|
|
|
251
247
|
* Configure the action instance if not already set.
|
|
252
248
|
* Used to propagate parent action context to nested builders.
|
|
253
249
|
*
|
|
254
|
-
* @param {ActionBuilderAction} action The action instance to inherit.
|
|
250
|
+
* @param {ActionBuilderAction} action - The action instance to inherit.
|
|
255
251
|
* @returns {ActionBuilder} The builder instance for chaining.
|
|
256
252
|
*/
|
|
257
253
|
withAction(action) {
|
|
@@ -271,7 +267,7 @@ export default class ActionBuilder {
|
|
|
271
267
|
/**
|
|
272
268
|
* Register a callback to be executed after all activities complete.
|
|
273
269
|
*
|
|
274
|
-
* @param {ActionFunction} callback Function to execute at the end of the pipeline.
|
|
270
|
+
* @param {ActionFunction} callback - Function to execute at the end of the pipeline.
|
|
275
271
|
* @returns {ActionBuilder} The builder instance for chaining.
|
|
276
272
|
*/
|
|
277
273
|
done(callback) {
|
|
@@ -285,7 +281,7 @@ export default class ActionBuilder {
|
|
|
285
281
|
* Validates that an activity name has not been reused.
|
|
286
282
|
*
|
|
287
283
|
* @private
|
|
288
|
-
* @param {string
|
|
284
|
+
* @param {string|symbol} name Activity identifier.
|
|
289
285
|
*/
|
|
290
286
|
#dupeActivityCheck(name) {
|
|
291
287
|
Valid.assert(
|
|
@@ -298,9 +294,9 @@ export default class ActionBuilder {
|
|
|
298
294
|
* Finalises the builder and returns a payload that can be consumed by the
|
|
299
295
|
* runner.
|
|
300
296
|
*
|
|
301
|
-
* @returns {Promise<
|
|
297
|
+
* @returns {Promise<ActionWrapper>} Payload consumed by the {@link ActionRunner} constructor.
|
|
302
298
|
*/
|
|
303
|
-
async build() {
|
|
299
|
+
async build(runner) {
|
|
304
300
|
const action = this.#action
|
|
305
301
|
|
|
306
302
|
if(action && !action.tag) {
|
|
@@ -309,6 +305,20 @@ export default class ActionBuilder {
|
|
|
309
305
|
await Promise.resolve(action.setup.call(action, this))
|
|
310
306
|
}
|
|
311
307
|
|
|
308
|
+
if(action) {
|
|
309
|
+
// Inject a method to the action for emission, but only if it's undefined.
|
|
310
|
+
if(Data.isType(action.emit, "Undefined"))
|
|
311
|
+
action.emit = (...args) => runner.emit(...args)
|
|
312
|
+
|
|
313
|
+
// Inject a method to the action for onission, but only if it's undefined.
|
|
314
|
+
if(Data.isType(action.on, "Undefined"))
|
|
315
|
+
action.on = (event, cb) => runner.on(event, cb)
|
|
316
|
+
|
|
317
|
+
// Inject a method to the action for offission, but only if it's undefined.
|
|
318
|
+
if(Data.isType(action.off, "Undefined"))
|
|
319
|
+
action.off = (event, cb) => runner.off(event, cb)
|
|
320
|
+
}
|
|
321
|
+
|
|
312
322
|
// All children in a branch also get the same hooks.
|
|
313
323
|
const hooks = await this.#getHooks()
|
|
314
324
|
|
|
@@ -317,7 +327,8 @@ export default class ActionBuilder {
|
|
|
317
327
|
debug: this.#debug,
|
|
318
328
|
hooks,
|
|
319
329
|
done: this.#done,
|
|
320
|
-
action
|
|
330
|
+
action,
|
|
331
|
+
runner: runner,
|
|
321
332
|
})
|
|
322
333
|
}
|
|
323
334
|
|
|
@@ -4,16 +4,14 @@ import {Data, Sass, Promised, Time, Util, Valid} from "@gesslar/toolkit"
|
|
|
4
4
|
* @typedef {(message: string, level?: number, ...args: Array<unknown>) => void} DebugFn
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* @typedef {object} ActionHooksConfig
|
|
9
|
-
* @property {string} actionKind Action identifier shared between runner and hooks.
|
|
10
|
-
* @property {unknown} hooks Already-instantiated hooks implementation.
|
|
11
|
-
* @property {number} [hookTimeout] Timeout applied to hook execution in milliseconds.
|
|
12
|
-
* @property {DebugFn} debug Logger to emit diagnostics.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
7
|
/**
|
|
16
8
|
* @typedef {Record<string, (context: unknown) => Promise<unknown>|unknown>} HookModule
|
|
9
|
+
*
|
|
10
|
+
* @typedef {object} ActionHooksConfig
|
|
11
|
+
* @property {string} actionKind - Action identifier shared between runner and hooks.
|
|
12
|
+
* @property {unknown} hooks - Already-instantiated hooks implementation.
|
|
13
|
+
* @property {number} [hookTimeout] - Timeout applied to hook execution in milliseconds.
|
|
14
|
+
* @property {DebugFn} debug - Logger to emit diagnostics.
|
|
17
15
|
*/
|
|
18
16
|
|
|
19
17
|
/**
|
|
@@ -24,19 +22,19 @@ import {Data, Sass, Promised, Time, Util, Valid} from "@gesslar/toolkit"
|
|
|
24
22
|
* Browser version: Requires pre-instantiated hooks. File-based loading is not supported.
|
|
25
23
|
*/
|
|
26
24
|
export default class ActionHooks {
|
|
27
|
-
/** @type {HookModule
|
|
25
|
+
/** @type {HookModule?} */
|
|
28
26
|
#hooks = null
|
|
29
|
-
/** @type {string
|
|
27
|
+
/** @type {string?} */
|
|
30
28
|
#actionKind = null
|
|
31
29
|
/** @type {number} */
|
|
32
30
|
#timeout = 1_000 // Default 1 second timeout
|
|
33
|
-
/** @type {DebugFn
|
|
31
|
+
/** @type {DebugFn?} */
|
|
34
32
|
#debug = null
|
|
35
33
|
|
|
36
34
|
/**
|
|
37
35
|
* Creates a new ActionHook instance.
|
|
38
36
|
*
|
|
39
|
-
* @param {ActionHooksConfig} config Configuration values describing how to load the hooks.
|
|
37
|
+
* @param {ActionHooksConfig} config - Configuration values describing how to load the hooks.
|
|
40
38
|
*/
|
|
41
39
|
constructor({actionKind, hooks, hookTimeout = 1_000, debug}) {
|
|
42
40
|
this.#actionKind = actionKind
|
|
@@ -57,7 +55,7 @@ export default class ActionHooks {
|
|
|
57
55
|
/**
|
|
58
56
|
* Gets the loaded hooks object.
|
|
59
57
|
*
|
|
60
|
-
* @returns {object
|
|
58
|
+
* @returns {object?} Hooks object or null if not loaded
|
|
61
59
|
*/
|
|
62
60
|
get hooks() {
|
|
63
61
|
return this.#hooks
|
|
@@ -75,7 +73,7 @@ export default class ActionHooks {
|
|
|
75
73
|
/**
|
|
76
74
|
* Gets the setup hook function if available.
|
|
77
75
|
*
|
|
78
|
-
* @returns {(args: object) => unknown
|
|
76
|
+
* @returns {(args: object) => unknown} Setup hook function or null
|
|
79
77
|
*/
|
|
80
78
|
get setup() {
|
|
81
79
|
return this.hooks?.setup || null
|
|
@@ -84,7 +82,7 @@ export default class ActionHooks {
|
|
|
84
82
|
/**
|
|
85
83
|
* Gets the cleanup hook function if available.
|
|
86
84
|
*
|
|
87
|
-
* @returns {(args: object) => unknown
|
|
85
|
+
* @returns {(args: object) => unknown} Cleanup hook function or null
|
|
88
86
|
*/
|
|
89
87
|
get cleanup() {
|
|
90
88
|
return this.hooks?.cleanup || null
|
|
@@ -94,9 +92,9 @@ export default class ActionHooks {
|
|
|
94
92
|
* Static factory method to create and initialize a hook manager.
|
|
95
93
|
* Browser version: Only works with pre-instantiated hooks passed via config.hooks.
|
|
96
94
|
*
|
|
97
|
-
* @param {ActionHooksConfig} config Configuration object with hooks property
|
|
98
|
-
* @param {DebugFn} debug The debug function.
|
|
99
|
-
* @returns {Promise<ActionHooks
|
|
95
|
+
* @param {ActionHooksConfig} config - Configuration object with hooks property
|
|
96
|
+
* @param {DebugFn} debug - The debug function.
|
|
97
|
+
* @returns {Promise<ActionHooks?>} Initialized hook manager or null if no hooks provided
|
|
100
98
|
*/
|
|
101
99
|
static async new(config, debug) {
|
|
102
100
|
debug("Creating new HookManager instance with args: %o", 2, config)
|
|
@@ -117,9 +115,9 @@ export default class ActionHooks {
|
|
|
117
115
|
/**
|
|
118
116
|
* Invoke a dynamically-named hook such as `before$foo`.
|
|
119
117
|
*
|
|
120
|
-
* @param {
|
|
121
|
-
* @param {string|symbol} activityName Activity identifier.
|
|
122
|
-
* @param {unknown} context Pipeline context supplied to the hook.
|
|
118
|
+
* @param {string} kind - Hook namespace.
|
|
119
|
+
* @param {string|symbol} activityName - Activity identifier.
|
|
120
|
+
* @param {unknown} context - Pipeline context supplied to the hook.
|
|
123
121
|
* @returns {Promise<void>}
|
|
124
122
|
*/
|
|
125
123
|
async callHook(kind, activityName, context) {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import {Promised, Data, Sass,
|
|
1
|
+
import {Promised, Data, Sass, Tantrum, Valid} from "@gesslar/toolkit"
|
|
2
2
|
|
|
3
3
|
import {ACTIVITY} from "./Activity.js"
|
|
4
4
|
import Piper from "./Piper.js"
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* @typedef {import("./ActionBuilder.js").default} ActionBuilder
|
|
7
|
+
* Types
|
|
8
|
+
*
|
|
9
|
+
* @import {default as ActionBuilder} from "./ActionBuilder.js"
|
|
10
|
+
* @import {default as ActionWrapper} from "./ActionWrapper.js"
|
|
12
11
|
*/
|
|
13
|
-
|
|
14
12
|
/**
|
|
13
|
+
* @typedef {(message: string, level?: number, ...args: Array<unknown>) => void} DebugFn
|
|
14
|
+
*
|
|
15
15
|
* @typedef {object} ActionRunnerOptions
|
|
16
16
|
* @property {DebugFn} [debug] Logger function.
|
|
17
17
|
*/
|
|
@@ -24,9 +24,9 @@ import Piper from "./Piper.js"
|
|
|
24
24
|
* context object under `result.value` that can be replaced or enriched.
|
|
25
25
|
*/
|
|
26
26
|
export default class ActionRunner extends Piper {
|
|
27
|
-
/** @type {
|
|
27
|
+
/** @type {ActionBuilder?} */
|
|
28
28
|
#actionBuilder = null
|
|
29
|
-
/** @type {
|
|
29
|
+
/** @type {ActionWrapper?} */
|
|
30
30
|
#actionWrapper = null
|
|
31
31
|
|
|
32
32
|
/**
|
|
@@ -36,13 +36,6 @@ export default class ActionRunner extends Piper {
|
|
|
36
36
|
*/
|
|
37
37
|
#debug = () => {}
|
|
38
38
|
|
|
39
|
-
/**
|
|
40
|
-
* Event emitter for cross-runner communication (BREAK/CONTINUE signals).
|
|
41
|
-
*
|
|
42
|
-
* @type {typeof Notify}
|
|
43
|
-
*/
|
|
44
|
-
#notify = Notify
|
|
45
|
-
|
|
46
39
|
/**
|
|
47
40
|
* Instantiate a runner over an optional action wrapper.
|
|
48
41
|
*
|
|
@@ -76,14 +69,17 @@ export default class ActionRunner extends Piper {
|
|
|
76
69
|
* @param {import("./ActionWrapper.js").default|null} [parentWrapper] - Parent wrapper for BREAK/CONTINUE signaling.
|
|
77
70
|
* @returns {Promise<unknown>} Final value produced by the pipeline.
|
|
78
71
|
* @throws {Sass} When no activities are registered, conflicting activity kinds are used, or execution fails.
|
|
72
|
+
* @throws {Tantrum} When both an activity and the done callback fail.
|
|
79
73
|
*/
|
|
80
74
|
async run(context, parentWrapper=null) {
|
|
81
75
|
if(!this.#actionWrapper)
|
|
82
|
-
this.#actionWrapper = await this.#actionBuilder.build()
|
|
76
|
+
this.#actionWrapper = await this.#actionBuilder.build(this)
|
|
83
77
|
|
|
84
78
|
const actionWrapper = this.#actionWrapper
|
|
85
79
|
const activities = Array.from(actionWrapper.activities)
|
|
86
80
|
|
|
81
|
+
let caughtError = null
|
|
82
|
+
|
|
87
83
|
try {
|
|
88
84
|
for(
|
|
89
85
|
let cursor = 0, max = activities.length;
|
|
@@ -114,7 +110,7 @@ export default class ActionRunner extends Piper {
|
|
|
114
110
|
|
|
115
111
|
if(await this.#evalPredicate(activity, context)) {
|
|
116
112
|
if(kindBreak) {
|
|
117
|
-
this
|
|
113
|
+
this.emit("loop.break", parentWrapper)
|
|
118
114
|
break
|
|
119
115
|
}
|
|
120
116
|
|
|
@@ -132,7 +128,7 @@ export default class ActionRunner extends Piper {
|
|
|
132
128
|
break
|
|
133
129
|
|
|
134
130
|
let weWereOnABreak = false
|
|
135
|
-
const breakReceiver = this
|
|
131
|
+
const breakReceiver = this.on("loop.break", wrapper => {
|
|
136
132
|
if(wrapper.id === actionWrapper.id) {
|
|
137
133
|
weWereOnABreak = true
|
|
138
134
|
}
|
|
@@ -158,10 +154,7 @@ export default class ActionRunner extends Piper {
|
|
|
158
154
|
)
|
|
159
155
|
|
|
160
156
|
const original = context
|
|
161
|
-
const splitContexts = await splitter.call(
|
|
162
|
-
activity.action,
|
|
163
|
-
context
|
|
164
|
-
)
|
|
157
|
+
const splitContexts = await splitter.call(activity.action,context)
|
|
165
158
|
|
|
166
159
|
let settled
|
|
167
160
|
|
|
@@ -199,20 +192,28 @@ export default class ActionRunner extends Piper {
|
|
|
199
192
|
throw Sass.new("ActionRunner running activity", error)
|
|
200
193
|
}
|
|
201
194
|
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
195
|
+
} catch(err) {
|
|
196
|
+
caughtError = err
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Execute done callback if registered - always runs, even on error
|
|
200
|
+
// Only run for top-level pipelines, not nested builders (inside loops)
|
|
201
|
+
if(actionWrapper.done && !parentWrapper) {
|
|
202
|
+
try {
|
|
203
|
+
context = await actionWrapper.done.call(
|
|
204
|
+
actionWrapper.action, caughtError ?? context
|
|
205
|
+
)
|
|
206
|
+
} catch(error) {
|
|
207
|
+
if(caughtError)
|
|
208
|
+
caughtError = new Tantrum("ActionRunner running done callback", [caughtError, error])
|
|
209
|
+
else
|
|
210
|
+
caughtError = Sass.new("ActionRunner running done callback", error)
|
|
213
211
|
}
|
|
214
212
|
}
|
|
215
213
|
|
|
214
|
+
if(caughtError)
|
|
215
|
+
throw caughtError
|
|
216
|
+
|
|
216
217
|
return context
|
|
217
218
|
}
|
|
218
219
|
|
|
@@ -248,10 +249,20 @@ export default class ActionRunner extends Piper {
|
|
|
248
249
|
debug: this.#debug, name: activity.name
|
|
249
250
|
})
|
|
250
251
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
252
|
+
// Forward loop.break events from nested runner to this runner
|
|
253
|
+
// so that parent WHILE/UNTIL loops can receive break signals.
|
|
254
|
+
const forwarder = runner.on("loop.break",
|
|
255
|
+
wrapper => this.emit("loop.break", wrapper)
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
try {
|
|
259
|
+
if(parallel) {
|
|
260
|
+
return await runner.pipe(context)
|
|
261
|
+
} else {
|
|
262
|
+
return await runner.run(context, activity.wrapper)
|
|
263
|
+
}
|
|
264
|
+
} finally {
|
|
265
|
+
forwarder()
|
|
255
266
|
}
|
|
256
267
|
} else if(opKind === "Function") {
|
|
257
268
|
try {
|
|
@@ -281,8 +292,6 @@ export default class ActionRunner extends Piper {
|
|
|
281
292
|
}
|
|
282
293
|
}
|
|
283
294
|
|
|
284
|
-
console.log(activity.opKind + " " + JSON.stringify(activity))
|
|
285
|
-
|
|
286
295
|
throw Sass.new("We buy Functions and ActionBuilders. Only. Not whatever that was.")
|
|
287
296
|
}
|
|
288
297
|
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import Activity from "./Activity.js"
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Type imports
|
|
5
|
+
*
|
|
6
|
+
* @import {default as ActionHooks} from "./ActionHooks.js"
|
|
7
|
+
* @import {default as ActionRunner} from "./ActionRunner.js"
|
|
8
|
+
*/
|
|
9
|
+
|
|
3
10
|
/**
|
|
4
11
|
* @typedef {object} WrappedActivityConfig
|
|
5
12
|
* @property {string|symbol} name Activity identifier used by hooks/logs.
|
|
@@ -10,10 +17,6 @@ import Activity from "./Activity.js"
|
|
|
10
17
|
* @property {(message: string, level?: number, ...args: Array<unknown>) => void} [debug] Optional logger reference.
|
|
11
18
|
*/
|
|
12
19
|
|
|
13
|
-
/**
|
|
14
|
-
* @typedef {import("@gesslar/toolkit").Generator<Activity, void, unknown>} ActivityIterator
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
20
|
/**
|
|
18
21
|
* Thin wrapper that materialises {@link Activity} instances on demand.
|
|
19
22
|
*/
|
|
@@ -32,7 +35,7 @@ export default class ActionWrapper {
|
|
|
32
35
|
*/
|
|
33
36
|
#debug = () => {}
|
|
34
37
|
|
|
35
|
-
/** @type {
|
|
38
|
+
/** @type {ActionHooks} */
|
|
36
39
|
#hooks = null
|
|
37
40
|
/** @type {((context: unknown) => unknown|Promise<unknown>)|null} */
|
|
38
41
|
#done = null
|
|
@@ -40,6 +43,8 @@ export default class ActionWrapper {
|
|
|
40
43
|
#action = null
|
|
41
44
|
/** @type {symbol} */
|
|
42
45
|
#id = Symbol(performance.now())
|
|
46
|
+
/** @type {ActionRunner} */
|
|
47
|
+
#runner
|
|
43
48
|
|
|
44
49
|
/**
|
|
45
50
|
* Create a wrapper from the builder payload.
|