@cldmv/slothlet-types 3.15.3 → 3.16.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/lib/builders/api-assignment.d.mts +125 -4
- package/lib/builders/api_builder.d.mts +104 -7
- package/lib/builders/builder.d.mts +82 -1
- package/lib/builders/modes-processor.d.mts +66 -3
- package/lib/errors.d.mts +114 -19
- package/lib/factories/component-base.d.mts +171 -8
- package/lib/factories/context.d.mts +22 -4
- package/lib/handlers/api-cache-manager.d.mts +209 -20
- package/lib/handlers/api-manager.d.mts +539 -38
- package/lib/handlers/context-async.d.mts +92 -25
- package/lib/handlers/context-live.d.mts +117 -30
- package/lib/handlers/framework-internals.d.mts +33 -2
- package/lib/handlers/hook-manager.d.mts +306 -73
- package/lib/handlers/lifecycle-token.d.mts +48 -3
- package/lib/handlers/lifecycle.d.mts +86 -5
- package/lib/handlers/materialize-manager.d.mts +76 -8
- package/lib/handlers/metadata.d.mts +238 -18
- package/lib/handlers/module-manager.d.mts +169 -21
- package/lib/handlers/ownership.d.mts +376 -45
- package/lib/handlers/permission-manager.d.mts +283 -46
- package/lib/handlers/routine-manager.d.mts +425 -0
- package/lib/handlers/trusted-root.d.mts +45 -4
- package/lib/handlers/unified-wrapper.d.mts +287 -26
- package/lib/handlers/version-manager.d.mts +236 -29
- package/lib/helpers/caller-pinning.d.mts +21 -2
- package/lib/helpers/class-instance-wrapper.d.mts +56 -2
- package/lib/helpers/config.d.mts +311 -161
- package/lib/helpers/defaults.d.mts +39 -0
- package/lib/helpers/eventemitter-context.d.mts +29 -3
- package/lib/helpers/eventtarget-context.d.mts +19 -1
- package/lib/helpers/eventtarget-property-context.d.mts +21 -0
- package/lib/helpers/generate-manifest.d.mts +174 -7
- package/lib/helpers/hint-detector.d.mts +22 -2
- package/lib/helpers/manifest-resolver.d.mts +100 -1
- package/lib/helpers/modes-utils.d.mts +30 -3
- package/lib/helpers/module-discovery.d.mts +80 -7
- package/lib/helpers/module-manifest-validator.d.mts +36 -13
- package/lib/helpers/module-sort.d.mts +64 -1
- package/lib/helpers/observer-context.d.mts +21 -0
- package/lib/helpers/pattern-matcher.d.mts +43 -3
- package/lib/helpers/platform.d.mts +109 -10
- package/lib/helpers/resolve-from-caller.d.mts +27 -3
- package/lib/helpers/sanitize.d.mts +92 -4
- package/lib/helpers/scheduler-context.d.mts +21 -1
- package/lib/helpers/utilities.d.mts +52 -4
- package/lib/i18n/translations.d.mts +50 -5
- package/lib/modes/eager.d.mts +46 -8
- package/lib/modes/lazy.d.mts +57 -10
- package/lib/processors/flatten.d.mts +116 -56
- package/lib/processors/loader.d.mts +77 -10
- package/lib/processors/type-generator.d.mts +16 -2
- package/lib/processors/typescript.d.mts +169 -13
- package/lib/runtime/runtime-asynclocalstorage.d.mts +71 -3
- package/lib/runtime/runtime-livebindings.d.mts +37 -2
- package/lib/runtime/runtime.d.mts +39 -3
- package/lib/typegen/typegen.d.mts +34 -2
- package/package.json +5 -23
- package/slothlet.d.mts +428 -3
|
@@ -1,5 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manages hooks for API function interception.
|
|
3
|
+
* Supports before/after/always/error hooks with pattern matching and priority ordering.
|
|
4
|
+
*
|
|
5
|
+
* @class HookManager
|
|
6
|
+
* @extends ComponentBase
|
|
7
|
+
*/
|
|
1
8
|
export class HookManager extends ComponentBase {
|
|
9
|
+
/**
|
|
10
|
+
* Property name for auto-discovery
|
|
11
|
+
* @type {string}
|
|
12
|
+
* @static
|
|
13
|
+
*/
|
|
2
14
|
static slothletProperty: string;
|
|
15
|
+
/**
|
|
16
|
+
* Creates a new HookManager instance.
|
|
17
|
+
* @param {object} slothlet - Parent slothlet instance
|
|
18
|
+
*/
|
|
19
|
+
constructor(slothlet: object);
|
|
3
20
|
enabled: boolean;
|
|
4
21
|
defaultPattern: string;
|
|
5
22
|
suppressErrors: boolean;
|
|
@@ -9,80 +26,296 @@ export class HookManager extends ComponentBase {
|
|
|
9
26
|
hooks: Map<any, any>;
|
|
10
27
|
registrationOrder: number;
|
|
11
28
|
reportedErrors: WeakSet<object>;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Register a hook for API functions.
|
|
31
|
+
*
|
|
32
|
+
* @param {string} typePattern - Path pattern then hook type, `"pattern:type"` (e.g. `"math.*:before"`).
|
|
33
|
+
* The legacy `"type:pattern"` form (e.g. `"before:math.*"`) is still accepted but deprecated.
|
|
34
|
+
* @param {function} handler - Hook handler function
|
|
35
|
+
* @param {object} [options={}] - Hook options
|
|
36
|
+
* @param {string} [options.id] - Unique identifier (auto-generated if not provided)
|
|
37
|
+
* @param {number} [options.priority=0] - Higher = earlier execution
|
|
38
|
+
* @param {string} [options.subset=DEFAULT_HOOK_SUBSET] - Phase: "before", "primary", or "after" ({@link HOOK_SUBSETS})
|
|
39
|
+
* @param {boolean} [options.lockCaller=true] - Pin the registering module's caller
|
|
40
|
+
* identity onto the handler so its `self.*` calls and permission checks are
|
|
41
|
+
* attributed to the module that registered the hook, not the caller whose API
|
|
42
|
+
* call triggered it. On by default; pass `false` to opt out — the handler then
|
|
43
|
+
* runs un-pinned, with whatever async context is ambient when it fires (for a
|
|
44
|
+
* `before` hook, typically none, so a `self.*` call inside it has no context).
|
|
45
|
+
* No effect when the hook is registered outside a module (no caller identity to
|
|
46
|
+
* capture) or when `handler` is already a `lockCaller`-wrapped function.
|
|
47
|
+
* @returns {string} Hook ID
|
|
48
|
+
* @public
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* hookManager.on("math.*:before", ({ args }) => {
|
|
52
|
+
* console.log("Args:", args);
|
|
53
|
+
* return args;
|
|
54
|
+
* }, { priority: 100 });
|
|
55
|
+
*/
|
|
56
|
+
public on(typePattern: string, handler: Function, options?: {
|
|
57
|
+
id?: string | undefined;
|
|
58
|
+
priority?: number | undefined;
|
|
59
|
+
subset?: string | undefined;
|
|
60
|
+
lockCaller?: boolean | undefined;
|
|
61
|
+
}): string;
|
|
62
|
+
/**
|
|
63
|
+
* Remove hooks matching filter criteria.
|
|
64
|
+
*
|
|
65
|
+
* @param {object} [filter={}] - Filter criteria
|
|
66
|
+
* @param {string} [filter.id] - Remove hook by ID
|
|
67
|
+
* @param {string} [filter.type] - Remove hooks by type
|
|
68
|
+
* @param {string} [filter.pattern] - Remove hooks matching pattern
|
|
69
|
+
* @returns {number} Number of hooks removed
|
|
70
|
+
* @public
|
|
71
|
+
*/
|
|
72
|
+
public remove(filter?: {
|
|
73
|
+
id?: string | undefined;
|
|
74
|
+
type?: string | undefined;
|
|
75
|
+
pattern?: string | undefined;
|
|
76
|
+
}): number;
|
|
77
|
+
/**
|
|
78
|
+
* Enable hooks matching filter criteria.
|
|
79
|
+
*
|
|
80
|
+
* @param {object|string} [filter={}] - Filter criteria (empty = enable all, string = pattern)
|
|
81
|
+
* @param {string} [filter.id] - Enable hook by ID
|
|
82
|
+
* @param {string} [filter.type] - Enable hooks by type
|
|
83
|
+
* @param {string} [filter.pattern] - Enable hooks matching pattern
|
|
84
|
+
* @returns {number} Number of hooks enabled
|
|
85
|
+
* @public
|
|
86
|
+
*/
|
|
87
|
+
public enable(filter?: object | string): number;
|
|
88
|
+
/**
|
|
89
|
+
* Disable hooks matching filter criteria.
|
|
90
|
+
*
|
|
91
|
+
* @param {object|string} [filter={}] - Filter criteria (empty = disable all, string = pattern)
|
|
92
|
+
* @param {string} [filter.id] - Disable hook by ID
|
|
93
|
+
* @param {string} [filter.type] - Disable hooks by type
|
|
94
|
+
* @param {string} [filter.pattern] - Disable hooks matching pattern
|
|
95
|
+
* @returns {number} Number of hooks disabled
|
|
96
|
+
* @public
|
|
97
|
+
*/
|
|
98
|
+
public disable(filter?: object | string): number;
|
|
99
|
+
/**
|
|
100
|
+
* Restrict hook execution to a path pattern at runtime (the global path filter).
|
|
101
|
+
*
|
|
102
|
+
* Distinct from {@link enable}/{@link disable}, which toggle the `enabled` flag of
|
|
103
|
+
* individual registered hooks by their registration pattern. This narrows *which API
|
|
104
|
+
* paths* the hook system applies to at all — the runtime counterpart of the `hook.pattern`
|
|
105
|
+
* config. Once any pattern is enabled the filter is active, and a hook fires only when the
|
|
106
|
+
* called path matches at least one enabled pattern. Adding `"**"` matches every path.
|
|
107
|
+
*
|
|
108
|
+
* @param {string} pattern - Glob path pattern to restrict execution to (e.g. "math.*").
|
|
109
|
+
* @returns {number} The number of patterns now in the active filter.
|
|
110
|
+
* @public
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* api.slothlet.hook.enablePattern("database.*"); // only intercept database.* paths
|
|
114
|
+
*/
|
|
115
|
+
public enablePattern(pattern: string): number;
|
|
116
|
+
/**
|
|
117
|
+
* Remove a path pattern from the runtime global path filter.
|
|
118
|
+
*
|
|
119
|
+
* When the last enabled pattern is removed the filter deactivates, so hooks once again
|
|
120
|
+
* apply to every path (an unrestricted state, matching a `"**"` default).
|
|
121
|
+
*
|
|
122
|
+
* @param {string} pattern - The previously-enabled path pattern to remove.
|
|
123
|
+
* @returns {number} The number of patterns remaining in the filter.
|
|
124
|
+
* @public
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* api.slothlet.hook.disablePattern("database.*"); // stop restricting to database.*
|
|
128
|
+
*/
|
|
129
|
+
public disablePattern(pattern: string): number;
|
|
130
|
+
/**
|
|
131
|
+
* Reset the runtime global path filter back to the configured `hook.pattern` default.
|
|
132
|
+
*
|
|
133
|
+
* Clears any runtime {@link enablePattern}/{@link disablePattern} changes. If the configured
|
|
134
|
+
* default is the catch-all `"**"` the filter ends up inactive (unrestricted); otherwise it is
|
|
135
|
+
* re-seeded with the configured pattern.
|
|
136
|
+
*
|
|
137
|
+
* @returns {void}
|
|
138
|
+
* @public
|
|
139
|
+
*/
|
|
140
|
+
public resetPatternFilter(): void;
|
|
141
|
+
/**
|
|
142
|
+
* Set the pin-enforcement policy at runtime (backs `api.slothlet.hook.pin.enable`/`disable`).
|
|
143
|
+
* When true (the default) module hooks are force-pinned to their owner; false permits a
|
|
144
|
+
* per-registration `lockCaller: false`. The public wrapper is host-only when permissions are
|
|
145
|
+
* enabled — `slothlet.hook.pin.*` falls under the `slothlet.hook.**` deny baseline.
|
|
146
|
+
*
|
|
147
|
+
* @param {boolean} value - True to enforce pinning (force-pin module hooks), false to permit unpinned.
|
|
148
|
+
* @returns {boolean} The policy value now in effect.
|
|
149
|
+
* @public
|
|
150
|
+
*/
|
|
151
|
+
public setPinEnforced(value: boolean): boolean;
|
|
152
|
+
/**
|
|
153
|
+
* List registered hooks matching filter criteria.
|
|
154
|
+
*
|
|
155
|
+
* @param {object|string} [filter={}] - Filter criteria (empty = list all), type string, or pattern string
|
|
156
|
+
* @param {string} [filter.id] - List hook by ID
|
|
157
|
+
* @param {string} [filter.type] - List hooks by type
|
|
158
|
+
* @param {string} [filter.pattern] - List hooks matching pattern
|
|
159
|
+
* @param {boolean} [filter.enabled] - Filter by enabled state
|
|
160
|
+
* @returns {object} Object with registeredHooks array property
|
|
161
|
+
* @public
|
|
162
|
+
*/
|
|
163
|
+
public list(filter?: object | string): object;
|
|
164
|
+
/**
|
|
165
|
+
* Get hooks for a specific API path and type.
|
|
166
|
+
* Used internally by UnifiedWrapper.
|
|
167
|
+
*
|
|
168
|
+
* @param {string} type - Hook type (before/after/always/error)
|
|
169
|
+
* @param {string} apiPath - API path (e.g., "math.add")
|
|
170
|
+
* @returns {Array<object>} Sorted array of matching hooks
|
|
171
|
+
* @public
|
|
172
|
+
*/
|
|
173
|
+
public getHooksForPath(type: string, apiPath: string): Array<object>;
|
|
174
|
+
/**
|
|
175
|
+
* Derive the dispatch strategy for a path from the current hook set.
|
|
176
|
+
*
|
|
177
|
+
* @param {string} path - API path about to be called
|
|
178
|
+
* @returns {{asyncBefore: boolean, asyncAfter: boolean}} Whether any matching transforming
|
|
179
|
+
* hook is asynchronous.
|
|
180
|
+
* @public
|
|
181
|
+
*
|
|
182
|
+
* @description
|
|
183
|
+
* The strategy is a property of the CALL, derived per invocation from the registration state —
|
|
184
|
+
* never baked onto the leaf, so removing an async hook returns the path to synchronous
|
|
185
|
+
* dispatch. Only TRANSFORMING hooks (before/after) are consulted: `always` and `error` are
|
|
186
|
+
* observers whose return values are never consumed, so they never force promotion. Cached per
|
|
187
|
+
* path behind the registry epoch; the hot-path cost is one integer compare.
|
|
188
|
+
*/
|
|
189
|
+
public getDispatchStrategy(path: string): {
|
|
190
|
+
asyncBefore: boolean;
|
|
191
|
+
asyncAfter: boolean;
|
|
30
192
|
};
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
193
|
+
/**
|
|
194
|
+
* Execute before hooks for an API path.
|
|
195
|
+
*
|
|
196
|
+
* @param {string} path - API path being called
|
|
197
|
+
* @param {Array} args - Function arguments
|
|
198
|
+
* @param {object} api - Bound API object
|
|
199
|
+
* @param {object} ctx - User context object
|
|
200
|
+
* @returns {object} Result object: { args, shortCircuit, value }
|
|
201
|
+
* @public
|
|
202
|
+
*/
|
|
203
|
+
public executeBeforeHooks(path: string, args: any[], api: object, ctx: object): object;
|
|
204
|
+
/**
|
|
205
|
+
* Execute after hooks for an API path.
|
|
206
|
+
*
|
|
207
|
+
* @param {string} path - API path being called
|
|
208
|
+
* @param {*} result - Function return value
|
|
209
|
+
* @param {Array} args - Original function arguments
|
|
210
|
+
* @param {object} api - Bound API object
|
|
211
|
+
* @param {object} ctx - User context object
|
|
212
|
+
* @returns {HookExecutionResult} Object indicating if result was modified and the final result
|
|
213
|
+
* @public
|
|
214
|
+
*/
|
|
215
|
+
public executeAfterHooks(path: string, result: any, args: any[], api: object, ctx: object): HookExecutionResult;
|
|
216
|
+
/**
|
|
217
|
+
* Execute before hooks asynchronously — the promoted-pipeline twin of
|
|
218
|
+
* {@link executeBeforeHooks}.
|
|
219
|
+
*
|
|
220
|
+
* @param {string} path - API path being called
|
|
221
|
+
* @param {Array} args - Function arguments
|
|
222
|
+
* @param {object} api - Bound API object
|
|
223
|
+
* @param {object} ctx - User context object
|
|
224
|
+
* @returns {Promise<object>} Result object: { args, shortCircuit, value }
|
|
225
|
+
* @public
|
|
226
|
+
*
|
|
227
|
+
* @description
|
|
228
|
+
* Same protocol and strict registration order as the sync variant, with one difference: a
|
|
229
|
+
* handler's thenable return is AWAITED rather than refused — the caller of a promoted path
|
|
230
|
+
* already receives a Promise, so awaiting the chain changes nothing observable. A synchronous
|
|
231
|
+
* handler's return is used as-is (no microtask tick is inserted for it).
|
|
232
|
+
*/
|
|
233
|
+
public executeBeforeHooksAsync(path: string, args: any[], api: object, ctx: object): Promise<object>;
|
|
234
|
+
/**
|
|
235
|
+
* Execute after hooks asynchronously — the promoted-pipeline twin of
|
|
236
|
+
* {@link executeAfterHooks}.
|
|
237
|
+
*
|
|
238
|
+
* @param {string} path - API path being called
|
|
239
|
+
* @param {*} result - Function return value (already settled)
|
|
240
|
+
* @param {Array} args - Original function arguments
|
|
241
|
+
* @param {object} api - Bound API object
|
|
242
|
+
* @param {object} ctx - User context object
|
|
243
|
+
* @returns {Promise<HookExecutionResult>} Object indicating if result was modified and the final result
|
|
244
|
+
* @public
|
|
245
|
+
*
|
|
246
|
+
* @description
|
|
247
|
+
* Same protocol and ordering as the sync variant; a thenable transform is awaited (that is the
|
|
248
|
+
* cell this pipeline exists for) and a synchronous transform costs no microtask tick.
|
|
249
|
+
*/
|
|
250
|
+
public executeAfterHooksAsync(path: string, result: any, args: any[], api: object, ctx: object): Promise<HookExecutionResult>;
|
|
251
|
+
/**
|
|
252
|
+
* Execute always hooks for an API path.
|
|
253
|
+
*
|
|
254
|
+
* @param {string} path - API path being called
|
|
255
|
+
* @param {Array} args - Function arguments
|
|
256
|
+
* @param {*} resultOrError - Function result or error
|
|
257
|
+
* @param {boolean} hasError - Whether an error occurred
|
|
258
|
+
* @param {Array<Error>} errors - Array of errors that occurred
|
|
259
|
+
* @param {object} api - Bound API object
|
|
260
|
+
* @param {object} ctx - User context object
|
|
261
|
+
* @public
|
|
262
|
+
*/
|
|
263
|
+
public executeAlwaysHooks(path: string, args: any[], resultOrError: any, hasError: boolean | undefined, errors: Array<Error> | undefined, api: object, ctx: object): void;
|
|
264
|
+
/**
|
|
265
|
+
* Execute error hooks for an API path.
|
|
266
|
+
*
|
|
267
|
+
* @param {string} path - API path being called
|
|
268
|
+
* @param {Error} error - The error that occurred
|
|
269
|
+
* @param {object} source - Error source info with type, hookTag, hookId, timestamp, stack
|
|
270
|
+
* @param {Array} args - Function arguments
|
|
271
|
+
* @param {object} api - Bound API object
|
|
272
|
+
* @param {object} ctx - User context object
|
|
273
|
+
* @public
|
|
274
|
+
*/
|
|
275
|
+
public executeErrorHooks(path: string, error: Error, source: object, args: any[], api: object, ctx: object): void;
|
|
276
|
+
/**
|
|
277
|
+
* Get the pattern compilation function for diagnostic purposes.
|
|
278
|
+
* Only exposed when diagnostics mode is enabled.
|
|
279
|
+
*
|
|
280
|
+
* @returns {function} The pattern compilation function
|
|
281
|
+
* @internal
|
|
282
|
+
*/
|
|
283
|
+
getCompilePatternForDiagnostics(): Function;
|
|
284
|
+
/**
|
|
285
|
+
* Export all registered hooks (including handler closures) so they can be
|
|
286
|
+
* re-registered on a fresh HookManager instance after a full reload.
|
|
287
|
+
*
|
|
288
|
+
* @returns {Array<object>} Snapshot of all current hook registrations.
|
|
289
|
+
* @public
|
|
290
|
+
*/
|
|
291
|
+
public exportHooks(): Array<object>;
|
|
292
|
+
/**
|
|
293
|
+
* Re-register hooks exported by {@link exportHooks} into this (new) instance.
|
|
294
|
+
* Called after a full `api.slothlet.reload()` to restore user-registered hooks.
|
|
295
|
+
*
|
|
296
|
+
* @param {Array<object>} registrations - Snapshot returned by exportHooks().
|
|
297
|
+
* @returns {void}
|
|
298
|
+
* @public
|
|
299
|
+
*/
|
|
300
|
+
public importHooks(registrations: Array<object>): void;
|
|
301
|
+
/**
|
|
302
|
+
* Cleanup hook manager on shutdown.
|
|
303
|
+
* @public
|
|
304
|
+
*/
|
|
305
|
+
public shutdown(): Promise<void>;
|
|
86
306
|
#private;
|
|
87
307
|
}
|
|
308
|
+
/**
|
|
309
|
+
* Result returned by hook execution methods.
|
|
310
|
+
*/
|
|
311
|
+
export type HookExecutionResult = {
|
|
312
|
+
/**
|
|
313
|
+
* - Whether any hook modified the result value.
|
|
314
|
+
*/
|
|
315
|
+
modified: boolean;
|
|
316
|
+
/**
|
|
317
|
+
* - The final (possibly hook-modified) return value.
|
|
318
|
+
*/
|
|
319
|
+
result?: any;
|
|
320
|
+
};
|
|
88
321
|
import { ComponentBase } from "#factories/component-base";
|
|
@@ -1,3 +1,48 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Registers a Slothlet instance and creates its per-instance lifecycle capability token.
|
|
3
|
+
*
|
|
4
|
+
* Safe to call multiple times on the same instance (idempotent) — subsequent calls are
|
|
5
|
+
* silently ignored, preserving the original token. This handles the reload code path where
|
|
6
|
+
* `load()` is called again on the same Slothlet object.
|
|
7
|
+
*
|
|
8
|
+
* @param {object} slothlet - The Slothlet instance to register.
|
|
9
|
+
* @returns {void}
|
|
10
|
+
* @package
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* // Called once (or on reload) in Slothlet.load():
|
|
14
|
+
* registerInstance(this);
|
|
15
|
+
*/
|
|
16
|
+
export function registerInstance(slothlet: object): void;
|
|
17
|
+
/**
|
|
18
|
+
* Returns the per-instance capability token for the given Slothlet instance.
|
|
19
|
+
*
|
|
20
|
+
* Used internally by `lifecycle.mjs` (emit dispatch) and `modes-processor.mjs`
|
|
21
|
+
* (direct tagSystemMetadata call for folder wrappers). Requires a live registered
|
|
22
|
+
* Slothlet instance — cannot be exploited without one.
|
|
23
|
+
*
|
|
24
|
+
* @param {object} slothlet - A registered Slothlet instance.
|
|
25
|
+
* @returns {symbol|undefined} The instance token, or undefined if not registered.
|
|
26
|
+
* @package
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* handler(data, getInstanceToken(this.slothlet));
|
|
30
|
+
*/
|
|
31
|
+
export function getInstanceToken(slothlet: object): symbol | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* Verifies that `token` is the registered capability token for the given Slothlet instance.
|
|
34
|
+
*
|
|
35
|
+
* Used by `metadata.mjs` inside `tagSystemMetadata()` to reject calls that did not
|
|
36
|
+
* originate from the internal lifecycle dispatch path.
|
|
37
|
+
*
|
|
38
|
+
* @param {object} slothlet - A registered Slothlet instance.
|
|
39
|
+
* @param {*} token - The token value to verify.
|
|
40
|
+
* @returns {boolean} `true` only if `token` is the exact Symbol registered for `slothlet`.
|
|
41
|
+
* @package
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* if (!verifyToken(this.slothlet, token)) {
|
|
45
|
+
* throw new this.SlothletError("METADATA_LIFECYCLE_BYPASS", ...);
|
|
46
|
+
* }
|
|
47
|
+
*/
|
|
48
|
+
export function verifyToken(slothlet: object, token: any): boolean;
|
|
@@ -1,12 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lifecycle event manager for impl changes
|
|
3
|
+
* @extends ComponentBase
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
1
6
|
export class Lifecycle extends ComponentBase {
|
|
7
|
+
/**
|
|
8
|
+
* Where this component should be mounted on the Slothlet instance
|
|
9
|
+
* @type {string}
|
|
10
|
+
*/
|
|
2
11
|
static slothletProperty: string;
|
|
12
|
+
/**
|
|
13
|
+
* @param {object} slothlet - Slothlet instance
|
|
14
|
+
*/
|
|
15
|
+
constructor(slothlet: object);
|
|
3
16
|
subscribers: Map<any, any>;
|
|
4
17
|
eventLog: any[];
|
|
5
18
|
maxLogSize: number;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Subscribe to lifecycle event
|
|
21
|
+
* @param {string} event - Event name (impl:created, impl:changed, impl:removed, materialized:complete, path:collision)
|
|
22
|
+
* @param {Function} handler - Event handler function(eventData)
|
|
23
|
+
* @returns {Function} Unsubscribe function
|
|
24
|
+
* @public
|
|
25
|
+
*
|
|
26
|
+
* @description
|
|
27
|
+
* Subscribe to lifecycle events to react to impl changes.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* const unsubscribe = lifecycle.subscribe("impl:changed", (data) => {
|
|
31
|
+
* console.log("Impl changed:", data.apiPath, data.source);
|
|
32
|
+
* });
|
|
33
|
+
*/
|
|
34
|
+
public subscribe(event: string, handler: Function): Function;
|
|
35
|
+
/**
|
|
36
|
+
* Alias for subscribe() - standard EventEmitter pattern
|
|
37
|
+
* @param {string} event - Event name
|
|
38
|
+
* @param {Function} handler - Event handler function
|
|
39
|
+
* @returns {Function} Unsubscribe function
|
|
40
|
+
* @public
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* lifecycle.on('materialized:complete', (data) => {
|
|
44
|
+
* console.log(`${data.total} modules materialized`);
|
|
45
|
+
* });
|
|
46
|
+
*/
|
|
47
|
+
public on(event: string, handler: Function): Function;
|
|
48
|
+
/**
|
|
49
|
+
* Unsubscribe from lifecycle event - standard EventEmitter pattern
|
|
50
|
+
* @param {string} event - Event name
|
|
51
|
+
* @param {Function} handler - Event handler function to remove
|
|
52
|
+
* @public
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* const handler = (data) => console.log(data);
|
|
56
|
+
* lifecycle.on('impl:changed', handler);
|
|
57
|
+
* lifecycle.off('impl:changed', handler);
|
|
58
|
+
*/
|
|
59
|
+
public off(event: string, handler: Function): void;
|
|
60
|
+
/**
|
|
61
|
+
* Alias for off() - standard EventEmitter pattern
|
|
62
|
+
* @param {string} event - Event name
|
|
63
|
+
* @param {Function} handler - Event handler function to remove
|
|
64
|
+
* @public
|
|
65
|
+
*/
|
|
66
|
+
public unsubscribe(event: string, handler: Function): void;
|
|
67
|
+
/**
|
|
68
|
+
* Emit lifecycle event
|
|
69
|
+
* @param {string} event - Event name
|
|
70
|
+
* @param {object} data - Event data
|
|
71
|
+
* @private
|
|
72
|
+
*
|
|
73
|
+
* @description
|
|
74
|
+
* Emit event to all subscribers. Event data should include:
|
|
75
|
+
* - apiPath: API path where impl exists
|
|
76
|
+
* - impl: The implementation object
|
|
77
|
+
* - source: Source of event (initial, hot-reload, materialization, etc)
|
|
78
|
+
* - moduleID: Module identifier (if applicable)
|
|
79
|
+
* - filePath: File path (if applicable)
|
|
80
|
+
* - metadata: Additional metadata
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* lifecycle.emit("impl:created", {
|
|
84
|
+
* apiPath: "math.add",
|
|
85
|
+
* impl: addFunction,
|
|
86
|
+
* source: "initial",
|
|
87
|
+
* moduleID: "base_abc123",
|
|
88
|
+
* filePath: "/path/to/math.mjs"
|
|
89
|
+
* });
|
|
90
|
+
*/
|
|
91
|
+
private emit;
|
|
11
92
|
}
|
|
12
93
|
import { ComponentBase } from "#factories/component-base";
|
|
@@ -1,12 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manager for tracking lazy folder materialization state
|
|
3
|
+
* @class MaterializeManager
|
|
4
|
+
* @extends ComponentBase
|
|
5
|
+
* @package
|
|
6
|
+
*
|
|
7
|
+
* @description
|
|
8
|
+
* Provides access to lazy materialization state via `api.slothlet.materialize`.
|
|
9
|
+
* Tracks count of unmaterialized lazy folders and provides boolean state, statistics,
|
|
10
|
+
* and wait functionality for synchronization.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const api = await slothlet({ base: "./api", mode: "lazy" });
|
|
14
|
+
*
|
|
15
|
+
* // Check if fully materialized
|
|
16
|
+
* if (api.slothlet.materialize.materialized) {
|
|
17
|
+
* console.log("All lazy folders loaded!");
|
|
18
|
+
* }
|
|
19
|
+
*
|
|
20
|
+
* // Get statistics
|
|
21
|
+
* const stats = api.slothlet.materialize.get();
|
|
22
|
+
* console.log(`${stats.percentage}% loaded (${stats.remaining}/${stats.total} remaining)`);
|
|
23
|
+
*
|
|
24
|
+
* // Wait for full materialization
|
|
25
|
+
* await api.slothlet.materialize.wait();
|
|
26
|
+
*/
|
|
1
27
|
export class MaterializeManager extends ComponentBase {
|
|
2
28
|
static slothletProperty: string;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Create MaterializeManager instance
|
|
31
|
+
* @param {object} slothlet - Slothlet orchestrator instance
|
|
32
|
+
* @package
|
|
33
|
+
*/
|
|
34
|
+
constructor(slothlet: object);
|
|
35
|
+
/**
|
|
36
|
+
* Get materialization state as a boolean
|
|
37
|
+
* Returns true when all lazy wrappers have been materialized
|
|
38
|
+
* @returns {boolean} True if fully materialized, false if any lazy folders remain
|
|
39
|
+
* @public
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* if (api.slothlet.materialize.materialized) {
|
|
43
|
+
* console.log("API is fully loaded");
|
|
44
|
+
* }
|
|
45
|
+
*/
|
|
46
|
+
public get materialized(): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Get detailed materialization statistics
|
|
49
|
+
* @returns {Object} Statistics object with total, materialized, remaining, percentage
|
|
50
|
+
* @public
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* const stats = api.slothlet.materialize.get();
|
|
54
|
+
* // { total: 5, materialized: 3, remaining: 2, percentage: 60 }
|
|
55
|
+
*/
|
|
56
|
+
public get(): Object;
|
|
57
|
+
/**
|
|
58
|
+
* Wait for full materialization (all lazy folders loaded)
|
|
59
|
+
* Returns immediately if already fully materialized
|
|
60
|
+
* @returns {Promise<void>} Resolves when all lazy wrappers have materialized
|
|
61
|
+
* @public
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* // Wait for API to fully load
|
|
65
|
+
* await api.slothlet.materialize.wait();
|
|
66
|
+
* console.log("All modules loaded!");
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* // Wait with timeout
|
|
70
|
+
* const timeoutPromise = new Promise((_, reject) =>
|
|
71
|
+
* setTimeout(() => reject(new Error("Timeout")), 5000)
|
|
72
|
+
* );
|
|
73
|
+
* await Promise.race([
|
|
74
|
+
* api.slothlet.materialize.wait(),
|
|
75
|
+
* timeoutPromise
|
|
76
|
+
* ]);
|
|
77
|
+
*/
|
|
78
|
+
public wait(): Promise<void>;
|
|
11
79
|
}
|
|
12
80
|
import { ComponentBase } from "#factories/component-base";
|