@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 CHANGED
@@ -5,7 +5,7 @@
5
5
  "name": "gesslar",
6
6
  "url": "https://gesslar.dev"
7
7
  },
8
- "version": "2.2.0",
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.24.0"
52
+ "@gesslar/toolkit": "^3.34.0"
53
53
  },
54
54
  "devDependencies": {
55
- "@gesslar/uglier": "^1.2.0",
56
- "eslint": "^9.39.2",
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#build} to register activities.
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 ActivityFlags}.
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|null} */
54
+ /** @type {ActionBuilderAction?} */
62
55
  #action = null
63
56
  /** @type {Map<string|symbol, ActivityDefinition>} */
64
57
  #activities = new Map([])
65
- /** @type {DebugFn|null} */
58
+ /** @type {DebugFn?} */
66
59
  #debug = null
67
- /** @type {symbol|null} */
60
+ /** @type {symbol?} */
68
61
  #tag = null
69
- /** @type {string|null} */
62
+ /** @type {string?} */
70
63
  #hooksFile = null
71
- /** @type {string|null} */
64
+ /** @type {string?} */
72
65
  #hooksKind = null
73
- /** @type {import("./ActionHooks.js").default|null} */
66
+ /** @type {ActionHooks?} */
74
67
  #hooks = null
75
- /** @type {ActionFunction|null} */
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 ActivityFlags}.
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 {import("./ActionHooks.js").default} hooks An already-instantiated hooks instance.
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 | symbol} name Activity identifier.
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<import("./ActionWrapper.js").default>} Payload consumed by the {@link ActionRunner} constructor.
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: this.#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|null} */
25
+ /** @type {HookModule?} */
28
26
  #hooks = null
29
- /** @type {string|null} */
27
+ /** @type {string?} */
30
28
  #actionKind = null
31
29
  /** @type {number} */
32
30
  #timeout = 1_000 // Default 1 second timeout
33
- /** @type {DebugFn|null} */
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|null} Hooks object or null if not loaded
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|null} Setup hook function or null
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|null} Cleanup hook function or null
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|null>} Initialized hook manager or null if no hooks provided
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 {'before'|'after'|'setup'|'cleanup'|string} kind Hook namespace.
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, Valid, Notify} from "@gesslar/toolkit"
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
- * @typedef {(message: string, level?: number, ...args: Array<unknown>) => void} DebugFn
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 {import("./ActionBuilder.js").default|null} */
27
+ /** @type {ActionBuilder?} */
28
28
  #actionBuilder = null
29
- /** @type {import("./ActionWrapper.js").default|null} */
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.#notify.emit("loop.break", parentWrapper)
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.#notify.on("loop.break", wrapper => {
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
- } finally {
203
- // Execute done callback if registered - always runs, even on error
204
- // Only run for top-level pipelines, not nested builders (inside loops)
205
- if(actionWrapper.done && !parentWrapper) {
206
- try {
207
- context = await actionWrapper.done.call(
208
- actionWrapper.action, context
209
- )
210
- } catch(error) {
211
- throw Sass.new("ActionRunner running done callback", error)
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
- if(parallel) {
252
- return await runner.pipe(context)
253
- } else {
254
- return await runner.run(context, activity.wrapper)
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 {import("./ActionHooks.js").default|null} */
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.