@gesslar/actioneer 2.0.2 → 2.1.0

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.0.2",
8
+ "version": "2.1.0",
9
9
  "license": "Unlicense",
10
10
  "homepage": "https://github.com/gesslar/toolkit#readme",
11
11
  "repository": {
@@ -49,19 +49,19 @@
49
49
  "node": ">=22"
50
50
  },
51
51
  "dependencies": {
52
- "@gesslar/toolkit": "^3.6.2"
52
+ "@gesslar/toolkit": "^3.23.0"
53
53
  },
54
54
  "devDependencies": {
55
- "@gesslar/uglier": "^0.5.0",
55
+ "@gesslar/uglier": "^1.1.0",
56
56
  "eslint": "^9.39.2",
57
57
  "typescript": "^5.9.3"
58
58
  },
59
59
  "scripts": {
60
60
  "lint": "eslint src/",
61
61
  "lint:fix": "eslint src/ --fix",
62
- "types:build": "tsc -p tsconfig.types.json",
62
+ "types": "node -e \"require('fs').rmSync('types',{recursive:true,force:true});\" && tsc -p tsconfig.types.json",
63
63
  "submit": "pnpm publish --access public --//registry.npmjs.org/:_authToken=\"${NPM_ACCESS_TOKEN}\"",
64
- "update": "pnpm up --latest --recursive",
64
+ "update": "pnpm self-update && pnpx npm-check-updates -u && pnpm install",
65
65
  "test": "node --test tests/**/*.test.js",
66
66
  "test:browser": "node --test tests/browser/*.test.js",
67
67
  "test:node": "node --test tests/node/*.test.js",
@@ -69,6 +69,7 @@ export default class ActionBuilder {
69
69
  #hooksFile = null
70
70
  #hooksKind = null
71
71
  #hooks = null
72
+ #done = null
72
73
 
73
74
  /**
74
75
  * Creates a new ActionBuilder instance with the provided action callback.
@@ -246,6 +247,19 @@ export default class ActionBuilder {
246
247
  return this
247
248
  }
248
249
 
250
+ /**
251
+ * Register a callback to be executed after all activities complete.
252
+ *
253
+ * @param {ActionFunction} callback Function to execute at the end of the pipeline.
254
+ * @returns {ActionBuilder} The builder instance for chaining.
255
+ */
256
+ done(callback) {
257
+ Valid.type(callback, "Function")
258
+ this.#done = callback
259
+
260
+ return this
261
+ }
262
+
249
263
  /**
250
264
  * Validates that an activity name has not been reused.
251
265
  *
@@ -281,6 +295,8 @@ export default class ActionBuilder {
281
295
  activities: this.#activities,
282
296
  debug: this.#debug,
283
297
  hooks,
298
+ done: this.#done,
299
+ action: this.#action,
284
300
  })
285
301
  }
286
302
 
@@ -7,10 +7,15 @@ import Piper from "./Piper.js"
7
7
  * @typedef {(message: string, level?: number, ...args: Array<unknown>) => void} DebugFn
8
8
  */
9
9
 
10
+ /**
11
+ * @typedef {import("./ActionBuilder.js").default} ActionBuilder
12
+ */
13
+
10
14
  /**
11
15
  * @typedef {object} ActionRunnerOptions
12
16
  * @property {DebugFn} [debug] Logger function.
13
17
  */
18
+
14
19
  /**
15
20
  * Orchestrates execution of {@link ActionBuilder}-produced pipelines.
16
21
  *
@@ -71,95 +76,109 @@ export default class ActionRunner extends Piper {
71
76
  const actionWrapper = this.#actionWrapper
72
77
  const activities = actionWrapper.activities
73
78
 
74
- for(const activity of activities) {
75
- try {
76
- // await timeout(500)
77
-
78
- const kind = activity.kind
79
+ try {
80
+ for(const activity of activities) {
81
+ try {
82
+ // await timeout(500)
79
83
 
80
- // If we have no kind, then it's just a once.
81
- // Get it over and done with!
82
- if(!kind) {
83
- context = await this.#execute(activity, context)
84
- } else {
85
- // Validate that only one activity kind bit is set
86
- // (kind & (kind - 1)) !== 0 means multiple bits are set
87
- const multipleBitsSet = (kind & (kind - 1)) !== 0
88
- if(multipleBitsSet)
89
- throw Sass.new(
90
- "For Kathy Griffin's sake! You can't combine activity kinds. " +
91
- "Pick one: WHILE, UNTIL, or SPLIT!"
92
- )
93
-
94
- const {WHILE,UNTIL,SPLIT} = ACTIVITY
95
- const kindWhile = kind & WHILE
96
- const kindUntil = kind & UNTIL
97
- const kindSplit = kind & SPLIT
98
-
99
- if(kindWhile || kindUntil) {
100
- const predicate = activity.pred
101
-
102
- for(;;) {
103
-
104
- if(kindWhile)
105
- if(!await this.#hasPredicate(activity,predicate,context))
106
- break
107
-
108
- context = await this.#execute(activity,context)
109
-
110
- if(kindUntil)
111
- if(await this.#hasPredicate(activity,predicate,context))
112
- break
113
- }
114
- } else if(kindSplit) {
115
- // SPLIT activity: parallel execution with splitter/rejoiner
116
- // pattern
117
- const {splitter, rejoiner} = activity
84
+ const kind = activity.kind
118
85
 
119
- if(!splitter || !rejoiner)
86
+ // If we have no kind, then it's just a once.
87
+ // Get it over and done with!
88
+ if(!kind) {
89
+ context = await this.#execute(activity, context)
90
+ } else {
91
+ // Validate that only one activity kind bit is set
92
+ // (kind & (kind - 1)) !== 0 means multiple bits are set
93
+ const multipleBitsSet = (kind & (kind - 1)) !== 0
94
+ if(multipleBitsSet)
120
95
  throw Sass.new(
121
- `SPLIT activity "${String(activity.name)}" requires both ` +
122
- `splitter and rejoiner functions.`
96
+ "For Kathy Griffin's sake! You can't combine activity kinds. " +
97
+ "Pick one: WHILE, UNTIL, or SPLIT!"
123
98
  )
124
99
 
125
- const original = context
126
- const splitContexts = await splitter.call(activity.action, context)
100
+ const {WHILE,UNTIL,SPLIT} = ACTIVITY
101
+ const kindWhile = kind & WHILE
102
+ const kindUntil = kind & UNTIL
103
+ const kindSplit = kind & SPLIT
127
104
 
128
- let settled
105
+ if(kindWhile || kindUntil) {
106
+ const predicate = activity.pred
129
107
 
130
- if(activity.opKind === "ActionBuilder") {
131
- if(activity.action)
132
- activity.op.withAction(activity.action)
108
+ for(;;) {
133
109
 
134
- if(activity.hooks)
135
- activity.op.withHooks(activity.hooks)
110
+ if(kindWhile)
111
+ if(!await this.#hasPredicate(activity,predicate,context))
112
+ break
136
113
 
137
- const runner = new this.constructor(activity.op, {
138
- debug: this.#debug, name: activity.name
139
- })
114
+ context = await this.#execute(activity,context)
140
115
 
141
- // pipe() returns settled results with concurrency control
142
- settled = await runner.pipe(splitContexts)
143
- } else {
144
- // For plain functions, process each split context
145
- settled = await Promised.settle(
146
- splitContexts.map(ctx => this.#execute(activity, ctx))
147
- )
148
- }
116
+ if(kindUntil)
117
+ if(await this.#hasPredicate(activity,predicate,context))
118
+ break
119
+ }
120
+ } else if(kindSplit) {
121
+ // SPLIT activity: parallel execution with splitter/rejoiner
122
+ // pattern
123
+ const {splitter, rejoiner} = activity
149
124
 
150
- const rejoined = await rejoiner.call(
151
- activity.action,
152
- original,
153
- settled
154
- )
125
+ if(!splitter || !rejoiner)
126
+ throw Sass.new(
127
+ `SPLIT activity "${String(activity.name)}" requires both ` +
128
+ `splitter and rejoiner functions.`
129
+ )
155
130
 
156
- context = rejoined
157
- } else {
158
- context = await this.#execute(activity, context)
131
+ const original = context
132
+ const splitContexts = await splitter.call(
133
+ activity.action, context
134
+ )
135
+ let settled
136
+
137
+ if(activity.opKind === "ActionBuilder") {
138
+ if(activity.action)
139
+ activity.op.withAction(activity.action)
140
+
141
+ if(activity.hooks)
142
+ activity.op.withHooks(activity.hooks)
143
+
144
+ const runner = new this.constructor(activity.op, {
145
+ debug: this.#debug, name: activity.name
146
+ })
147
+
148
+ // pipe() returns settled results with concurrency control
149
+ settled = await runner.pipe(splitContexts)
150
+ } else {
151
+ // For plain functions, process each split context
152
+ settled = await Promised.settle(
153
+ splitContexts.map(ctx => this.#execute(activity, ctx))
154
+ )
155
+ }
156
+
157
+ const rejoined = await rejoiner.call(
158
+ activity.action,
159
+ original,
160
+ settled
161
+ )
162
+
163
+ context = rejoined
164
+ } else {
165
+ context = await this.#execute(activity, context)
166
+ }
159
167
  }
168
+ } catch(error) {
169
+ throw Sass.new("ActionRunner running activity", error)
170
+ }
171
+ }
172
+ } finally {
173
+ // Execute done callback if registered - always runs, even on error
174
+ if(actionWrapper.done) {
175
+ try {
176
+ context = await actionWrapper.done.call(
177
+ actionWrapper.action, context
178
+ )
179
+ } catch(error) {
180
+ throw Sass.new("ActionRunner running done callback", error)
160
181
  }
161
- } catch(error) {
162
- throw Sass.new("ActionRunner running activity", error)
163
182
  }
164
183
  }
165
184
 
@@ -11,7 +11,7 @@ import Activity from "./Activity.js"
11
11
  */
12
12
 
13
13
  /**
14
- * @typedef {Generator<Activity, void, unknown>} ActivityIterator
14
+ * @typedef {import("@gesslar/toolkit").Generator<Activity, void, unknown>} ActivityIterator
15
15
  */
16
16
 
17
17
  /**
@@ -33,14 +33,20 @@ export default class ActionWrapper {
33
33
 
34
34
  #hooks = null
35
35
 
36
+ #done = null
37
+
38
+ #action = null
39
+
36
40
  /**
37
41
  * Create a wrapper from the builder payload.
38
42
  *
39
43
  * @param {{activities: Map<string|symbol, WrappedActivityConfig>, debug: (message: string, level?: number, ...args: Array<unknown>) => void}} init Builder payload containing activities + logger.
40
44
  */
41
- constructor({activities,hooks,debug}) {
45
+ constructor({activities,hooks,debug,done: doneCallback,action}) {
42
46
  this.#debug = debug
43
47
  this.#hooks = hooks
48
+ this.#done = doneCallback
49
+ this.#action = action
44
50
  this.#activities = activities
45
51
  this.#debug(
46
52
  "Instantiating ActionWrapper with %o activities.",
@@ -62,4 +68,22 @@ export default class ActionWrapper {
62
68
  get activities() {
63
69
  return this.#_activities()
64
70
  }
71
+
72
+ /**
73
+ * Get the done callback if registered.
74
+ *
75
+ * @returns {((context: unknown) => unknown|Promise<unknown>)|null} Done callback or null.
76
+ */
77
+ get done() {
78
+ return this.#done
79
+ }
80
+
81
+ /**
82
+ * Get the action instance.
83
+ *
84
+ * @returns {unknown|null} Action instance or null.
85
+ */
86
+ get action() {
87
+ return this.#action
88
+ }
65
89
  }
@@ -109,7 +109,7 @@ export default class Piper {
109
109
  }
110
110
 
111
111
  const setupResult = await Promised.settle(
112
- [...this.#lifeCycle.get("setup")].map(e => e())
112
+ [...this.#lifeCycle.get("setup")].map(e => Promise.resolve(e()))
113
113
  )
114
114
 
115
115
  this.#processResult("Setting up the pipeline.", setupResult)
@@ -127,7 +127,7 @@ export default class Piper {
127
127
  } finally {
128
128
  // Run cleanup hooks
129
129
  const teardownResult = await Promised.settle(
130
- [...this.#lifeCycle.get("teardown")].map(e => e())
130
+ [...this.#lifeCycle.get("teardown")].map(e => Promise.resolve(e()))
131
131
  )
132
132
 
133
133
  this.#processResult("Tearing down the pipeline.", teardownResult)
@@ -41,6 +41,14 @@ export default class ActionHooks extends BrowserActionHooks {
41
41
  return this.#hooksFile
42
42
  }
43
43
 
44
+ /**
45
+ * @typedef {object} ActionHooksConfig
46
+ * @property {string} [hooksFile] Path to the hooks file
47
+ * @property {string} [hooksKind] Name of the hooks class to instantiate
48
+ * @property {object} [hooks] Pre-instantiated hooks object
49
+ * @property {number} [timeout] Timeout for hook execution
50
+ */
51
+
44
52
  /**
45
53
  * Static factory method to create and initialize a hook manager.
46
54
  * Loads hooks from the specified file and returns an initialized instance.
@@ -112,6 +112,13 @@ export default class ActionBuilder {
112
112
  * @returns {ActionBuilder} The builder instance for chaining.
113
113
  */
114
114
  withAction(action: ActionBuilderAction): ActionBuilder;
115
+ /**
116
+ * Register a callback to be executed after all activities complete.
117
+ *
118
+ * @param {ActionFunction} callback Function to execute at the end of the pipeline.
119
+ * @returns {ActionBuilder} The builder instance for chaining.
120
+ */
121
+ done(callback: ActionFunction): ActionBuilder;
115
122
  /**
116
123
  * Finalises the builder and returns a payload that can be consumed by the
117
124
  * runner.
@@ -1 +1 @@
1
- {"version":3,"file":"ActionBuilder.d.ts","sourceRoot":"","sources":["../../../browser/lib/ActionBuilder.js"],"names":[],"mappings":"AAMA,kEAAkE;AAClE,uEAAuE;AAEvE;;GAEG;AAEH;;;;GAIG;AAEH;;;;GAIG;AAEH;;;;;;;;GAQG;AAEH;;GAEG;AAEH;;;;;;;;;;;;;;;;;;;GAmBG;AACH;IAaE;;;;;OAKG;IACH,qBAHW,mBAAmB,mBACnB,mBAAmB,EAe7B;IAED,yBAEC;;;;;;;;;;;;;;IAUE,SACQ,MAAM,GAAC,MAAM,MACb,cAAc,GACZ,aAAa,CACzB;;;;;;;;;IAGE,SACQ,MAAM,GAAC,MAAM,QACb,MAAM,QACN,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,GAAC,OAAO,CAAC,OAAO,CAAC,MAC9C,cAAc,GAAC,OAAO,oBAAoB,EAAE,OAAO,GACjD,aAAa,CACzB;;;;;;;;;;IAGE,SACQ,MAAM,GAAC,MAAM,QACb,MAAM,YACN,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,YAC7B,CAAC,eAAe,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,KAAK,OAAO,MAC5D,cAAc,GAAC,OAAO,oBAAoB,EAAE,OAAO,GACjD,aAAa,CACzB;IA0DD;;;;;;;OAOG;IACH,yBALW,MAAM,aACN,MAAM,GACJ,aAAa,CAYzB;IAED;;;;;;OAMG;IACH,iBAJW,OAAO,kBAAkB,EAAE,OAAO,GAChC,aAAa,CAgBzB;IAED;;;;;;OAMG;IACH,mBAHW,mBAAmB,GACjB,aAAa,CAczB;IAeD;;;;;OAKG;IACH,SAFa,OAAO,CAAC,OAAO,oBAAoB,EAAE,OAAO,CAAC,CAmBzD;;CAqBF;2BA3Sa,OAAO,mBAAmB,EAAE,OAAO;4BACnC,cAAc,eAAe,EAAE,QAAQ;sBAGxC,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI;;;;;WAKjE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;YAYhC,mBAAmB,GAAC,IAAI;;;;WACxB,OAAO,GAAC,IAAI;;;;UACZ,MAAM,GAAC,MAAM;;;;QACb,cAAc,GAAC,OAAO,oBAAoB,EAAE,OAAO;;;;;;;;sBAEzC,OAAO,KAAK,OAAO,GAAC,OAAO,CAAC,OAAO,CAAC;;6BAI/C,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,GAAC,OAAO,CAAC,OAAO,CAAC"}
1
+ {"version":3,"file":"ActionBuilder.d.ts","sourceRoot":"","sources":["../../../browser/lib/ActionBuilder.js"],"names":[],"mappings":"AAMA,kEAAkE;AAClE,uEAAuE;AAEvE;;GAEG;AAEH;;;;GAIG;AAEH;;;;GAIG;AAEH;;;;;;;;GAQG;AAEH;;GAEG;AAEH;;;;;;;;;;;;;;;;;;;GAmBG;AACH;IAcE;;;;;OAKG;IACH,qBAHW,mBAAmB,mBACnB,mBAAmB,EAe7B;IAED,yBAEC;;;;;;;;;;;;;;IAUE,SACQ,MAAM,GAAC,MAAM,MACb,cAAc,GACZ,aAAa,CACzB;;;;;;;;;IAGE,SACQ,MAAM,GAAC,MAAM,QACb,MAAM,QACN,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,GAAC,OAAO,CAAC,OAAO,CAAC,MAC9C,cAAc,GAAC,OAAO,oBAAoB,EAAE,OAAO,GACjD,aAAa,CACzB;;;;;;;;;;IAGE,SACQ,MAAM,GAAC,MAAM,QACb,MAAM,YACN,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,YAC7B,CAAC,eAAe,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,KAAK,OAAO,MAC5D,cAAc,GAAC,OAAO,oBAAoB,EAAE,OAAO,GACjD,aAAa,CACzB;IA0DD;;;;;;;OAOG;IACH,yBALW,MAAM,aACN,MAAM,GACJ,aAAa,CAYzB;IAED;;;;;;OAMG;IACH,iBAJW,OAAO,kBAAkB,EAAE,OAAO,GAChC,aAAa,CAgBzB;IAED;;;;;;OAMG;IACH,mBAHW,mBAAmB,GACjB,aAAa,CAczB;IAED;;;;;OAKG;IACH,eAHW,cAAc,GACZ,aAAa,CAOzB;IAeD;;;;;OAKG;IACH,SAFa,OAAO,CAAC,OAAO,oBAAoB,EAAE,OAAO,CAAC,CAoBzD;;CAqBF;2BA1Ta,OAAO,mBAAmB,EAAE,OAAO;4BACnC,cAAc,eAAe,EAAE,QAAQ;sBAGxC,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI;;;;;WAKjE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;YAYhC,mBAAmB,GAAC,IAAI;;;;WACxB,OAAO,GAAC,IAAI;;;;UACZ,MAAM,GAAC,MAAM;;;;QACb,cAAc,GAAC,OAAO,oBAAoB,EAAE,OAAO;;;;;;;;sBAEzC,OAAO,KAAK,OAAO,GAAC,OAAO,CAAC,OAAO,CAAC;;6BAI/C,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,GAAC,OAAO,CAAC,OAAO,CAAC"}
@@ -1,6 +1,9 @@
1
1
  /**
2
2
  * @typedef {(message: string, level?: number, ...args: Array<unknown>) => void} DebugFn
3
3
  */
4
+ /**
5
+ * @typedef {import("./ActionBuilder.js").default} ActionBuilder
6
+ */
4
7
  /**
5
8
  * @typedef {object} ActionRunnerOptions
6
9
  * @property {DebugFn} [debug] Logger function.
@@ -33,6 +36,7 @@ export default class ActionRunner extends Piper {
33
36
  #private;
34
37
  }
35
38
  export type DebugFn = (message: string, level?: number, ...args: Array<unknown>) => void;
39
+ export type ActionBuilder = import("./ActionBuilder.js").default;
36
40
  export type ActionRunnerOptions = {
37
41
  /**
38
42
  * Logger function.
@@ -1 +1 @@
1
- {"version":3,"file":"ActionRunner.d.ts","sourceRoot":"","sources":["../../../browser/lib/ActionRunner.js"],"names":[],"mappings":"AAKA;;GAEG;AAEH;;;GAGG;AACH;;;;;;GAMG;AACH;IAaE;;;;;OAKG;IACH,2BAHW,OAAO,oBAAoB,EAAE,OAAO,GAAC,IAAI,cACzC,mBAAmB,EAkB7B;IAED;;;;;;;;OAQG;IACH,aAJW,OAAO,GACL,OAAO,CAAC,OAAO,CAAC,CAuG5B;;CA0FF;sBA1PY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI;;;;;;;kBAH7D,YAAY"}
1
+ {"version":3,"file":"ActionRunner.d.ts","sourceRoot":"","sources":["../../../browser/lib/ActionRunner.js"],"names":[],"mappings":"AAKA;;GAEG;AAEH;;GAEG;AAEH;;;GAGG;AACH;;;;;;GAMG;AACH;IAaE;;;;;OAKG;IACH,2BAHW,OAAO,oBAAoB,EAAE,OAAO,GAAC,IAAI,cACzC,mBAAmB,EAkB7B;IAED;;;;;;;;OAQG;IACH,aAJW,OAAO,GACL,OAAO,CAAC,OAAO,CAAC,CAgH5B;;CA0FF;sBAvQY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI;4BAIlE,OAAO,oBAAoB,EAAE,OAAO;;;;;;;kBAP/B,YAAY"}
@@ -8,7 +8,7 @@
8
8
  * @property {(message: string, level?: number, ...args: Array<unknown>) => void} [debug] Optional logger reference.
9
9
  */
10
10
  /**
11
- * @typedef {Generator<Activity, void, unknown>} ActivityIterator
11
+ * @typedef {import("@gesslar/toolkit").Generator<Activity, void, unknown>} ActivityIterator
12
12
  */
13
13
  /**
14
14
  * Thin wrapper that materialises {@link Activity} instances on demand.
@@ -19,7 +19,7 @@ export default class ActionWrapper {
19
19
  *
20
20
  * @param {{activities: Map<string|symbol, WrappedActivityConfig>, debug: (message: string, level?: number, ...args: Array<unknown>) => void}} init Builder payload containing activities + logger.
21
21
  */
22
- constructor({ activities, hooks, debug }: {
22
+ constructor({ activities, hooks, debug, done: doneCallback }: {
23
23
  activities: Map<string | symbol, WrappedActivityConfig>;
24
24
  debug: (message: string, level?: number, ...args: Array<unknown>) => void;
25
25
  });
@@ -29,6 +29,12 @@ export default class ActionWrapper {
29
29
  * @returns {ActivityIterator} Lazy iterator yielding Activity instances.
30
30
  */
31
31
  get activities(): ActivityIterator;
32
+ /**
33
+ * Get the done callback if registered.
34
+ *
35
+ * @returns {((context: unknown) => unknown|Promise<unknown>)|null} Done callback or null.
36
+ */
37
+ get done(): ((context: unknown) => unknown | Promise<unknown>) | null;
32
38
  #private;
33
39
  }
34
40
  export type WrappedActivityConfig = {
@@ -57,6 +63,6 @@ export type WrappedActivityConfig = {
57
63
  */
58
64
  debug?: ((message: string, level?: number, ...args: Array<unknown>) => void) | undefined;
59
65
  };
60
- export type ActivityIterator = Generator<Activity, void, unknown>;
66
+ export type ActivityIterator = import("@gesslar/toolkit").Generator<Activity, void, unknown>;
61
67
  import Activity from "./Activity.js";
62
68
  //# sourceMappingURL=ActionWrapper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ActionWrapper.d.ts","sourceRoot":"","sources":["../../../browser/lib/ActionWrapper.js"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAEH;;GAEG;AAEH;;GAEG;AACH;IAgBE;;;;OAIG;IACH,0CAFW;QAAC,UAAU,EAAE,GAAG,CAAC,MAAM,GAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;QAAC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI,CAAA;KAAC,EAW5I;IAOD;;;;OAIG;IACH,kBAFa,gBAAgB,CAI5B;;CACF;;;;;UA5Da,MAAM,GAAC,MAAM;;;;QACb,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,GAAC,OAAO,CAAC,OAAO,CAAC,GAAC,aAAa;;;;;;;;sBAElD,OAAO,KAAK,OAAO,GAAC,OAAO,CAAC,OAAO,CAAC;;;;aAC9C,OAAO;;;;uBACG,MAAM,UAAU,MAAM,WAAW,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI;;+BAInE,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC;qBAb1B,eAAe"}
1
+ {"version":3,"file":"ActionWrapper.d.ts","sourceRoot":"","sources":["../../../browser/lib/ActionWrapper.js"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAEH;;GAEG;AAEH;;GAEG;AACH;IAkBE;;;;OAIG;IACH,8DAFW;QAAC,UAAU,EAAE,GAAG,CAAC,MAAM,GAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;QAAC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI,CAAA;KAAC,EAY5I;IAOD;;;;OAIG;IACH,kBAFa,gBAAgB,CAI5B;IAED;;;;OAIG;IACH,YAFa,CAAC,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,GAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAC,IAAI,CAIjE;;CACF;;;;;UAxEa,MAAM,GAAC,MAAM;;;;QACb,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,GAAC,OAAO,CAAC,OAAO,CAAC,GAAC,aAAa;;;;;;;;sBAElD,OAAO,KAAK,OAAO,GAAC,OAAO,CAAC,OAAO,CAAC;;;;aAC9C,OAAO;;;;uBACG,MAAM,UAAU,MAAM,WAAW,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI;;+BAInE,OAAO,kBAAkB,EAAE,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC;qBAbrD,eAAe"}
@@ -112,6 +112,13 @@ export default class ActionBuilder {
112
112
  * @returns {ActionBuilder} The builder instance for chaining.
113
113
  */
114
114
  withAction(action: ActionBuilderAction): ActionBuilder
115
+ /**
116
+ * Register a callback to be executed after all activities complete.
117
+ *
118
+ * @param {ActionFunction} callback Function to execute at the end of the pipeline.
119
+ * @returns {ActionBuilder} The builder instance for chaining.
120
+ */
121
+ done(callback: ActionFunction): ActionBuilder
115
122
  /**
116
123
  * Finalises the builder and returns a payload that can be consumed by the
117
124
  * runner.
@@ -14,6 +14,13 @@
14
14
  * Inherits all browser functionality and adds FileObject-based hook import capability.
15
15
  */
16
16
  export default class ActionHooks extends BrowserActionHooks {
17
+ /**
18
+ * @typedef {object} ActionHooksConfig
19
+ * @property {string} [hooksFile] Path to the hooks file
20
+ * @property {string} [hooksKind] Name of the hooks class to instantiate
21
+ * @property {object} [hooks] Pre-instantiated hooks object
22
+ * @property {number} [timeout] Timeout for hook execution
23
+ */
17
24
  /**
18
25
  * Static factory method to create and initialize a hook manager.
19
26
  * Loads hooks from the specified file and returns an initialized instance.
@@ -23,7 +30,24 @@ export default class ActionHooks extends BrowserActionHooks {
23
30
  * @param {DebugFn} debug The debug function.
24
31
  * @returns {Promise<ActionHooks|null>} Initialized hook manager or null if no hooks found
25
32
  */
26
- static "new"(config: ActionHooksConfig, debug: DebugFn): Promise<ActionHooks | null>;
33
+ static "new"(config: {
34
+ /**
35
+ * Path to the hooks file
36
+ */
37
+ hooksFile?: string | undefined;
38
+ /**
39
+ * Name of the hooks class to instantiate
40
+ */
41
+ hooksKind?: string | undefined;
42
+ /**
43
+ * Pre-instantiated hooks object
44
+ */
45
+ hooks?: object | undefined;
46
+ /**
47
+ * Timeout for hook execution
48
+ */
49
+ timeout?: number | undefined;
50
+ }, debug: DebugFn): Promise<ActionHooks | null>;
27
51
  /**
28
52
  * Creates a new ActionHook instance.
29
53
  *
@@ -1 +1 @@
1
- {"version":3,"file":"ActionHooks.d.ts","sourceRoot":"","sources":["../../lib/ActionHooks.js"],"names":[],"mappings":"AAGA;;GAEG;AAEH;;;;;;;GAOG;AAEH;;;GAGG;AACH;IAuBE;;;;;;;;OAQG;IACH,qBAJW,iBAAiB,SACjB,OAAO,GACL,OAAO,CAAC,WAAW,GAAC,IAAI,CAAC,CAgDrC;IA1ED;;;;OAIG;IACH,kEAFW,qBAAqB,EAK/B;IAED;;;;OAIG;IACH,iBAFa,UAAU,CAItB;;CA2DF;sBAhGY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI;;;;;gBAKjE,MAAM;;;;;;;;YAEN,OAAO;;;;;;;;WAEP,OAAO;;kDAZ2B,qBAAqB;2BADtC,kBAAkB"}
1
+ {"version":3,"file":"ActionHooks.d.ts","sourceRoot":"","sources":["../../lib/ActionHooks.js"],"names":[],"mappings":"AAGA;;GAEG;AAEH;;;;;;;GAOG;AAEH;;;GAGG;AACH;IAuBE;;;;;;OAMG;IAEH;;;;;;;;OAQG;IACH;;;;;;;;;;;;;;;;;cAHW,OAAO,GACL,OAAO,CAAC,WAAW,GAAC,IAAI,CAAC,CAgDrC;IAlFD;;;;OAIG;IACH,kEAFW,qBAAqB,EAK/B;IAED;;;;OAIG;IACH,iBAFa,UAAU,CAItB;;CAmEF;sBAxGY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI;;;;;gBAKjE,MAAM;;;;;;;;YAEN,OAAO;;;;;;;;WAEP,OAAO;;kDAZ2B,qBAAqB;2BADtC,kBAAkB"}
@@ -19,7 +19,7 @@ export default class ActionWrapper {
19
19
  *
20
20
  * @param {{activities: Map<string|symbol, WrappedActivityConfig>, debug: (message: string, level?: number, ...args: Array<unknown>) => void}} init Builder payload containing activities + logger.
21
21
  */
22
- constructor({ activities, hooks, debug }: {
22
+ constructor({ activities, hooks, debug, done: doneCallback }: {
23
23
  activities: Map<string | symbol, WrappedActivityConfig>;
24
24
  debug: (message: string, level?: number, ...args: Array<unknown>) => void;
25
25
  })
@@ -29,6 +29,12 @@ export default class ActionWrapper {
29
29
  * @returns {ActivityIterator} Lazy iterator yielding Activity instances.
30
30
  */
31
31
  get activities(): ActivityIterator
32
+ /**
33
+ * Get the done callback if registered.
34
+ *
35
+ * @returns {((context: unknown) => unknown|Promise<unknown>)|null} Done callback or null.
36
+ */
37
+ get done(): ((context: unknown) => unknown | Promise<unknown>) | null
32
38
  #private
33
39
  }
34
40
  export type WrappedActivityConfig = {