@cldmv/slothlet 2.8.0 → 2.9.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.
Files changed (37) hide show
  1. package/AGENT-USAGE.md +1 -1
  2. package/README.md +253 -1578
  3. package/dist/lib/helpers/als-eventemitter.mjs +4 -5
  4. package/dist/lib/helpers/api_builder/add_api.mjs +237 -0
  5. package/dist/lib/helpers/api_builder/analysis.mjs +522 -0
  6. package/dist/lib/helpers/api_builder/construction.mjs +457 -0
  7. package/dist/lib/helpers/api_builder/decisions.mjs +737 -0
  8. package/dist/lib/helpers/api_builder.mjs +16 -1567
  9. package/dist/lib/helpers/utilities.mjs +121 -0
  10. package/dist/lib/runtime/runtime-asynclocalstorage.mjs +44 -17
  11. package/dist/lib/runtime/runtime-livebindings.mjs +18 -3
  12. package/dist/lib/runtime/runtime.mjs +3 -3
  13. package/dist/slothlet.mjs +146 -746
  14. package/docs/API-RULES-CONDITIONS.md +508 -0
  15. package/{API-RULES.md → docs/API-RULES.md} +127 -72
  16. package/package.json +11 -9
  17. package/types/dist/lib/helpers/als-eventemitter.d.mts.map +1 -1
  18. package/types/dist/lib/helpers/api_builder/add_api.d.mts +60 -0
  19. package/types/dist/lib/helpers/api_builder/add_api.d.mts.map +1 -0
  20. package/types/dist/lib/helpers/api_builder/analysis.d.mts +189 -0
  21. package/types/dist/lib/helpers/api_builder/analysis.d.mts.map +1 -0
  22. package/types/dist/lib/helpers/api_builder/construction.d.mts +107 -0
  23. package/types/dist/lib/helpers/api_builder/construction.d.mts.map +1 -0
  24. package/types/dist/lib/helpers/api_builder/decisions.d.mts +213 -0
  25. package/types/dist/lib/helpers/api_builder/decisions.d.mts.map +1 -0
  26. package/types/dist/lib/helpers/api_builder.d.mts +5 -448
  27. package/types/dist/lib/helpers/api_builder.d.mts.map +1 -1
  28. package/types/dist/lib/helpers/utilities.d.mts +120 -0
  29. package/types/dist/lib/helpers/utilities.d.mts.map +1 -0
  30. package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts +7 -0
  31. package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts.map +1 -1
  32. package/types/dist/lib/runtime/runtime-livebindings.d.mts +8 -0
  33. package/types/dist/lib/runtime/runtime-livebindings.d.mts.map +1 -1
  34. package/types/dist/slothlet.d.mts +0 -11
  35. package/types/dist/slothlet.d.mts.map +1 -1
  36. package/types/index.d.mts +0 -1
  37. package/API-RULES-CONDITIONS.md +0 -367
@@ -1,449 +1,6 @@
1
- /**
2
- * Analyzes a module and returns processing decisions that both eager and lazy modes can use.
3
- * This centralizes the module loading logic from _loadSingleModule while allowing each mode
4
- * to handle the results according to their strategy (immediate materialization vs proxy creation).
5
- * @function analyzeModule
6
- * @internal
7
- * @package
8
- * @param {string} modulePath - Absolute path to the module file
9
- * @param {object} options - Analysis options
10
- * @param {boolean} [options.debug=false] - Enable debug logging
11
- * @param {object} [options.instance] - Slothlet instance for accessing config and methods
12
- * @returns {Promise<{
13
- * rawModule: object,
14
- * processedModule: object,
15
- * isFunction: boolean,
16
- * hasDefault: boolean,
17
- * isCjs: boolean,
18
- * exports: Array<[string, any]>,
19
- * defaultExportType: 'function'|'object'|null,
20
- * shouldWrapAsCallable: boolean,
21
- * namedExports: object,
22
- * metadata: object
23
- * }>} Module analysis results
24
- * @example
25
- * // Analyze a module file
26
- * const analysis = await analyzeModule("./api/math.mjs", { instance });
27
- * // Eager mode: use analysis.processedModule directly
28
- * // Lazy mode: create proxy based on analysis.isFunction, analysis.exports, etc.
29
- */
30
- export function analyzeModule(modulePath: string, options?: {
31
- debug?: boolean;
32
- instance?: object;
33
- }): Promise<{
34
- rawModule: object;
35
- processedModule: object;
36
- isFunction: boolean;
37
- hasDefault: boolean;
38
- isCjs: boolean;
39
- exports: Array<[string, any]>;
40
- defaultExportType: "function" | "object" | null;
41
- shouldWrapAsCallable: boolean;
42
- namedExports: object;
43
- metadata: object;
44
- }>;
45
- /**
46
- * Processes module analysis results into a final module object using slothlet's established patterns.
47
- * This centralizes the processing logic while allowing both modes to apply the results differently.
48
- * @function processModuleFromAnalysis
49
- * @internal
50
- * @package
51
- * @param {object} analysis - Results from analyzeModule
52
- * @param {object} options - Processing options
53
- * @param {object} [options.instance] - Slothlet instance for accessing _toapiPathKey method
54
- * @param {boolean} [options.debug=false] - Enable debug logging
55
- * @returns {object} Processed module ready for API integration
56
- * @example
57
- * // Process analyzed module
58
- * const analysis = await analyzeModule(modulePath, { instance });
59
- * const processed = processModuleFromAnalysis(analysis, { instance });
60
- * // Both modes can use 'processed' but integrate it differently
61
- */
62
- export function processModuleFromAnalysis(analysis: object, options?: {
63
- instance?: object;
64
- debug?: boolean;
65
- }): object;
66
- /**
67
- * Analyzes a directory and returns structural decisions that both eager and lazy modes can use.
68
- * This provides the decision-making logic for directory handling without implementing the actual
69
- * loading strategy (allowing lazy mode to create proxies while eager mode materializes).
70
- * @function analyzeDirectoryStructure
71
- * @internal
72
- * @package
73
- * @param {string} categoryPath - Absolute path to the directory
74
- * @param {object} options - Analysis options
75
- * @param {object} options.instance - Slothlet instance for accessing config and methods
76
- * @param {number} [options.currentDepth=0] - Current traversal depth
77
- * @param {number} [options.maxDepth=Infinity] - Maximum traversal depth
78
- * @param {boolean} [options.debug=false] - Enable debug logging
79
- * @returns {Promise<{
80
- * isSingleFile: boolean,
81
- * shouldAutoFlatten: boolean,
82
- * categoryName: string,
83
- * moduleFiles: Array<import('fs').Dirent>,
84
- * subDirs: Array<import('fs').Dirent>,
85
- * multiDefaultAnalysis: object,
86
- * processingStrategy: 'single-file'|'multi-file'|'empty',
87
- * flatteningHints: object
88
- * }>} Directory structure analysis
89
- * @example
90
- * // Analyze directory structure
91
- * const analysis = await analyzeDirectoryStructure(categoryPath, { instance });
92
- * if (analysis.isSingleFile) {
93
- * // Both modes: handle as single file (but differently)
94
- * } else {
95
- * // Both modes: handle as multi-file (but differently)
96
- * }
97
- */
98
- export function analyzeDirectoryStructure(categoryPath: string, options?: {
99
- instance: object;
100
- currentDepth?: number;
101
- maxDepth?: number;
102
- debug?: boolean;
103
- }): Promise<{
104
- isSingleFile: boolean;
105
- shouldAutoFlatten: boolean;
106
- categoryName: string;
107
- moduleFiles: Array<import("fs").Dirent>;
108
- subDirs: Array<import("fs").Dirent>;
109
- multiDefaultAnalysis: object;
110
- processingStrategy: "single-file" | "multi-file" | "empty";
111
- flatteningHints: object;
112
- }>;
113
- /**
114
- * Returns category building decisions and processed modules that both eager and lazy modes can use.
115
- * This provides all the structural information needed to build a category but lets each mode
116
- * implement the actual building strategy (materialization vs proxy creation).
117
- * @function getCategoryBuildingDecisions
118
- * @internal
119
- * @package
120
- * @param {string} categoryPath - Absolute path to the directory
121
- * @param {object} options - Building options
122
- * @param {object} options.instance - Slothlet instance for accessing config and methods
123
- * @param {number} [options.currentDepth=0] - Current traversal depth
124
- * @param {number} [options.maxDepth=Infinity] - Maximum traversal depth
125
- * @param {boolean} [options.debug=false] - Enable debug logging
126
- * @returns {Promise<{
127
- * processingStrategy: 'single-file'|'multi-file'|'empty',
128
- * categoryName: string,
129
- * shouldFlattenSingle: boolean,
130
- * processedModules: Array<{file: import('fs').Dirent, moduleName: string, processedModule: any, flattening: object}>,
131
- * subDirectories: Array<{dirEntry: import('fs').Dirent, apiPathKey: string}>,
132
- * multiDefaultAnalysis: object,
133
- * flatteningDecisions: object,
134
- * upwardFlatteningCandidate: {shouldFlatten: boolean, apiPathKey: string}
135
- * }>} Complete category building information
136
- * @example
137
- * // Get category building decisions
138
- * const decisions = await getCategoryBuildingDecisions(categoryPath, { instance });
139
- * if (decisions.processingStrategy === "single-file") {
140
- * // Both modes: handle single file differently
141
- * // Eager: return decisions.processedModules[0].processedModule
142
- * // Lazy: create proxy based on decisions.processedModules[0].flattening
143
- * }
144
- */
145
- export function getCategoryBuildingDecisions(categoryPath: string, options?: {
146
- instance: object;
147
- currentDepth?: number;
148
- maxDepth?: number;
149
- debug?: boolean;
150
- }): Promise<{
151
- processingStrategy: "single-file" | "multi-file" | "empty";
152
- categoryName: string;
153
- shouldFlattenSingle: boolean;
154
- processedModules: Array<{
155
- file: import("fs").Dirent;
156
- moduleName: string;
157
- processedModule: any;
158
- flattening: object;
159
- }>;
160
- subDirectories: Array<{
161
- dirEntry: import("fs").Dirent;
162
- apiPathKey: string;
163
- }>;
164
- multiDefaultAnalysis: object;
165
- flatteningDecisions: object;
166
- upwardFlatteningCandidate: {
167
- shouldFlatten: boolean;
168
- apiPathKey: string;
169
- };
170
- }>;
171
- /**
172
- * Auto-flattening decision logic that determines whether a module should be flattened
173
- * based on filename matching, export patterns, and context.
174
- * @function getFlatteningDecision
175
- * @internal
176
- * @package
177
- * @param {object} options - Flattening analysis options
178
- * @param {object} options.mod - The loaded module object
179
- * @param {string} options.fileName - Original filename (without extension)
180
- * @param {string} options.apiPathKey - Sanitized API key for the module
181
- * @param {boolean} options.hasMultipleDefaultExports - Whether multiple default exports exist in the container
182
- * @param {boolean} options.isSelfReferential - Whether this is a self-referential export
183
- * @param {boolean} [options.moduleHasDefault] - Whether this specific module has a default export.
184
- * Should use originalAnalysis.hasDefault when available for accuracy, as !!mod.default
185
- * may be inaccurate after processModuleFromAnalysis modifies module structure.
186
- * @param {string} [options.categoryName] - Container/category name for context
187
- * @param {number} [options.totalModules=1] - Total number of modules in container
188
- * @param {boolean} [options.debug=false] - Enable debug logging
189
- * @returns {{
190
- * shouldFlatten: boolean,
191
- * flattenToRoot: boolean,
192
- * flattenToCategory: boolean,
193
- * preserveAsNamespace: boolean,
194
- * useAutoFlattening: boolean,
195
- * reason: string
196
- * }} Flattening decision result
197
- *
198
- * @description
199
- * Determines flattening behavior based on slothlet's established rules:
200
- *
201
- * 1. Self-referential exports: Never flatten (preserve as namespace)
202
- * 2. Multi-default context: Flatten modules WITHOUT defaults, preserve WITH defaults
203
- * 3. Single named export matching filename: Auto-flatten to use export directly
204
- * 4. Filename matches container: Flatten contents to container level
205
- * 5. Traditional context: Preserve as namespace unless auto-flattening applies
206
- *
207
- * @example
208
- * // Internal usage - single named export matching filename
209
- * const decision = getFlatteningDecision({
210
- * mod: { math: { add: fn, multiply: fn } },
211
- * fileName: "math", apiPathKey: "math",
212
- * hasMultipleDefaultExports: false, isSelfReferential: false
213
- * });
214
- * // Returns: { shouldFlatten: true, useAutoFlattening: true, reason: "auto-flatten single named export" }
215
- */
216
- export function getFlatteningDecision(options: {
217
- mod: object;
218
- fileName: string;
219
- apiPathKey: string;
220
- hasMultipleDefaultExports: boolean;
221
- isSelfReferential: boolean;
222
- moduleHasDefault?: boolean;
223
- categoryName?: string;
224
- totalModules?: number;
225
- debug?: boolean;
226
- }): {
227
- shouldFlatten: boolean;
228
- flattenToRoot: boolean;
229
- flattenToCategory: boolean;
230
- preserveAsNamespace: boolean;
231
- useAutoFlattening: boolean;
232
- reason: string;
233
- };
234
- /**
235
- * Processes a single module and applies it to the target API object based on flattening decisions.
236
- * @function processModuleForAPI
237
- * @internal
238
- * @package
239
- * @param {object} options - Module processing options
240
- * @param {object} options.mod - The loaded module object
241
- * @param {string} options.fileName - Original filename (without extension)
242
- * @param {string} options.apiPathKey - Sanitized API key for the module
243
- * @param {boolean} options.hasMultipleDefaultExports - Whether multiple default exports exist
244
- * @param {boolean} options.isSelfReferential - Whether this is a self-referential export
245
- * @param {object} options.api - Target API object to modify (could be root api or categoryModules)
246
- * @param {function} [options.getRootDefault] - Function to get current root default function
247
- * @param {function} [options.setRootDefault] - Function to set the root default function
248
- * @param {object} [options.context] - Processing context
249
- * @param {boolean} [options.context.debug=false] - Enable debug logging
250
- * @param {string} [options.context.mode="unknown"] - Processing mode (root, subfolder, eager, lazy)
251
- * @param {string} [options.context.categoryName] - Container/category name
252
- * @param {number} [options.context.totalModules=1] - Total modules in container
253
- * @returns {{
254
- * processed: boolean,
255
- * rootDefaultSet: boolean,
256
- * flattened: boolean,
257
- * namespaced: boolean,
258
- * apiAssignments: Record<string, any>
259
- * }} Processing result
260
- *
261
- * @description
262
- * Unified module processing logic that handles:
263
- * 1. Function default exports (multi-default, self-referential, traditional root contributor)
264
- * 2. Object/named exports with flattening decisions
265
- * 3. Export merging and namespace assignments
266
- * 4. Function name preference logic
267
- * 5. Root default function management
268
- *
269
- * @example
270
- * // Internal usage for root-level processing
271
- * const result = processModuleForAPI({
272
- * mod, fileName, apiPathKey, hasMultipleDefaultExports, isSelfReferential, api,
273
- * getRootDefault: () => rootDefaultFunction,
274
- * setRootDefault: (fn) => { rootDefaultFunction = fn; },
275
- * context: { debug: true, mode: "root", totalModules: 3 },
276
- * originalAnalysis: { hasDefault: true, namedExportsCount: 2 }
277
- * });
278
- */
279
- export function processModuleForAPI(options: {
280
- mod: object;
281
- fileName: string;
282
- apiPathKey: string;
283
- hasMultipleDefaultExports: boolean;
284
- isSelfReferential: boolean;
285
- api: object;
286
- getRootDefault?: Function;
287
- setRootDefault?: Function;
288
- context?: {
289
- debug?: boolean;
290
- mode?: string;
291
- categoryName?: string;
292
- totalModules?: number;
293
- };
294
- }): {
295
- processed: boolean;
296
- rootDefaultSet: boolean;
297
- flattened: boolean;
298
- namespaced: boolean;
299
- apiAssignments: Record<string, any>;
300
- };
301
- /**
302
- * Handles function name preference logic for better API naming.
303
- * @function applyFunctionNamePreference
304
- * @internal
305
- * @package
306
- * @param {object} options - Name preference options
307
- * @param {object} options.mod - The loaded module object
308
- * @param {string} options.fileName - Original filename (without extension)
309
- * @param {string} options.apiPathKey - Sanitized API key
310
- * @param {object} options.categoryModules - Target category modules object
311
- * @param {function} options.toapiPathKey - Function to sanitize names to API keys
312
- * @param {boolean} [options.debug=false] - Enable debug logging
313
- * @returns {{hasPreferredName: boolean, preferredKey: string}} Name preference result
314
- *
315
- * @description
316
- * Implements slothlet's function name preference logic where the original function name
317
- * is preferred over the sanitized filename when they represent the same semantic meaning
318
- * but have different capitalization (e.g., autoIP vs autoIp, parseJSON vs parseJson).
319
- *
320
- * @example
321
- * // Internal usage in _buildCategory
322
- * const preference = applyFunctionNamePreference({
323
- * mod: { autoIP: function autoIP() {} },
324
- * fileName: "auto-ip", apiPathKey: "autoIp",
325
- * categoryModules, toapiPathKey: this._toapiPathKey, debug: true
326
- * });
327
- * // Returns: { hasPreferredName: true, preferredKey: "autoIP" }
328
- */
329
- export function applyFunctionNamePreference(options: {
330
- mod: object;
331
- fileName: string;
332
- apiPathKey: string;
333
- categoryModules: object;
334
- toapiPathKey: Function;
335
- debug?: boolean;
336
- }): {
337
- hasPreferredName: boolean;
338
- preferredKey: string;
339
- };
340
- /**
341
- * Comprehensive category/directory building function that replaces _buildCategory.
342
- * Handles complete directory structure processing with all flattening rules.
343
- * @function buildCategoryStructure
344
- * @internal
345
- * @package
346
- * @async
347
- * @param {string} categoryPath - Absolute path to the category directory
348
- * @param {object} options - Building options
349
- * @param {number} [options.currentDepth=0] - Current recursion depth
350
- * @param {number} [options.maxDepth=Infinity] - Maximum recursion depth
351
- * @param {string} [options.mode="eager"] - Loading mode ("eager" or "lazy")
352
- * @param {function} [options.subdirHandler] - Custom subdirectory handler for lazy mode
353
- * @param {object} options.instance - Slothlet instance for access to helper methods
354
- * @returns {Promise<object>} Complete category API structure
355
- *
356
- * @description
357
- * Complete directory structure building pipeline that handles:
358
- * - Single-file vs multi-file directory processing
359
- * - Auto-flattening decisions for single files matching directory names
360
- * - Multi-default export detection and processing
361
- * - Self-referential export handling
362
- * - Recursive subdirectory traversal with depth control
363
- * - Function name preference over sanitized names
364
- * - All established slothlet flattening rules and conventions
365
- *
366
- * @example
367
- * // Internal usage - build complete category structure
368
- * const categoryApi = await buildCategoryStructure("/path/to/category", {
369
- * currentDepth: 0, maxDepth: 3, mode: "eager", instance: slothletInstance
370
- * });
371
- */
372
- export function buildCategoryStructure(categoryPath: string, options?: {
373
- currentDepth?: number;
374
- maxDepth?: number;
375
- mode?: string;
376
- subdirHandler?: Function;
377
- instance: object;
378
- }): Promise<object>;
379
- /**
380
- * Comprehensive root API building function that replaces eager/lazy create methods.
381
- * Handles complete root-level API construction with mode-specific optimizations.
382
- * @function buildRootAPI
383
- * @internal
384
- * @package
385
- * @async
386
- * @param {string} dir - Root directory path to build API from
387
- * @param {object} options - Building options
388
- * @param {boolean} [options.lazy=false] - Whether to use lazy loading mode
389
- * @param {number} [options.maxDepth=Infinity] - Maximum recursion depth
390
- * @param {object} options.instance - Slothlet instance for access to helper methods
391
- * @returns {Promise<object|function>} Complete root API (object or function with properties)
392
- *
393
- * @description
394
- * Complete root API building pipeline that handles:
395
- * - Root-level module processing with multi-default detection
396
- * - Root contributor pattern (default function becomes callable API)
397
- * - Named export merging and flattening decisions
398
- * - Recursive directory structure building via buildCategoryStructure
399
- * - Mode-specific optimizations (eager vs lazy)
400
- * - All established slothlet API construction patterns
401
- *
402
- * @example
403
- * // Internal usage - build complete root API
404
- * const rootApi = await buildRootAPI("/path/to/api", {
405
- * lazy: false, maxDepth: 3, instance: slothletInstance
406
- * });
407
- */
408
- export function buildRootAPI(dir: string, options?: {
409
- lazy?: boolean;
410
- maxDepth?: number;
411
- instance: object;
412
- }): Promise<object | Function>;
413
- /**
414
- * Centralized category building decisions - contains ALL logic for directory/category processing.
415
- * This function analyzes a directory and returns decisions about how to structure the API,
416
- * but doesn't actually build the API (allowing eager/lazy modes to implement differently).
417
- *
418
- * @function buildCategoryDecisions
419
- * @param {string} categoryPath - Path to the category directory
420
- * @param {object} options - Configuration options
421
- * @param {number} [options.currentDepth=0] - Current nesting depth
422
- * @param {number} [options.maxDepth=Infinity] - Maximum nesting depth
423
- * @param {string} [options.mode="eager"] - Loading mode ("eager" or "lazy")
424
- * @param {Function} [options.subdirHandler] - Handler for subdirectories (lazy mode)
425
- * @param {object} options.instance - Slothlet instance with _toapiPathKey, _shouldIncludeFile, config
426
- * @returns {Promise<object>} Category building decisions and data
427
- *
428
- * @example // ESM usage
429
- * import { buildCategoryDecisions } from "@cldmv/slothlet/helpers/api_builder";
430
- * const decisions = await buildCategoryDecisions("/path/to/category", {
431
- * currentDepth: 1,
432
- * instance: slothletInstance
433
- * });
434
- *
435
- * @example // CJS usage
436
- * const { buildCategoryDecisions } = require("@cldmv/slothlet/helpers/api_builder");
437
- * const decisions = await buildCategoryDecisions("/path/to/category", {
438
- * currentDepth: 1,
439
- * instance: slothletInstance
440
- * });
441
- */
442
- export function buildCategoryDecisions(categoryPath: string, options?: {
443
- currentDepth?: number;
444
- maxDepth?: number;
445
- mode?: string;
446
- subdirHandler?: Function;
447
- instance: object;
448
- }): Promise<object>;
1
+ export { addApiFromFolder } from "@cldmv/slothlet/helpers/api_builder/add_api";
2
+ export { isLikelySerializable, analyzeModule, processModuleFromAnalysis, analyzeDirectoryStructure, getCategoryBuildingDecisions } from "@cldmv/slothlet/helpers/api_builder/analysis";
3
+ export { getFlatteningDecision, applyFunctionNamePreference, processModuleForAPI, buildCategoryDecisions } from "@cldmv/slothlet/helpers/api_builder/decisions";
4
+ export { buildCategoryStructure, buildRootAPI, toapiPathKey, shouldIncludeFile } from "@cldmv/slothlet/helpers/api_builder/construction";
5
+ export { safeDefine, deepMerge, mutateLiveBindingFunction } from "@cldmv/slothlet/helpers/utilities";
449
6
  //# sourceMappingURL=api_builder.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api_builder.d.mts","sourceRoot":"","sources":["../../../../dist/lib/helpers/api_builder.mjs"],"names":[],"mappings":"AAuFA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,0CAtBW,MAAM,YAEd;IAA0B,KAAK,GAAvB,OAAO;IACU,QAAQ,GAAzB,MAAM;CACd,GAAU,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAC9B,iBAAiB,EAAE,UAAU,GAAC,QAAQ,GAAC,IAAI,CAAC;IAC5C,oBAAoB,EAAE,OAAO,CAAC;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAC,CAiGJ;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,oDAXW,MAAM,YAEd;IAAyB,QAAQ,GAAzB,MAAM;IACY,KAAK,GAAvB,OAAO;CACf,GAAU,MAAM,CA2NlB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wDAzBW,MAAM,YAEd;IAAwB,QAAQ,EAAxB,MAAM;IACW,YAAY,GAA7B,MAAM;IACW,QAAQ,GAAzB,MAAM;IACY,KAAK,GAAvB,OAAO;CACf,GAAU,OAAO,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE,MAAM,CAAC,CAAC;IACxC,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE,MAAM,CAAC,CAAC;IACpC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,kBAAkB,EAAE,aAAa,GAAC,YAAY,GAAC,OAAO,CAAC;IACvD,eAAe,EAAE,MAAM,CAAA;CACxB,CAAC,CAiEJ;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,2DAzBW,MAAM,YAEd;IAAwB,QAAQ,EAAxB,MAAM;IACW,YAAY,GAA7B,MAAM;IACW,QAAQ,GAAzB,MAAM;IACY,KAAK,GAAvB,OAAO;CACf,GAAU,OAAO,CAAC;IAChB,kBAAkB,EAAE,aAAa,GAAC,YAAY,GAAC,OAAO,CAAC;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,gBAAgB,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,OAAO,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,GAAG,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IACnH,cAAc,EAAE,KAAK,CAAC;QAAC,QAAQ,EAAE,OAAO,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IAC3E,oBAAoB,EAAE,MAAM,CAAC;IAC7B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,yBAAyB,EAAE;QAAC,aAAa,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAC,CAAA;CACxE,CAAC,CAkHJ;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,+CAtCG;IAAwB,GAAG,EAAnB,MAAM;IACU,QAAQ,EAAxB,MAAM;IACU,UAAU,EAA1B,MAAM;IACW,yBAAyB,EAA1C,OAAO;IACU,iBAAiB,EAAlC,OAAO;IACW,gBAAgB,GAAlC,OAAO;IAGU,YAAY,GAA7B,MAAM;IACW,YAAY,GAA7B,MAAM;IACY,KAAK,GAAvB,OAAO;CACf,GAAU;IACR,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAA;CACf,CAyHH;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,6CAvCG;IAAwB,GAAG,EAAnB,MAAM;IACU,QAAQ,EAAxB,MAAM;IACU,UAAU,EAA1B,MAAM;IACW,yBAAyB,EAA1C,OAAO;IACU,iBAAiB,EAAlC,OAAO;IACS,GAAG,EAAnB,MAAM;IACa,cAAc;IACd,cAAc;IAChB,OAAO,GAChC;QAAkC,KAAK,GAA/B,OAAO;QACkB,IAAI,GAA7B,MAAM;QACmB,YAAY,GAArC,MAAM;QACmB,YAAY,GAArC,MAAM;KACd;CAAA,GAAU;IACR,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CACpC,CA2KH;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qDAtBG;IAAwB,GAAG,EAAnB,MAAM;IACU,QAAQ,EAAxB,MAAM;IACU,UAAU,EAA1B,MAAM;IACU,eAAe,EAA/B,MAAM;IACY,YAAY;IACZ,KAAK,GAAvB,OAAO;CACf,GAAU;IAAC,gBAAgB,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAC,CA4D7D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,qDAzBW,MAAM,YAEd;IAAyB,YAAY,GAA7B,MAAM;IACW,QAAQ,GAAzB,MAAM;IACW,IAAI,GAArB,MAAM;IACa,aAAa;IAChB,QAAQ,EAAxB,MAAM;CACd,GAAU,OAAO,CAAC,MAAM,CAAC,CAmR3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,kCAtBW,MAAM,YAEd;IAA0B,IAAI,GAAtB,OAAO;IACU,QAAQ,GAAzB,MAAM;IACU,QAAQ,EAAxB,MAAM;CACd,GAAU,OAAO,CAAC,MAAM,WAAS,CAAC,CA2HpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qDAvBW,MAAM,YAEd;IAAyB,YAAY,GAA7B,MAAM;IACW,QAAQ,GAAzB,MAAM;IACW,IAAI,GAArB,MAAM;IACa,aAAa;IAChB,QAAQ,EAAxB,MAAM;CACd,GAAU,OAAO,CAAC,MAAM,CAAC,CAyZ3B"}
1
+ {"version":3,"file":"api_builder.d.mts","sourceRoot":"","sources":["../../../../dist/lib/helpers/api_builder.mjs"],"names":[],"mappings":""}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * @Project: @cldmv/slothlet
3
+ * @Filename: /src/lib/helpers/utilities.mjs
4
+ * @Date: 2025-12-30 08:44:44 -08:00 (1767113084)
5
+ * @Author: Nate Hyson <CLDMV>
6
+ * @Email: <Shinrai@users.noreply.github.com>
7
+ * -----
8
+ * @Last modified by: Nate Hyson <CLDMV> (Shinrai@users.noreply.github.com)
9
+ * @Last modified time: 2025-12-30 08:54:56 -08:00 (1767113696)
10
+ * -----
11
+ * @Copyright: Copyright (c) 2013-2025 Catalyzed Motivation Inc. All rights reserved.
12
+ */
13
+ /**
14
+ * @fileoverview Utility functions for property manipulation and object operations.
15
+ * @module @cldmv/slothlet/lib/helpers/utilities
16
+ * @memberof module:@cldmv/slothlet.lib.helpers
17
+ * @internal
18
+ * @private
19
+ *
20
+ * @description
21
+ * Provides general-purpose utility functions for safe property definition, deep object merging,
22
+ * and live-binding variable mutation. These utilities are used throughout slothlet for
23
+ * object manipulation, property management, and live-binding operations.
24
+ *
25
+ * Exported Functions:
26
+ * - safeDefine: Safe property definition handling non-configurable properties
27
+ * - deepMerge: Recursive deep merge for object combining
28
+ * - mutateLiveBindingFunction: Live-binding variable mutation preserving references
29
+ *
30
+ * @example
31
+ * // Internal usage in slothlet
32
+ * import { safeDefine, deepMerge, mutateLiveBindingFunction } from "./utilities.mjs";
33
+ *
34
+ * safeDefine(api, "shutdown", shutdownFunction, false);
35
+ * const merged = deepMerge(target, source);
36
+ * mutateLiveBindingFunction(boundapi, newApi);
37
+ */
38
+ /**
39
+ * Safely defines a property on an object, handling non-configurable properties.
40
+ *
41
+ * @function safeDefine
42
+ * @memberof module:@cldmv/slothlet.lib.helpers.utilities
43
+ * @param {object} obj - Target object
44
+ * @param {string} key - Property key
45
+ * @param {*} value - Property value
46
+ * @param {boolean} [enumerable=false] - Whether the property should be enumerable (default: false for management methods)
47
+ * @param {object} [config=null] - Optional configuration object with debug flag
48
+ * @package
49
+ *
50
+ * @description
51
+ * Attempts to define a property on an object with the specified configuration.
52
+ * Handles cases where the property is non-configurable by logging a warning
53
+ * instead of throwing an error. Used for safely attaching management methods
54
+ * like shutdown, addApi, and describe to API objects.
55
+ *
56
+ * @example
57
+ * // Internal usage
58
+ * import { safeDefine } from "./utilities.mjs";
59
+ *
60
+ * safeDefine(api, "shutdown", shutdownFunction, false, { debug: true });
61
+ */
62
+ export function safeDefine(obj: object, key: string, value: any, enumerable?: boolean, config?: object): void;
63
+ /**
64
+ * Deep merge two objects recursively.
65
+ *
66
+ * @function deepMerge
67
+ * @memberof module:@cldmv/slothlet.lib.helpers.utilities
68
+ * @param {object} target - Target object to merge into
69
+ * @param {object} source - Source object to merge from
70
+ * @returns {object} Merged object (mutates target)
71
+ * @package
72
+ *
73
+ * @description
74
+ * Performs a recursive deep merge of two objects, combining nested structures.
75
+ * Arrays are treated as primitive values and replaced rather than merged.
76
+ * Used for context merging in scope operations.
77
+ *
78
+ * **Security Note**: This function explicitly blocks the `__proto__`, `prototype`, and
79
+ * `constructor` keys to prevent prototype pollution attacks. Any attempt to merge
80
+ * these dangerous keys will be silently ignored.
81
+ *
82
+ * @example
83
+ * // Internal usage
84
+ * import { deepMerge } from "./utilities.mjs";
85
+ *
86
+ * const target = { a: 1, b: { c: 2 } };
87
+ * const source = { b: { d: 3 }, e: 4 };
88
+ * const merged = deepMerge(target, source);
89
+ * // Result: { a: 1, b: { c: 2, d: 3 }, e: 4 }
90
+ */
91
+ export function deepMerge(target: object, source: object): object;
92
+ /**
93
+ * Mutates a live-binding variable (object or function) to match a new value, preserving reference.
94
+ *
95
+ * @function mutateLiveBindingFunction
96
+ * @memberof module:@cldmv/slothlet.lib.helpers.utilities
97
+ * @param {function|object} target - The variable to mutate (object or function)
98
+ * @param {function|object} source - The new value to copy from (object or function)
99
+ * @package
100
+ *
101
+ * @description
102
+ * Mutates an existing live-binding variable to match a new structure while
103
+ * preserving the original reference. This is critical for maintaining live
104
+ * bindings in modules that have imported self, context, or reference.
105
+ *
106
+ * For functions: Sets _impl to call source, removes old properties (except _impl and __ctx),
107
+ * and attaches new properties from source.
108
+ *
109
+ * For objects: Removes old properties (except _impl and __ctx), attaches new properties,
110
+ * and manually copies management methods (shutdown, addApi, describe).
111
+ *
112
+ * @example
113
+ * // Internal usage
114
+ * import { mutateLiveBindingFunction } from "./utilities.mjs";
115
+ *
116
+ * mutateLiveBindingFunction(self, newSelf);
117
+ * mutateLiveBindingFunction(boundapi, newApi);
118
+ */
119
+ export function mutateLiveBindingFunction(target: Function | object, source: Function | object): void;
120
+ //# sourceMappingURL=utilities.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utilities.d.mts","sourceRoot":"","sources":["../../../../dist/lib/helpers/utilities.mjs"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,gCAnBW,MAAM,OACN,MAAM,SACN,GAAC,eACD,OAAO,WACP,MAAM,QAkChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,kCAvBW,MAAM,UACN,MAAM,GACJ,MAAM,CAkDlB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,kDAtBW,WAAS,MAAM,UACf,WAAS,MAAM,QAkEzB"}
@@ -5,6 +5,13 @@
5
5
  * @public
6
6
  */
7
7
  export const sharedALS: AsyncLocalStorageType;
8
+ /**
9
+ * Per-request AsyncLocalStorage instance for request-scoped context.
10
+ * Stores temporary context data that merges with instance context.
11
+ * @type {AsyncLocalStorageType}
12
+ * @public
13
+ */
14
+ export const requestALS: AsyncLocalStorageType;
8
15
  export function runWithCtx(ctx: object, fn: Function, thisArg: any, args: any[]): any;
9
16
  export function getCtx(): object | null;
10
17
  export function makeWrapper(ctx: object): Function;
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-asynclocalstorage.d.mts","sourceRoot":"","sources":["../../../../dist/lib/runtime/runtime-asynclocalstorage.mjs"],"names":[],"mappings":"AAuCA;;;;;GAKG;AACH,wBAHU,qBAAqB,CAGkB;AAsB1C,gCAdI,MAAM,yBAEN,GAAG,gBAED,GAAG,CAoGf;AAiBM,0BAZM,MAAM,GAAC,IAAI,CAY0B;AAkN3C,iCAjBI,MAAM,YAiJhB;AAuSD;;;;;;;;;;;;;GAaG;AACH,mBATU,WAAS,MAAM,CAS6B;AAEtD;;;;;;;;;;;;;GAaG;AACH,sBATU,MAAM,CAS4C;AAE5D;;;;;;;;;;;;;GAaG;AACH,wBATU,MAAM,CASgD;;kCApzB9B,kBAAkB"}
1
+ {"version":3,"file":"runtime-asynclocalstorage.d.mts","sourceRoot":"","sources":["../../../../dist/lib/runtime/runtime-asynclocalstorage.mjs"],"names":[],"mappings":"AAuCA;;;;;GAKG;AACH,wBAHU,qBAAqB,CAGkB;AAEjD;;;;;GAKG;AACH,yBAHU,qBAAqB,CAGmB;AAsB3C,gCAdI,MAAM,yBAEN,GAAG,gBAED,GAAG,CAwGf;AAiBM,0BAZM,MAAM,GAAC,IAAI,CAY0B;AAkN3C,iCAjBI,MAAM,YAiJhB;AA2TD;;;;;;;;;;;;;GAaG;AACH,mBATU,WAAS,MAAM,CAS6B;AAEtD;;;;;;;;;;;;;GAaG;AACH,sBATU,MAAM,CAS4C;AAE5D;;;;;;;;;;;;;GAaG;AACH,wBATU,MAAM,CASgD;;kCAp1B9B,kBAAkB"}
@@ -23,6 +23,13 @@ export function makeWrapper(ctx: object): Function;
23
23
  */
24
24
  export function getContext(): any;
25
25
  export function setContext(newContext: any): void;
26
+ /**
27
+ * Per-request AsyncLocalStorage instance for request-scoped context.
28
+ * Works alongside live bindings to provide per-request context isolation.
29
+ * @type {AsyncLocalStorage}
30
+ * @public
31
+ */
32
+ export const requestALS: AsyncLocalStorage<any>;
26
33
  /**
27
34
  * Live-binding reference to the current API instance.
28
35
  * Automatically resolves to the appropriate instance based on calling context.
@@ -56,4 +63,5 @@ export namespace contextManager {
56
63
  export { setContext as set };
57
64
  export { runWithCtx };
58
65
  }
66
+ import { AsyncLocalStorage } from "node:async_hooks";
59
67
  //# sourceMappingURL=runtime-livebindings.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-livebindings.d.mts","sourceRoot":"","sources":["../../../../dist/lib/runtime/runtime-livebindings.mjs"],"names":[],"mappings":"AA2RA;;;;;;;;;GASG;AACH,gCANW,MAAM,yBAEN,GAAG,gBAED,GAAG,CAoFf;AAED;;;;;;GAMG;AACH,iCAHW,MAAM,YAiEhB;AAID;;;GAGG;AAEH,kCAEC;AAED,kDASC;AAhYD;;;;;GAKG;AACH,mBAHU,MAAM,CAmDd;AAEF;;;;;GAKG;AACH,sBAHU,MAAM,CA+Cd;AAEF;;;;;GAKG;AACH,wBAHU,MAAM,CA+Cd;AAEF;;;;;GAKG;AACH,yBAHU,MAAM,CAkCd"}
1
+ {"version":3,"file":"runtime-livebindings.d.mts","sourceRoot":"","sources":["../../../../dist/lib/runtime/runtime-livebindings.mjs"],"names":[],"mappings":"AA+SA;;;;;;;;;GASG;AACH,gCANW,MAAM,yBAEN,GAAG,gBAED,GAAG,CAoFf;AAED;;;;;;GAMG;AACH,iCAHW,MAAM,YAiEhB;AAID;;;GAGG;AAEH,kCAEC;AAED,kDASC;AA/bD;;;;;GAKG;AACH,gDAAkD;AA8ClD;;;;;GAKG;AACH,mBAHU,MAAM,CAmDd;AAEF;;;;;GAKG;AACH,sBAHU,MAAM,CA0Dd;AAEF;;;;;GAKG;AACH,wBAHU,MAAM,CA+Cd;AAEF;;;;;GAKG;AACH,yBAHU,MAAM,CAkCd;;;;;;kCA5QgC,kBAAkB"}
@@ -1,14 +1,3 @@
1
- /**
2
- * Mutates a live-binding variable (object or function) to match a new value, preserving reference.
3
- * @param {function|object} target - The variable to mutate (object or function).
4
- * @param {function|object} source - The new value to copy from (object or function).
5
- * @private
6
- * @internal
7
- * @example
8
- * mutateLiveBindingFunction(self, newSelf);
9
- * mutateLiveBindingFunction(boundapi, newApi);
10
- */
11
- export function mutateLiveBindingFunction(target: Function | object, source: Function | object): void;
12
1
  /**
13
2
  * Live-binding reference to the current API instance.
14
3
  * This is updated whenever a new API instance is created.
@@ -1 +1 @@
1
- {"version":3,"file":"slothlet.d.mts","sourceRoot":"","sources":["../../dist/slothlet.mjs"],"names":[],"mappings":"AA80DA;;;;;;;;;GASG;AACH,kDARW,WAAS,MAAM,UACf,WAAS,MAAM,QAoDzB;AA9sDD;;;;;;;GAOG;AACH,mBAJU,MAAM,CAIO;AAEvB;;;;;GAKG;AACH,sBAJU,MAAM,CAIU;AAE1B;;;;;GAKG;AACH,wBAJU,MAAM,CAIY;;;;;;;;;UAisDd,MAAM;;;;;;WAIN,OAAO;;;;;;;;WAGP,MAAM;;;;;;;;aAKN,MAAM;;;;;;;cAKN,MAAM;;;;;;;eAIN,MAAM;;;;;;;;YAIN,OAAO;;;;;;;eAKP,MAAM;;;;;;;wBAIN,OAAO;;;;;;cAIP,MAAM;;;;;;gBAGN,MAAM;;;;;;eAMjB;QAA8B,UAAU,GAA7B,OAAO;QACY,gBAAgB,GAAnC,OAAO;QACY,gBAAgB,GAAnC,OAAO;QACW,KAAK,GAClC;YAAqC,KAAK,GAA/B,MAAM,EAAE;YACkB,gBAAgB,GAA1C,MAAM,EAAE;YACkB,KAAK,GAA/B,MAAM,EAAE;YACkB,KAAK,GAA/B,MAAM,EAAE;SACrB;KAAA;;;;;;cAIa,MAAM,OAAO,CAAC,IAAI,CAAC;;;;YACnB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;;;;cACtD,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC,CAAC,MAAM,GAAC,MAAM,CAAC,EAAE,GAAC,MAAM,GAAC,OAAO,CAAC,MAAM,CAAC,CAAC;;AA5vD/E;;;;;;;;GAQG;AACH,mCAJW,eAAe,GACb,OAAO,CAAC,WAAW,CAAC,CAiChC"}
1
+ {"version":3,"file":"slothlet.d.mts","sourceRoot":"","sources":["../../dist/slothlet.mjs"],"names":[],"mappings":"AA0LA;;;;;;;GAOG;AACH,mBAJU,MAAM,CAIO;AAEvB;;;;;GAKG;AACH,sBAJU,MAAM,CAIU;AAE1B;;;;;GAKG;AACH,wBAJU,MAAM,CAIY;;;;;;;;;UAsmCd,MAAM;;;;;;WAIN,OAAO;;;;;;;;WAGP,MAAM;;;;;;;;aAKN,MAAM;;;;;;;cAKN,MAAM;;;;;;;eAIN,MAAM;;;;;;;;YAIN,OAAO;;;;;;;eAKP,MAAM;;;;;;;wBAIN,OAAO;;;;;;cAIP,MAAM;;;;;;gBAGN,MAAM;;;;;;eAMjB;QAA8B,UAAU,GAA7B,OAAO;QACY,gBAAgB,GAAnC,OAAO;QACY,gBAAgB,GAAnC,OAAO;QACW,KAAK,GAClC;YAAqC,KAAK,GAA/B,MAAM,EAAE;YACkB,gBAAgB,GAA1C,MAAM,EAAE;YACkB,KAAK,GAA/B,MAAM,EAAE;YACkB,KAAK,GAA/B,MAAM,EAAE;SACrB;KAAA;;;;;;cAIa,MAAM,OAAO,CAAC,IAAI,CAAC;;;;YACnB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;;;;cACtD,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC,CAAC,MAAM,GAAC,MAAM,CAAC,EAAE,GAAC,MAAM,GAAC,OAAO,CAAC,MAAM,CAAC,CAAC;;AAjqC/E;;;;;;;;GAQG;AACH,mCAJW,eAAe,GACb,OAAO,CAAC,WAAW,CAAC,CAiChC"}
package/types/index.d.mts CHANGED
@@ -12,7 +12,6 @@ export * from "./dist/slothlet.mts";
12
12
 
13
13
  // Auto-generated named export declarations (these override the re-export above)
14
14
  export const context: any;
15
- export const mutateLiveBindingFunction: any;
16
15
  export const reference: any;
17
16
  export const self: any;
18
17