@cldmv/slothlet 2.8.0 → 2.10.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 (59) hide show
  1. package/AGENT-USAGE.md +1 -1
  2. package/README.md +300 -1557
  3. package/dist/lib/engine/slothlet_child.mjs +1 -1
  4. package/dist/lib/engine/slothlet_engine.mjs +1 -1
  5. package/dist/lib/engine/slothlet_esm.mjs +1 -1
  6. package/dist/lib/engine/slothlet_helpers.mjs +1 -1
  7. package/dist/lib/engine/slothlet_worker.mjs +1 -1
  8. package/dist/lib/helpers/als-eventemitter.mjs +5 -6
  9. package/dist/lib/helpers/api_builder/add_api.mjs +292 -0
  10. package/dist/lib/helpers/api_builder/analysis.mjs +532 -0
  11. package/dist/lib/helpers/api_builder/construction.mjs +457 -0
  12. package/dist/lib/helpers/api_builder/decisions.mjs +737 -0
  13. package/dist/lib/helpers/api_builder/metadata.mjs +248 -0
  14. package/dist/lib/helpers/api_builder.mjs +17 -1568
  15. package/dist/lib/helpers/auto-wrap.mjs +1 -1
  16. package/dist/lib/helpers/hooks.mjs +1 -1
  17. package/dist/lib/helpers/instance-manager.mjs +1 -1
  18. package/dist/lib/helpers/metadata-api.mjs +201 -0
  19. package/dist/lib/helpers/multidefault.mjs +12 -3
  20. package/dist/lib/helpers/resolve-from-caller.mjs +1 -1
  21. package/dist/lib/helpers/sanitize.mjs +1 -1
  22. package/dist/lib/helpers/utilities.mjs +121 -0
  23. package/dist/lib/modes/slothlet_eager.mjs +1 -1
  24. package/dist/lib/modes/slothlet_lazy.mjs +10 -1
  25. package/dist/lib/runtime/runtime-asynclocalstorage.mjs +49 -18
  26. package/dist/lib/runtime/runtime-livebindings.mjs +23 -4
  27. package/dist/lib/runtime/runtime.mjs +15 -4
  28. package/dist/slothlet.mjs +164 -748
  29. package/docs/API-RULES-CONDITIONS.md +508 -0
  30. package/{API-RULES.md → docs/API-RULES.md} +127 -72
  31. package/package.json +11 -9
  32. package/types/dist/lib/helpers/als-eventemitter.d.mts.map +1 -1
  33. package/types/dist/lib/helpers/api_builder/add_api.d.mts +76 -0
  34. package/types/dist/lib/helpers/api_builder/add_api.d.mts.map +1 -0
  35. package/types/dist/lib/helpers/api_builder/analysis.d.mts +189 -0
  36. package/types/dist/lib/helpers/api_builder/analysis.d.mts.map +1 -0
  37. package/types/dist/lib/helpers/api_builder/construction.d.mts +107 -0
  38. package/types/dist/lib/helpers/api_builder/construction.d.mts.map +1 -0
  39. package/types/dist/lib/helpers/api_builder/decisions.d.mts +213 -0
  40. package/types/dist/lib/helpers/api_builder/decisions.d.mts.map +1 -0
  41. package/types/dist/lib/helpers/api_builder/metadata.d.mts +99 -0
  42. package/types/dist/lib/helpers/api_builder/metadata.d.mts.map +1 -0
  43. package/types/dist/lib/helpers/api_builder.d.mts +5 -448
  44. package/types/dist/lib/helpers/api_builder.d.mts.map +1 -1
  45. package/types/dist/lib/helpers/metadata-api.d.mts +132 -0
  46. package/types/dist/lib/helpers/metadata-api.d.mts.map +1 -0
  47. package/types/dist/lib/helpers/multidefault.d.mts.map +1 -1
  48. package/types/dist/lib/helpers/utilities.d.mts +120 -0
  49. package/types/dist/lib/helpers/utilities.d.mts.map +1 -0
  50. package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts +9 -0
  51. package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts.map +1 -1
  52. package/types/dist/lib/runtime/runtime-livebindings.d.mts +10 -0
  53. package/types/dist/lib/runtime/runtime-livebindings.d.mts.map +1 -1
  54. package/types/dist/lib/runtime/runtime.d.mts +1 -0
  55. package/types/dist/lib/runtime/runtime.d.mts.map +1 -1
  56. package/types/dist/slothlet.d.mts +0 -11
  57. package/types/dist/slothlet.d.mts.map +1 -1
  58. package/types/index.d.mts +0 -1
  59. package/API-RULES-CONDITIONS.md +0 -367
package/README.md CHANGED
@@ -33,1541 +33,316 @@ The name might suggest we're taking it easy, but don't be fooled. **Slothlet del
33
33
 
34
34
  ---
35
35
 
36
- ## ✨ What's New in v2.x
36
+ ## ✨ What's New
37
37
 
38
- ### 🎯 **Complete Architectural Rewrite (v2.0)**
38
+ ### Latest: v2.9 (December 30, 2025)
39
39
 
40
- v2.0 represents a ground-up rewrite with enterprise-grade features:
40
+ - **Per-Request Context Isolation** - New `api.run()` and `api.scope()` methods for isolated context execution ([Documentation](https://github.com/CLDMV/slothlet/blob/master/docs/CONTEXT-PROPAGATION.md#per-request-context-isolation))
41
+ - API Builder Modularization - Improved maintainability and code organization
42
+ - [View Changelog](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.9.md)
41
43
 
42
- - **Universal Module Support**: Load both ESM (`.mjs`) and CommonJS (`.cjs`) files seamlessly
43
- - **Dual Runtime System**: Choose AsyncLocalStorage or live-bindings for context isolation
44
- - **4.3x Faster Startup**: Lazy mode achieves 564.17μs vs 2.45ms in eager mode
45
- - **Copy-Left Materialization**: Once loaded, modules stay materialized for optimal performance
46
- - **Zero Dependencies**: Pure Node.js implementation with no external dependencies
44
+ ### Recent Releases
47
45
 
48
- ### 🏗️ **Enhanced Architecture**
46
+ - **v2.8** - NPM security fixes and package workflow updates ([Changelog](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.8.md))
47
+ - **v2.7** - Security updates ([Changelog](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.7.md))
48
+ - **v2.6** - Hook System with 4 interceptor types ([Changelog](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.6.md))
49
+ - **v2.5** - Architectural consolidation and API consistency ([Changelog](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.5.md))
50
+ - **v2.4** - Multi-default export handling ([Changelog](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.4.md))
51
+ - **v2.3** - EventEmitter & Class Context Propagation ([Changelog](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.3.md))
52
+ - **v2.2** - Case preservation options ([Changelog](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.2.md))
53
+ - **v2.1** - Advanced sanitization patterns ([Changelog](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.1.md))
54
+ - **v2.0** - Complete Architectural Rewrite ([Changelog](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.0.md))
49
55
 
50
- - **Modular Design**: Organized into `engine/`, `modes/`, `runtime/`, and `helpers/`
51
- - **Live-Binding System**: Dynamic context and reference binding with runtime coordination
52
- - **Smart Function Naming**: Preserves original capitalization (`autoIP`, `parseJSON`, `getHTTPStatus`)
53
- - **Multi-Execution Environments**: Singleton, VM, worker, fork isolation modes (experimental)
54
-
55
- ### 🔧 **Advanced Sanitization Control** ⭐ NEW
56
-
57
- - **Custom API Naming**: Control how filenames become API property names through sanitize options
58
- - **Boundary Pattern Matching**: Use `**string**` patterns for precise transformations (`**url**` → `buildURLWithParams`)
59
- - **Glob Pattern Support**: Apply rules with wildcards (`*json*`, `auto*`, `http*`) for flexible naming control
60
- - **Case-Sensitive Rules**: Preserve important naming patterns (acronyms, technical terms, branding)
61
- - **Mixed Rule Types**: Combine exact matches, globs, and boundary patterns for sophisticated naming strategies
62
-
63
- ### 📊 **Performance Optimizations**
64
-
65
- - **Startup**: Lazy mode 4.3x faster (564.17μs vs 2.45ms)
66
- - **Function Calls**: Eager mode 1.1x faster (0.65μs vs 0.72μs) after materialization
67
- - **Memory**: On-demand loading scales with actual usage
68
- - **Predictability**: Consistent performance characteristics per mode
69
-
70
- ### 🔄 **Context Propagation (v2.3)** ⭐ NEW
71
-
72
- - **EventEmitter Context Propagation**: Automatic context preservation across EventEmitter callbacks using AsyncResource patterns
73
- - **Class Instance Context Propagation**: Automatic context preservation across class method calls with transparent wrapping
74
- - **AsyncResource Integration**: Production-ready context management following Node.js best practices
75
- - **Zero Configuration**: Works automatically with TCP servers, HTTP servers, and any EventEmitter-based patterns
76
-
77
- ### 🎣 **Hook System (v2.6.4)** ⭐ NEW
78
-
79
- - **3-Hook Types**: `before` (modify args or cancel), `after` (transform results), `always` (observe final result)
80
- - **Cross-Mode Compatibility**: Works seamlessly across all 4 combinations (eager/lazy × async/live)
81
- - **Pattern Matching**: Target specific functions or use wildcards (`math.*`, `*.add`, `**`)
82
- - **Priority Control**: Order hook execution with numeric priorities
83
- - **Runtime Control**: Enable/disable hooks at runtime, globally or by pattern
84
- - **Short-Circuit Support**: Cancel execution and return custom values from `before` hooks
85
-
86
- ---
87
-
88
- ## 🚀 Key Features
89
-
90
- ### 🎯 **Dual Loading Strategies**
91
-
92
- - **Eager Loading**: Immediate loading for maximum performance in production environments
93
- - **Lazy Loading**: Copy-left materialization with look-ahead proxies (4.3x faster startup, 1.1x slower calls after materialization)
94
-
95
- > [!IMPORTANT]
96
- > **Function Call Patterns:**
97
- >
98
- > - **Lazy Mode**: ALL function calls must be awaited (`await api.math.add(2, 3)`) due to materialization process
99
- > - **Eager Mode**: Functions behave as originally defined - sync functions are sync (`api.math.add(2, 3)`), async functions are async (`await api.async.process()`)
100
-
101
- ### ⚡ Performance Excellence
102
-
103
- - **📊 For comprehensive performance analysis, benchmarks, and recommendations, see [PERFORMANCE.md](https://github.com/CLDMV/slothlet/blob/HEAD/PERFORMANCE.md)**
104
-
105
- ### 🔧 **Smart API Management**
106
-
107
- - **Callable Interface**: Use `slothlet(options)` for direct API creation
108
- - **Smart Flattening**: Intelligent rules create clean APIs (`math/math.mjs` → `api.math`, `connection.mjs` → `api.connect()`)
109
- - **Intelligent Naming**: Dash-separated names convert automatically (`root-math.mjs` → `api.rootMath`)
110
- - **Function Name Preservation**: Maintains original capitalization (`auto-ip.mjs` with `autoIP` → `api.autoIP`)
111
- - **Hybrid Exports**: Support for callable APIs with methods, default + named exports, and mixed patterns
112
-
113
- > [!TIP]
114
- > **📁 For comprehensive examples of API flattening, naming conventions, and function preservation patterns, see the test modules in [api_tests/](https://github.com/CLDMV/slothlet/blob/HEAD/api_tests) and their documentation in [docs/api_tests/](https://github.com/CLDMV/slothlet/blob/HEAD/docs/api_tests)**
115
-
116
- > [!NOTE]
117
- > **🔍 For detailed technical documentation on API transformation rules:**
118
- >
119
- > - **[API-RULES.md](https://github.com/CLDMV/slothlet/blob/HEAD/API-RULES.md)** - Verified API transformation rules with examples and test cases
120
- > - **[API-RULES-CONDITIONS.md](https://github.com/CLDMV/slothlet/blob/HEAD/API-RULES-CONDITIONS.md)** - Complete technical reference of all conditional logic that controls API generation
121
-
122
- ### 🔗 **Advanced Binding System**
123
-
124
- - **Live Bindings**: Dynamic context and reference binding for runtime API mutation
125
- - **Context Isolation**: Dual runtime options for per-instance context isolation with seamless integration
126
- - **Copy-Left Preservation**: Materialized functions stay materialized, preserving performance gains
127
- - **Bubble-Up Updates**: Parent API synchronization ensures consistency across the API tree
128
- - **Mixed Module Support**: Seamlessly blend ESM and CommonJS modules in the same API
129
-
130
- ### 🛠 **Developer Experience**
131
-
132
- - **Enhanced Error Handling**: Clear JavaScript errors with module suggestions and descriptive errors (planned for v3.0.0)
133
- - **TypeScript-Friendly**: Comprehensive JSDoc annotations for excellent editor support with auto-generated declarations
134
- - **Configurable Debug**: Detailed logging for development and troubleshooting via CLI flags or environment variables
135
- - **Multiple Instances**: Parameter-based isolation for complex applications with instance ID management
136
- - **Development Checks**: Built-in environment detection with silent production behavior
137
-
138
- ### 🏗 **Architecture & Compatibility**
139
-
140
- - **ESM-First**: Built for modern JavaScript with full ES module support
141
- - **Universal Loading**: CommonJS and ESM files work together seamlessly
142
- - **Zero Dependencies**: Lightweight footprint with no external dependencies
143
- - **Cross-Platform**: Works seamlessly across all Node.js environments
144
- - **Extensible**: Modular architecture with flexible API composition patterns
145
-
146
- ---
147
-
148
- ## 📦 Installation
149
-
150
- ### Requirements
151
-
152
- - **Node.js v12.20.0 or higher** (for ESM support with `import`/`export`)
153
- - **Node.js v16.4.0 or higher** (recommended for AsyncLocalStorage runtime - `runtime: "async"`)
154
-
155
- > [!IMPORTANT]
156
- > **v2.x Runtime Options**: Slothlet v2.x supports two runtime systems:
157
- >
158
- > - **AsyncLocalStorage Runtime** (`runtime: "async"`) - Default, requires Node.js v16.4.0+ for context isolation
159
- > - **Live Bindings Runtime** (`runtime: "live"`) - Advanced system, works on Node.js v12.20.0+ without AsyncLocalStorage
160
- >
161
- > Both runtimes provide full live-binding capabilities with `self`, `context`, and `reference` support across ESM and CommonJS modules. Use `runtime: "live"` for older Node.js versions or advanced binding scenarios.
162
-
163
- ### Install
164
-
165
- ```bash
166
- npm install @cldmv/slothlet
167
- ```
168
-
169
- ---
170
-
171
- ## 🚀 Quick Start
172
-
173
- ### ESM (ES Modules)
174
-
175
- ```javascript
176
- import slothlet from "@cldmv/slothlet";
177
-
178
- // Direct usage - eager mode by default (auto-detects callable interface)
179
- const api = await slothlet({
180
- dir: "./api",
181
- context: { user: "alice" }
182
- });
183
-
184
- // Eager mode: Functions behave as originally defined
185
- const result = api.math.add(2, 3); // Sync function - no await needed
186
- const greeting = api("World"); // Instant if callable
187
-
188
- // Original async functions still need await in eager mode
189
- const asyncResult = await api.async.processData({ data: "async" });
190
-
191
- // Access both ESM and CJS modules seamlessly
192
- const esmResult = api.mathEsm.multiply(4, 5); // 20 (sync)
193
- const cjsResult = await api.mathCjs.divide(10, 2); // 5 (if originally async)
194
- ```
195
-
196
- ### CommonJS (CJS)
197
-
198
- ```javascript
199
- const slothlet = require("@cldmv/slothlet");
200
-
201
- // Same usage pattern works with CommonJS
202
- const api = await slothlet({
203
- dir: "./api",
204
- context: { env: "production" }
205
- });
206
-
207
- const result = api.math.multiply(4, 5); // 20
208
- const mixedResult = await api.interop.processData({ data: "test" }); // CJS+ESM interop
209
- ```
210
-
211
- ### Runtime Selection
212
-
213
- ```javascript
214
- // AsyncLocalStorage runtime (default) - requires Node.js v16.4.0+
215
- const apiAsync = await slothlet({
216
- dir: "./api",
217
- runtime: "async", // or "asynclocalstorage"
218
- context: { user: "alice" }
219
- });
220
-
221
- // Live bindings runtime - works on Node.js v12.20.0+
222
- const apiLive = await slothlet({
223
- dir: "./api",
224
- runtime: "live", // or "livebindings"
225
- context: { user: "bob" }
226
- });
227
-
228
- // Both provide identical live-binding capabilities
229
- import { self, context, reference } from "@cldmv/slothlet/runtime";
230
- // context.user is available in your modules regardless of runtime choice
231
- ```
232
-
233
- ### Lazy Loading Mode
234
-
235
- ```javascript
236
- import slothlet from "@cldmv/slothlet";
237
-
238
- // Lazy mode with copy-left materialization
239
- const api = await slothlet({
240
- mode: "lazy", // New preferred syntax
241
- dir: "./api",
242
- apiDepth: 3
243
- });
244
-
245
- // Or use legacy syntax (still supported)
246
- const apiLegacy = await slothlet({
247
- lazy: true, // Legacy syntax
248
- dir: "./api",
249
- apiDepth: 3
250
- });
251
-
252
- // First access: ~310μs (materialization overhead)
253
- const result1 = await api.math.add(2, 3);
254
-
255
- // Subsequent access: ~0.5μs (materialized function)
256
- const result2 = await api.math.add(5, 7); // 700x faster than first call!
257
- ```
258
-
259
- ### Advanced Configuration
260
-
261
- ```javascript
262
- import slothlet from "@cldmv/slothlet";
263
-
264
- const api = await slothlet({
265
- dir: "./api",
266
- mode: "eager", // New: Loading strategy (lazy/eager)
267
- engine: "singleton", // New: Execution environment
268
- api_mode: "auto", // API structure behavior
269
- apiDepth: Infinity, // Directory traversal depth
270
- debug: false, // Enable verbose logging
271
- context: {
272
- // Injected into live-binding
273
- user: "alice",
274
- env: "production",
275
- config: { timeout: 5000 }
276
- },
277
- reference: {
278
- // Merged into API root
279
- version: "2.0.0",
280
- helpers: {
281
- /* ... */
282
- }
283
- },
284
- sanitize: {
285
- // 🔧 NEW: Control API property naming
286
- lowerFirst: false, // Keep first character casing
287
- rules: {
288
- leave: ["parseJSON", "autoIP"], // Preserve exact names
289
- leaveInsensitive: ["*xml*"], // Case-insensitive preservation
290
- upper: ["**url**", "api", "http*"], // Force uppercase (including boundary patterns)
291
- lower: ["id", "uuid", "*id"] // Force lowercase
292
- }
293
- }
294
- });
295
- ```
296
-
297
- ### Sanitize Options Examples
298
-
299
- Transform module filenames into clean, professional API property names with sophisticated control:
300
-
301
- ```javascript
302
- // Without sanitize options (default behavior)
303
- const api = await slothlet({ dir: "./api" });
304
- // Files: build-url-with-params.mjs, parse-json-data.mjs, auto-ip.mjs
305
- // Result: api.buildUrlWithParams, api.parseJsonData, api.autoIp
306
-
307
- // With sanitize options (custom naming control)
308
- const api = await slothlet({
309
- dir: "./api",
310
- sanitize: {
311
- lowerFirst: false, // Keep first character casing
312
- preserveAllUpper: true, // Preserve identifiers like "COMMON_APPS"
313
- preserveAllLower: false, // Transform identifiers like "common_apps"
314
- rules: {
315
- leave: ["parseJSON"], // Exact match preservation (case-sensitive)
316
- leaveInsensitive: ["*xml*"], // Case-insensitive preservation
317
- upper: ["**url**", "ip", "http*"], // Force uppercase transformations
318
- lower: ["id", "*id"] // Force lowercase transformations
319
- }
320
- }
321
- });
322
- // Result: api.buildURLWithParams, api.parseJSON, api.autoIP
323
- ```
324
-
325
- **Comprehensive Sanitize Configuration:**
326
-
327
- ```javascript
328
- const api = await slothlet({
329
- dir: "./api",
330
- sanitize: {
331
- // Basic Options
332
- lowerFirst: true, // Default: lowercase first character for camelCase
333
- preserveAllUpper: true, // Keep "COMMON_APPS" unchanged
334
- preserveAllLower: false, // Transform "common_apps" → "commonApps"
335
-
336
- rules: {
337
- // Preserve exact matches (case-sensitive)
338
- leave: ["parseJSON", "autoIP", "getHTTPStatus"],
339
-
340
- // Preserve patterns (case-insensitive)
341
- leaveInsensitive: ["*xml*", "*html*"],
342
-
343
- // Force uppercase transformations
344
- upper: [
345
- "api", // Exact: "api" → "API"
346
- "http*", // Glob: "httpGet" → "HTTPGet"
347
- "**url**", // Boundary: "buildUrlPath" → "buildURLPath"
348
- "**json**" // Boundary: "parseJsonData" → "parseJSONData"
349
- ],
350
-
351
- // Force lowercase transformations
352
- lower: [
353
- "id", // Exact: "ID" → "id"
354
- "*id", // Glob: "userId" → "userid"
355
- "uuid*" // Glob: "UUIDGenerator" → "uuidGenerator"
356
- ]
357
- }
358
- }
359
- });
360
- ```
361
-
362
- **Sanitize Pattern Types:**
363
-
364
- - **Exact Match**: `"parseJSON"` - Matches exact string only
365
- - **Glob Patterns**:
366
- - `"*json*"` - Matches anywhere in string (`parseJsonData`)
367
- - `"auto*"` - Matches at start (`autoGenerateId`)
368
- - `"*id"` - Matches at end (`userId`)
369
- - **Boundary Patterns**:
370
- - `"**url**"` - Only matches when surrounded by characters (`buildUrlPath` ✓, `url` ✗)
371
- - `"**json**"` - Matches `parseJsonData` but not standalone `json`
372
- - **Case Control**:
373
- - `leave` - Case-sensitive exact preservation
374
- - `leaveInsensitive` - Case-insensitive preservation
375
- - `preserveAllUpper`/`preserveAllLower` - Automatic case detection
376
-
377
- **Advanced Pattern Examples:**
378
-
379
- ```javascript
380
- // File transformations with patterns:
381
- sanitizePathName("build-url-with-params", {
382
- rules: { upper: ["**url**"] }
383
- }); // → "buildURLWithParams"
384
-
385
- sanitizePathName("parse-json-data", {
386
- rules: { upper: ["**json**"] }
387
- }); // → "parseJSONData"
388
-
389
- sanitizePathName("get-http-status", {
390
- rules: { upper: ["http*"] }
391
- }); // → "getHTTPStatus"
392
-
393
- sanitizePathName("validate-user-id", {
394
- rules: { lower: ["*id"] }
395
- }); // → "validateUserid"
396
-
397
- sanitizePathName("XML_PARSER", {
398
- preserveAllUpper: true
399
- }); // → "XML_PARSER" (preserved)
400
- ```
401
-
402
- ### Multiple Instances
403
-
404
- In v2.x, each call to `slothlet(options)` automatically creates a new isolated instance with its own context and configuration:
405
-
406
- #### ESM (ES Modules)
407
-
408
- ```javascript
409
- import slothlet from "@cldmv/slothlet";
410
-
411
- // Each call creates a new isolated instance automatically
412
- const api1 = await slothlet({ dir: "./api1", context: { tenant: "alice" } });
413
- const api2 = await slothlet({ dir: "./api2", context: { tenant: "bob" } });
414
-
415
- // Instances are completely isolated
416
- console.log(api1.context.tenant); // "alice"
417
- console.log(api2.context.tenant); // "bob"
418
- ```
419
-
420
- #### CommonJS (CJS)
421
-
422
- ```javascript
423
- const slothlet = require("@cldmv/slothlet");
424
-
425
- // Each call creates a new isolated instance automatically
426
- const api1 = await slothlet({ dir: "./api1", context: { tenant: "alice" } });
427
- const api2 = await slothlet({ dir: "./api2", context: { tenant: "bob" } });
428
-
429
- // Instances are completely isolated with their own AsyncLocalStorage contexts
430
- console.log(api1.context.tenant); // "alice"
431
- console.log(api2.context.tenant); // "bob"
432
- ```
433
-
434
- > [!NOTE]
435
- > **v2.x Simplification**: Unlike v1.x which required query string parameters or `withInstanceId()` methods, v2.x automatically creates isolated instances with each `slothlet()` call, using your chosen runtime system (`async` or `live`) for complete context separation.
436
-
437
- ---
438
-
439
- ## 📚 API Reference
440
-
441
- ### Core Methods
442
-
443
- #### `slothlet(options)` ⇒ `Promise<object>`
444
-
445
- Creates and loads an API instance with the specified configuration.
446
-
447
- **Parameters:**
448
-
449
- | Param | Type | Description |
450
- | ------- | -------- | --------------------- |
451
- | options | `object` | Configuration options |
452
-
453
- **Returns:** `Promise<object>` - The bound API object
454
-
455
- **Options:**
456
-
457
- | Option | Type | Default | Description |
458
- | ----------- | --------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
459
- | `dir` | `string` | `"api"` | Directory to load API modules from. Can be absolute or relative path. If relative, resolved from process.cwd(). |
460
- | `lazy` | `boolean` | `false` | **Legacy** loading strategy - `true` for lazy loading (on-demand), `false` for eager loading (immediate). Use `mode` option instead. |
461
- | `mode` | `string` | - | **New** loading mode - `"lazy"` for on-demand loading, `"eager"` for immediate loading. Takes precedence over `lazy` option. Also supports execution modes for backward compatibility. |
462
- | `engine` | `string` | `"singleton"` | **New** execution environment mode - `"singleton"`, `"vm"`, `"worker"`, or `"fork"` |
463
- | `runtime` | `string` | `"async"` | Runtime binding system: `"async"` for AsyncLocalStorage-based context isolation (default, requires Node.js v16.4.0+), `"live"` for advanced live-binding system (works on Node.js v12.20.0+). Both provide full live-binding capabilities. |
464
- | `apiDepth` | `number` | `Infinity` | Directory traversal depth control - `0` for root only, `Infinity` for all levels |
465
- | `debug` | `boolean` | `false` | Enable verbose logging. Can also be set via `--slothletdebug` command line flag or `SLOTHLET_DEBUG=true` environment variable |
466
- | `api_mode` | `string` | `"auto"` | API structure behavior when root-level default functions exist:<br/>• `"auto"`: Automatically detects if root has default function export and creates callable API<br/>• `"function"`: Forces API to be callable (use when you have root-level default function exports)<br/>• `"object"`: Forces API to be object-only (use when you want object interface regardless of exports) |
467
- | `allowApiOverwrite` | `boolean` | `true` | Controls whether `addApi()` can overwrite existing API endpoints:<br/>• `true`: Allow overwrites (default, backwards compatible)<br/>• `false`: Prevent overwrites - logs warning and skips when attempting to overwrite existing endpoints<br/>Applies to both function and object overwrites at the final key of the API path |
468
- | `context` | `object` | `{}` | Context data object injected into live-binding `context` reference. Available to all loaded modules via `import { context } from "@cldmv/slothlet/runtime"` |
469
- | `reference` | `object` | `{}` | Reference object merged into the API root level. Properties not conflicting with loaded modules are added directly to the API |
470
- | `sanitize` | `object` | `{}` | **🔧 NEW**: Advanced filename-to-API transformation control. Options: `lowerFirst` (boolean), `preserveAllUpper` (boolean), `preserveAllLower` (boolean), `rules` object with `leave` (exact case-sensitive), `leaveInsensitive` (case-insensitive), `upper`/`lower` arrays. Supports exact matches, glob patterns (`*json*`, `http*`), and boundary patterns (`**url**` for surrounded matches only) |
471
-
472
- #### ✨ Current Option Format
473
-
474
- The option structure has been improved for better clarity:
475
-
476
- ```javascript
477
- // ✅ New recommended syntax
478
- const api = await slothlet({
479
- mode: "lazy", // Loading strategy: "lazy" | "eager"
480
- engine: "singleton", // Execution environment: "singleton" | "vm" | "worker" | "fork"
481
- dir: "./api"
482
- });
483
-
484
- // ✅ Legacy syntax (still fully supported)
485
- const api = await slothlet({
486
- lazy: true, // Boolean loading strategy
487
- mode: "singleton", // Execution environment (legacy placement)
488
- dir: "./api"
489
- });
490
-
491
- // ✅ Mixed usage (mode takes precedence)
492
- const api = await slothlet({
493
- lazy: false, // Will be overridden
494
- mode: "lazy", // Takes precedence - results in lazy loading
495
- engine: "singleton"
496
- });
497
- ```
498
-
499
- **Benefits of the new syntax:**
500
-
501
- - **Clearer separation**: `mode` for loading strategy, `engine` for execution environment
502
- - **Better discoverability**: String values are more self-documenting than boolean flags
503
- - **Future-proof**: Easier to extend with additional loading strategies
504
- - **Backward compatible**: All existing code continues to work unchanged
505
-
506
- #### `slothlet.getApi()` ⇒ `object`
507
-
508
- Returns the raw API object (Proxy or plain object).
509
-
510
- **Returns:** `function | object` - The raw API object or function
511
-
512
- #### `slothlet.getBoundApi()` ⇒ `object`
513
-
514
- Returns the bound API object with context and reference.
515
-
516
- **Returns:** `function | object` - The bound API object or function with live bindings and context
517
-
518
- #### `slothlet.isLoaded()` ⇒ `boolean`
519
-
520
- Returns true if the API is loaded.
521
-
522
- **Returns:** `boolean` - Whether the API has been loaded
523
-
524
- #### `slothlet.shutdown()` ⇒ `Promise<void>`
525
-
526
- Gracefully shuts down the API and performs comprehensive resource cleanup to prevent hanging processes.
527
-
528
- **Cleanup includes:**
529
-
530
- - Hook manager state and registered hooks
531
- - AsyncLocalStorage context and bindings
532
- - EventEmitter listeners and AsyncResource instances (including third-party libraries)
533
- - Instance data and runtime coordination
534
-
535
- **Returns:** `Promise<void>` - Resolves when shutdown is complete
536
-
537
- > [!IMPORTANT]
538
- > **🛡️ Process Cleanup**: The shutdown method now performs comprehensive cleanup of all EventEmitter listeners created after slothlet loads, including those from third-party libraries like pg-pool. This prevents hanging AsyncResource instances that could prevent your Node.js process from exiting cleanly.
539
-
540
- #### `api.addApi(apiPath, folderPath)` ⇒ `Promise<void>` ⭐ NEW
541
-
542
- Dynamically extend your API at runtime by loading additional modules and merging them into a specified path.
543
-
544
- **Parameters:**
545
-
546
- | Param | Type | Description |
547
- | ------------ | -------- | ------------------------------------------------------------------- |
548
- | `apiPath` | `string` | Dotted path where modules will be added (e.g., `"runtime.plugins"`) |
549
- | `folderPath` | `string` | Path to folder containing modules to load (relative or absolute) |
550
-
551
- **Returns:** `Promise<void>` - Resolves when the API extension is complete
552
-
553
- **Features:**
554
-
555
- - ✅ **Dynamic Loading**: Add modules after initial API creation
556
- - ✅ **Path Creation**: Automatically creates intermediate objects for nested paths
557
- - ✅ **Smart Merging**: Merges into existing objects or creates new namespaces
558
- - ✅ **Mode Respect**: Uses same loading mode (lazy/eager) as parent API
559
- - ✅ **Live Binding Updates**: Automatically updates `self`, `context`, and `reference`
560
- - ✅ **Function Support**: Can traverse through functions (slothlet's function.property pattern)
561
- - ✅ **Validation**: Prevents extension through primitives, validates path format
562
- - ✅ **Overwrite Protection**: Optional `allowApiOverwrite` config prevents accidental endpoint overwrites
563
-
564
- **Configuration:**
565
-
566
- The `allowApiOverwrite` option controls whether `addApi` can overwrite existing endpoints:
567
-
568
- ```javascript
569
- // Default behavior - allows overwrites (backwards compatible)
570
- const api = await slothlet({
571
- dir: "./api",
572
- allowApiOverwrite: true // default
573
- });
574
- await api.addApi("tools", "./new-tools"); // Overwrites existing api.tools
575
-
576
- // Protected mode - prevents overwrites
577
- const api = await slothlet({
578
- dir: "./api",
579
- allowApiOverwrite: false // protection enabled
580
- });
581
- await api.addApi("tools", "./new-tools"); // Logs warning and skips
582
- // Console: "[slothlet] Skipping addApi: API path "tools" final key "tools" already exists..."
583
- ```
584
-
585
- **Usage Examples:**
586
-
587
- ```javascript
588
- const api = await slothlet({ dir: "./api" });
589
-
590
- // Add modules to nested path
591
- await api.addApi("runtime.plugins", "./plugins");
592
- api.runtime.plugins.myPlugin(); // New modules accessible
593
-
594
- // Add to root level
595
- await api.addApi("utilities", "./utils");
596
- api.utilities.helperFunc(); // Root-level addition
597
-
598
- // Deep nesting (creates intermediate objects)
599
- await api.addApi("services.external.github", "./integrations/github");
600
- api.services.external.github.getUser(); // Deep path created
601
-
602
- // Merge into existing namespace
603
- await api.addApi("math", "./advanced-math"); // Merges with existing api.math
604
- api.math.add(2, 3); // Original functions preserved
605
- api.math.advancedCalc(); // New functions added
606
- ```
607
-
608
- **Path Validation:**
609
-
610
- ```javascript
611
- // ❌ Invalid paths throw errors
612
- await api.addApi("", "./modules"); // Empty string
613
- await api.addApi(".path", "./modules"); // Leading dot
614
- await api.addApi("path.", "./modules"); // Trailing dot
615
- await api.addApi("path..name", "./modules"); // Consecutive dots
616
-
617
- // ✅ Valid paths
618
- await api.addApi("simple", "./modules"); // Single segment
619
- await api.addApi("nested.path", "./modules"); // Dotted path
620
- await api.addApi("very.deep.nested", "./modules"); // Multi-level
621
- ```
622
-
623
- **Type Safety:**
624
-
625
- ```javascript
626
- // ✅ Can extend through objects and functions
627
- api.logger = { info: () => {} };
628
- await api.addApi("logger.plugins", "./logger-plugins"); // Works - object
629
-
630
- api.handler = () => "handler";
631
- await api.addApi("handler.middleware", "./middleware"); // Works - function
632
-
633
- // ❌ Cannot extend through primitives
634
- api.config.timeout = 5000;
635
- await api.addApi("config.timeout.advanced", "./modules"); // Throws error
636
- ```
637
-
638
- > [!WARNING]
639
- > **⚠️ Concurrency Limitation:** The `addApi` method is **not thread-safe**. Concurrent calls to `addApi` with overlapping paths may result in race conditions and inconsistent API state. Ensure calls are properly sequenced using `await` or other synchronization mechanisms. Do not call `addApi` from multiple threads/workers simultaneously.
640
-
641
- > [!NOTE]
642
- > **📚 For detailed API documentation with comprehensive parameter descriptions, method signatures, and examples, see [docs/API.md](https://github.com/CLDMV/slothlet/blob/HEAD/docs/API.md)**
643
-
644
- ### Live Bindings
645
-
646
- Access live-bound references in your API modules:
647
-
648
- ```javascript
649
- // Create API with reference functions
650
- const api = await slothlet({
651
- dir: "./api",
652
- reference: {
653
- md5: (str) => crypto.createHash("md5").update(str).digest("hex"),
654
- version: "2.0.0",
655
- utils: { format: (msg) => `[LOG] ${msg}` }
656
- }
657
- });
658
- ```
659
-
660
- ```javascript
661
- // In your API modules (ESM)
662
- import { self, context, reference } from "@cldmv/slothlet/runtime";
663
-
664
- export function myFunction() {
665
- console.log(context.user); // Access live context
666
- return self.otherModule.helper(); // Access other API modules
667
-
668
- // Reference functions are available directly on self
669
- const hash = self.md5("hello world"); // Access reference function
670
- console.log(self.version); // Access reference data
671
- }
672
-
673
- // Mixed module example (ESM accessing CJS)
674
- export function processData(data) {
675
- // Call a CJS module from ESM
676
- const processed = self.cjsModule.process(data);
677
-
678
- // Use reference utilities directly
679
- const logged = self.utils.format(`Processed: ${processed}`);
680
- return self.md5(logged); // Hash the result
681
- }
682
- ```
683
-
684
- ```javascript
685
- // In your CJS modules
686
- const { self, context, reference } = require("@cldmv/slothlet/runtime");
687
-
688
- function cjsFunction(data) {
689
- console.log(context.env); // Access live context
690
-
691
- // Reference functions available directly on self
692
- const hash = self.md5(data); // Direct access to reference function
693
-
694
- return self.esmModule.transform(hash); // Access ESM modules from CJS
695
- }
696
-
697
- module.exports = { cjsFunction };
698
- ```
699
-
700
- ### EventEmitter Context Propagation
701
-
702
- Slothlet automatically preserves AsyncLocalStorage context across all EventEmitter callbacks using Node.js AsyncResource patterns. This ensures your API modules maintain full context access in event handlers without any configuration.
703
-
704
- ```javascript
705
- // api/tcp-server.mjs - Your API module
706
- import { self, context } from "@cldmv/slothlet/runtime";
707
- import net from "node:net";
708
-
709
- export function createTcpServer() {
710
- const server = net.createServer();
711
-
712
- // Connection handler maintains full context automatically
713
- server.on("connection", (socket) => {
714
- console.log(`User: ${context.user}`); // ✅ Context preserved
715
- console.log(`API keys: ${Object.keys(self).length}`); // ✅ Full API access
716
-
717
- // Socket data handler also maintains context automatically
718
- socket.on("data", (data) => {
719
- console.log(`Session: ${context.session}`); // ✅ Context preserved
720
- console.log(`Processing for: ${context.user}`); // ✅ Context preserved
721
-
722
- // Full API access in nested event handlers
723
- const processed = self.dataProcessor.handle(data.toString());
724
- socket.write(processed);
725
- });
726
-
727
- socket.on("error", (err) => {
728
- // Error handlers also maintain context
729
- self.logger.error(`Error for user ${context.user}: ${err.message}`);
730
- });
731
- });
732
-
733
- return server;
734
- }
735
-
736
- export function startServer(port = 3000) {
737
- const server = createTcpServer();
738
- server.listen(port);
739
- return server;
740
- }
741
- ```
742
-
743
- ```javascript
744
- // Usage in your application
745
- import slothlet from "@cldmv/slothlet";
746
-
747
- const api = await slothlet({
748
- dir: "./api",
749
- context: { user: "alice", session: "tcp-session" }
750
- });
751
-
752
- // Start the server - all event handlers will have full context
753
- const server = api.startServer(8080);
754
- console.log("TCP server started with context preservation");
755
- ```
756
-
757
- **Key Benefits:**
758
-
759
- - ✅ **Automatic**: No configuration needed - works transparently in all API modules
760
- - ✅ **Complete Context**: Full `context` object and `self` API access in all event handlers
761
- - ✅ **Nested Events**: Works with any depth of EventEmitter nesting (server → socket → custom emitters)
762
- - ✅ **Universal Support**: All EventEmitter methods (`on`, `once`, `addListener`) are automatically context-aware
763
- - ✅ **Production Ready**: Uses Node.js AsyncResource patterns for reliable context propagation
764
- - ✅ **Clean Shutdown**: Automatically cleans up all AsyncResource instances during shutdown to prevent hanging processes
765
- - ✅ **Zero Overhead**: Only wraps listeners when context is active, minimal performance impact
766
-
767
- > [!TIP]
768
- > **Automatic Context Propagation**: EventEmitter context propagation works automatically in both lazy and eager modes. TCP servers, HTTP servers, custom EventEmitters, and any other event-driven patterns in your API modules will maintain full slothlet context and API access without any code changes.
769
-
770
- ### Class Instance Context Propagation
771
-
772
- Slothlet automatically preserves AsyncLocalStorage context across all class instance method calls. When your API functions return class instances, slothlet wraps them transparently to ensure all method calls maintain full context access.
773
-
774
- ```javascript
775
- // api/data-processor.mjs - Your API module
776
- import { self, context } from "@cldmv/slothlet/runtime";
777
-
778
- class DataProcessor {
779
- constructor(config) {
780
- this.config = config;
781
- }
782
-
783
- process(data) {
784
- // Context automatically available in all methods
785
- console.log(`Processing for user: ${context.user}`); // ✅ Context preserved
786
- console.log(`Request ID: ${context.requestId}`); // ✅ Context preserved
787
-
788
- // Full API access in class methods
789
- const validated = self.validator.check(data);
790
- return this.transform(validated);
791
- }
792
-
793
- transform(data) {
794
- // Context preserved in nested method calls
795
- console.log(`Transforming for: ${context.user}`); // ✅ Context preserved
796
-
797
- // Call other API modules from class methods
798
- return self.utils.format(data);
799
- }
800
- }
801
-
802
- export function createProcessor(config) {
803
- // Return class instance - slothlet automatically wraps it
804
- return new DataProcessor(config);
805
- }
806
- ```
807
-
808
- ```javascript
809
- // Usage in your application
810
- import slothlet from "@cldmv/slothlet";
811
-
812
- const api = await slothlet({
813
- dir: "./api",
814
- context: { user: "alice", requestId: "req-123" }
815
- });
816
-
817
- // Create processor instance - all methods will have full context
818
- const processor = api.createProcessor({ format: "json" });
819
-
820
- // All method calls maintain context automatically
821
- const result = processor.process({ data: "test" });
822
- console.log("Processing completed with context preservation");
823
- ```
824
-
825
- **Key Benefits:**
826
-
827
- - ✅ **Automatic**: Class instances returned from API functions are automatically context-aware
828
- - ✅ **Transparent**: No code changes needed - works with existing class patterns
829
- - ✅ **Complete Context**: Full `context` object and `self` API access in all class methods
830
- - ✅ **Nested Methods**: Context preserved across method chains and internal calls
831
- - ✅ **Constructor Support**: Context preserved for both function calls and `new` constructor usage
832
- - ✅ **Performance Optimized**: Method wrapping is cached to avoid overhead on repeated calls
833
-
834
- > [!TIP]
835
- > **Universal Class Support**: Any class instance returned from your API functions automatically maintains slothlet context. This includes database models, service classes, utility classes, and any other object-oriented patterns in your codebase.
836
-
837
- ### Hook System
838
-
839
- Slothlet provides a powerful hook system for intercepting, modifying, and observing API function calls. Hooks work seamlessly across all loading modes (eager/lazy) and runtime types (async/live).
840
-
841
- #### Hook Configuration
842
-
843
- Hooks can be configured when creating a slothlet instance:
844
-
845
- ```javascript
846
- // Enable hooks (simple boolean)
847
- const api = await slothlet({
848
- dir: "./api",
849
- hooks: true // Enable all hooks with default pattern "**"
850
- });
851
-
852
- // Enable with custom pattern
853
- const api = await slothlet({
854
- dir: "./api",
855
- hooks: "database.*" // Only enable for database functions
856
- });
857
-
858
- // Full configuration object
859
- const api = await slothlet({
860
- dir: "./api",
861
- hooks: {
862
- enabled: true,
863
- pattern: "**", // Default pattern for filtering
864
- suppressErrors: false // Control error throwing behavior
865
- }
866
- });
867
- ```
868
-
869
- **Configuration Options:**
870
-
871
- - **`enabled`** (boolean): Enable or disable hook execution
872
- - **`pattern`** (string): Default pattern for filtering which functions hooks apply to
873
- - **`suppressErrors`** (boolean): Control error throwing behavior
874
- - `false` (default): Errors are sent to error hooks, THEN thrown (normal behavior)
875
- - `true`: Errors are sent to error hooks, BUT NOT thrown (returns `undefined`)
876
-
877
- **Error Suppression Behavior:**
878
-
879
- Error hooks **ALWAYS receive errors** regardless of this setting. The `suppressErrors` option only controls whether errors are thrown after error hooks execute.
880
-
881
- > [!IMPORTANT]
882
- > **Hooks Must Be Enabled**: Error hooks (and all hooks) only execute when `hooks.enabled: true`. If hooks are disabled, errors are thrown normally without any hook execution.
883
-
884
- When `suppressErrors: true`, errors are caught and sent to error hooks, but not thrown:
885
-
886
- ```javascript
887
- const api = await slothlet({
888
- dir: "./api",
889
- hooks: {
890
- enabled: true,
891
- pattern: "**",
892
- suppressErrors: true // Suppress all errors
893
- }
894
- });
895
-
896
- // Register error hook to monitor failures
897
- api.hooks.on(
898
- "error-monitor",
899
- "error",
900
- ({ path, error, source }) => {
901
- console.error(`Error in ${path}:`, error.message);
902
- // Log to monitoring service without crashing
903
- },
904
- { pattern: "**" }
905
- );
906
-
907
- // Function errors won't crash the application
908
- const result = await api.riskyOperation();
909
- if (result === undefined) {
910
- // Function failed but didn't throw
911
- console.log("Operation failed gracefully");
912
- }
913
- ```
914
-
915
- **Error Flow:**
916
-
917
- 1. Error occurs (in before hook, function, or after hook)
918
- 2. Error hooks execute and receive the error
919
- 3. **If `suppressErrors: false`** → Error is thrown (crashes if uncaught)
920
- 4. **If `suppressErrors: true`** → Error is NOT thrown, function returns `undefined`
921
-
922
- **What Gets Suppressed (when `suppressErrors: true`):**
923
-
924
- - ✅ Before hook errors → Sent to error hooks, NOT thrown
925
- - ✅ Function execution errors → Sent to error hooks, NOT thrown
926
- - ✅ After hook errors → Sent to error hooks, NOT thrown
927
- - ✅ Always hook errors → Sent to error hooks, never thrown (regardless of setting)
928
-
929
- > [!TIP]
930
- > **Use Case**: Enable `suppressErrors: true` for resilient systems where you want to monitor failures without crashing. Perfect for background workers, batch processors, or systems with comprehensive error monitoring.
931
-
932
- > [!CAUTION]
933
- > **Critical Operations**: For validation or authorization hooks where errors MUST stop execution, use `suppressErrors: false` (default) to ensure errors propagate normally.
934
-
935
- #### Hook Types
936
-
937
- **Four hook types with distinct responsibilities:**
938
-
939
- - **`before`**: Intercept before function execution
940
- - Modify arguments passed to functions
941
- - Cancel execution and return custom values (short-circuit)
942
- - Execute validation or logging before function runs
943
- - **`after`**: Transform results after successful execution
944
- - Transform function return values
945
- - Only runs if function executes (skipped on short-circuit)
946
- - Chain multiple transformations in priority order
947
- - **`always`**: Observe final result with full execution context
948
- - Always executes after function completes
949
- - Runs even when `before` hooks cancel execution or errors occur
950
- - Receives complete context: `{ path, result, hasError, errors }`
951
- - Cannot modify result (read-only observation)
952
- - Perfect for unified logging of both success and error scenarios
953
- - **`error`**: Monitor and handle errors
954
- - Receives detailed error context with source tracking
955
- - Error source types: 'before', 'function', 'after', 'always', 'unknown'
956
- - Includes error type, hook ID, hook tag, timestamp, and stack trace
957
- - Perfect for error monitoring, logging, and alerting
958
-
959
- #### Basic Usage
960
-
961
- ```javascript
962
- import slothlet from "@cldmv/slothlet";
963
-
964
- const api = await slothlet({
965
- dir: "./api",
966
- hooks: true // Enable hooks
967
- });
968
-
969
- // Before hook: Modify arguments
970
- api.hooks.on(
971
- "validate-input",
972
- "before",
973
- ({ path, args }) => {
974
- console.log(`Calling ${path} with args:`, args);
975
- // Return modified args or original
976
- return [args[0] * 2, args[1] * 2];
977
- },
978
- { pattern: "math.add", priority: 100 }
979
- );
980
-
981
- // After hook: Transform result
982
- api.hooks.on(
983
- "format-output",
984
- "after",
985
- ({ path, result }) => {
986
- console.log(`${path} returned:`, result);
987
- // Return transformed result
988
- return result * 10;
989
- },
990
- { pattern: "math.*", priority: 100 }
991
- );
992
-
993
- // Always hook: Observe final result with error context
994
- api.hooks.on(
995
- "log-execution",
996
- "always",
997
- ({ path, result, hasError, errors }) => {
998
- if (hasError) {
999
- console.log(`${path} failed with ${errors.length} error(s):`, errors);
1000
- } else {
1001
- console.log(`${path} succeeded with result:`, result);
1002
- }
1003
- // Return value ignored - read-only observer
1004
- },
1005
- { pattern: "**" } // All functions
1006
- );
1007
-
1008
- // Call function - hooks execute automatically
1009
- const result = await api.math.add(2, 3);
1010
- // Logs: "Calling math.add with args: [2, 3]"
1011
- // Logs: "math.add returned: 10" (4+6)
1012
- // Logs: "Final result for math.add: 100" (10*10)
1013
- // result === 100
1014
- ```
1015
-
1016
- #### Short-Circuit Execution
1017
-
1018
- `before` hooks can cancel function execution and return custom values:
1019
-
1020
- ```javascript
1021
- // Caching hook example
1022
- const cache = new Map();
1023
-
1024
- api.hooks.on(
1025
- "cache-check",
1026
- "before",
1027
- ({ path, args }) => {
1028
- const key = JSON.stringify({ path, args });
1029
- if (cache.has(key)) {
1030
- console.log(`Cache hit for ${path}`);
1031
- return cache.get(key); // Short-circuit: return cached value
1032
- }
1033
- // Return undefined to continue to function
1034
- },
1035
- { pattern: "**", priority: 1000 } // High priority
1036
- );
1037
-
1038
- api.hooks.on(
1039
- "cache-store",
1040
- "after",
1041
- ({ path, args, result }) => {
1042
- const key = JSON.stringify({ path, args });
1043
- cache.set(key, result);
1044
- return result; // Pass through
1045
- },
1046
- { pattern: "**", priority: 100 }
1047
- );
1048
-
1049
- // First call - executes function and caches
1050
- await api.math.add(2, 3); // Computes and stores
1051
-
1052
- // Second call - returns cached value (function not executed)
1053
- await api.math.add(2, 3); // Cache hit! No computation
1054
- ```
1055
-
1056
- #### Pattern Matching
1057
-
1058
- Hooks support flexible pattern matching:
1059
-
1060
- ```javascript
1061
- // Exact match
1062
- api.hooks.on("hook1", "before", handler, { pattern: "math.add" });
1063
-
1064
- // Wildcard: all functions in namespace
1065
- api.hooks.on("hook2", "before", handler, { pattern: "math.*" });
1066
-
1067
- // Wildcard: specific function in all namespaces
1068
- api.hooks.on("hook3", "before", handler, { pattern: "*.add" });
1069
-
1070
- // Global: all functions
1071
- api.hooks.on("hook4", "before", handler, { pattern: "**" });
1072
- ```
1073
-
1074
- #### Priority and Chaining
1075
-
1076
- Multiple hooks execute in priority order (highest first):
1077
-
1078
- ```javascript
1079
- // High priority - runs first
1080
- api.hooks.on(
1081
- "validate",
1082
- "before",
1083
- ({ args }) => {
1084
- if (args[0] < 0) throw new Error("Negative numbers not allowed");
1085
- return args;
1086
- },
1087
- { pattern: "math.*", priority: 1000 }
1088
- );
1089
-
1090
- // Medium priority - runs second
1091
- api.hooks.on("double", "before", ({ args }) => [args[0] * 2, args[1] * 2], { pattern: "math.*", priority: 500 });
1092
-
1093
- // Low priority - runs last
1094
- api.hooks.on(
1095
- "log",
1096
- "before",
1097
- ({ path, args }) => {
1098
- console.log(`Final args for ${path}:`, args);
1099
- return args;
1100
- },
1101
- { pattern: "math.*", priority: 100 }
1102
- );
1103
- ```
56
+ ---
1104
57
 
1105
- #### Runtime Control
58
+ ## 🚀 Key Features
1106
59
 
1107
- Enable and disable hooks at runtime:
60
+ ### 🎯 **Dual Loading Strategies**
1108
61
 
1109
- ```javascript
1110
- const api = await slothlet({ dir: "./api", hooks: true });
62
+ - **Eager Loading**: Immediate loading for maximum performance in production environments
63
+ - **Lazy Loading**: Copy-left materialization with look-ahead proxies (4.3x faster startup, 1.4x faster calls after materialization)
1111
64
 
1112
- // Add hooks
1113
- api.hooks.on("test", "before", handler, { pattern: "math.*" });
65
+ > [!IMPORTANT]
66
+ > **Function Call Patterns:**
67
+ >
68
+ > - **Lazy Mode**: ALL function calls must be awaited (`await api.math.add(2, 3)`) due to materialization process
69
+ > - **Eager Mode**: Functions behave as originally defined - sync functions are sync (`api.math.add(2, 3)`), async functions are async (`await api.async.process()`)
1114
70
 
1115
- // Disable all hooks
1116
- api.hooks.disable();
1117
- await api.math.add(2, 3); // No hooks execute
71
+ ### Performance Excellence
1118
72
 
1119
- // Re-enable all hooks
1120
- api.hooks.enable();
1121
- await api.math.add(2, 3); // Hooks execute
73
+ - **2.9x faster startup** in lazy mode (4.89ms vs 14.29ms)
74
+ - **1.1x faster function calls** in eager mode (0.90μs vs 0.99μs)
75
+ - **Copy-left materialization**: Once loaded, modules stay materialized
76
+ - **Zero dependencies**: Pure Node.js implementation
1122
77
 
1123
- // Enable specific pattern only
1124
- api.hooks.disable();
1125
- api.hooks.enable("math.*"); // Only math.* pattern enabled
1126
- await api.math.add(2, 3); // math.* hooks execute
1127
- await api.other.func(); // No hooks execute
1128
- ```
78
+ 📊 **For comprehensive performance analysis, benchmarks, and recommendations, see [docs/PERFORMANCE.md](https://github.com/CLDMV/slothlet/blob/master/docs/PERFORMANCE.md)**
1129
79
 
1130
- #### Hook Management
80
+ ### 🎣 **Hook System**
1131
81
 
1132
- ```javascript
1133
- // List registered hooks
1134
- const beforeHooks = api.hooks.list("before");
1135
- const afterHooks = api.hooks.list("after");
1136
- const allHooks = api.hooks.list(); // All types
82
+ Powerful function interceptor system with 4 hook types:
1137
83
 
1138
- // Remove specific hook by ID
1139
- const id = api.hooks.on("temp", "before", handler, { pattern: "math.*" });
1140
- api.hooks.off(id);
84
+ - **`before`** - Modify arguments or cancel execution
85
+ - **`after`** - Transform return values
86
+ - **`always`** - Observe final results (read-only)
87
+ - **`error`** - Monitor and handle errors with detailed source tracking
1141
88
 
1142
- // Remove all hooks matching pattern
1143
- api.hooks.off("math.*");
89
+ Pattern matching, priority control, runtime enable/disable, and short-circuit support included.
1144
90
 
1145
- // Clear all hooks of a type
1146
- api.hooks.clear("before"); // Remove all before hooks
1147
- api.hooks.clear(); // Remove all hooks
1148
- ```
91
+ 🎣 **For complete hook system documentation, see [docs/HOOKS.md](https://github.com/CLDMV/slothlet/blob/master/docs/HOOKS.md)**
1149
92
 
1150
- #### Error Handling
93
+ ### 🔄 **Context Propagation**
1151
94
 
1152
- Hooks have a special `error` type for observing function errors with detailed source tracking:
95
+ Automatic context preservation across all asynchronous boundaries:
1153
96
 
1154
- ```javascript
1155
- api.hooks.on(
1156
- "error-logger",
1157
- "error",
1158
- ({ path, error, source }) => {
1159
- console.error(`Error in ${path}:`, error.message);
1160
- console.error(`Source: ${source.type}`); // 'before', 'after', 'always', 'function', 'unknown'
97
+ - **EventEmitter propagation**: Context maintained across all event callbacks
98
+ - **Class instance propagation**: Context preserved in class method calls
99
+ - **Zero configuration**: Works automatically with TCP servers, HTTP servers, and custom EventEmitters
1161
100
 
1162
- if (source.type === "function") {
1163
- console.error("Error occurred in function execution");
1164
- } else if (["before", "after", "always"].includes(source.type)) {
1165
- console.error(`Error occurred in ${source.type} hook:`);
1166
- console.error(` Hook ID: ${source.hookId}`);
1167
- console.error(` Hook Tag: ${source.hookTag}`);
1168
- }
101
+ 🔄 **For context propagation details, see [docs/CONTEXT-PROPAGATION.md](https://github.com/CLDMV/slothlet/blob/master/docs/CONTEXT-PROPAGATION.md)**
1169
102
 
1170
- console.error(`Timestamp: ${source.timestamp}`);
1171
- console.error(`Stack trace:\n${source.stack}`);
103
+ ### 🔧 **Smart API Management**
1172
104
 
1173
- // Log to monitoring service with full context
1174
- // Error is re-thrown after all error hooks execute
1175
- },
1176
- { pattern: "**" }
1177
- );
105
+ - **Intelligent Flattening**: Clean APIs with automatic structure optimization (`math/math.mjs` → `api.math`)
106
+ - **Smart Naming**: Preserves original capitalization (`auto-ip.mjs` with `autoIP` `api.autoIP`)
107
+ - **Advanced Sanitization**: Custom naming rules with glob and boundary patterns
108
+ - **Hybrid Exports**: Support for callable APIs with methods, default + named exports
1178
109
 
1179
- try {
1180
- await api.validateData({ invalid: true });
1181
- } catch (error) {
1182
- // Error hooks executed before this catch block
1183
- console.log("Caught error:", error);
1184
- }
1185
- ```
110
+ 🏗️ **For module structure examples, see [docs/MODULE-STRUCTURE.md](https://github.com/CLDMV/slothlet/blob/master/docs/MODULE-STRUCTURE.md)**
111
+ 📐 **For API flattening rules, see [docs/API-FLATTENING.md](https://github.com/CLDMV/slothlet/blob/master/docs/API-FLATTENING.md)**
1186
112
 
1187
- ##### Error Source Tracking
113
+ ### 🔗 **Advanced Binding System**
1188
114
 
1189
- Error hooks receive detailed context about where errors originated:
115
+ - **Live Bindings**: Dynamic context and reference binding for runtime API mutation
116
+ - **Context Isolation**: Dual runtime options (AsyncLocalStorage or live-bindings)
117
+ - **Mixed Module Support**: Seamlessly blend ESM and CommonJS modules
118
+ - **Copy-Left Preservation**: Materialized functions stay materialized
1190
119
 
1191
- **Source Types:**
120
+ ### 🛠 **Developer Experience**
1192
121
 
1193
- - `"function"`: Error occurred during function execution
1194
- - `"before"`: Error occurred in a before hook
1195
- - `"after"`: Error occurred in an after hook
1196
- - `"always"`: Error occurred in an always hook
1197
- - `"unknown"`: Error source could not be determined
122
+ - **TypeScript-Friendly**: Comprehensive JSDoc annotations with auto-generated declarations
123
+ - **Configurable Debug**: Detailed logging via CLI flags or environment variables
124
+ - **Multiple Instances**: Parameter-based isolation for complex applications
125
+ - **Development Checks**: Built-in environment detection with silent production behavior
1198
126
 
1199
- **Source Metadata:**
127
+ ---
1200
128
 
1201
- - `source.type`: Error source type (see above)
1202
- - `source.hookId`: Hook identifier (for hook errors)
1203
- - `source.hookTag`: Hook tag/name (for hook errors)
1204
- - `source.timestamp`: ISO timestamp when error occurred
1205
- - `source.stack`: Full stack trace
129
+ ## 📦 Installation
1206
130
 
1207
- **Example: Comprehensive Error Monitoring**
131
+ ### Requirements
1208
132
 
1209
- ```javascript
1210
- const errorStats = {
1211
- function: 0,
1212
- before: 0,
1213
- after: 0,
1214
- always: 0,
1215
- byHook: {}
1216
- };
133
+ - **Node.js v16.4.0 or higher** (required for AsyncLocalStorage support)
1217
134
 
1218
- api.hooks.on(
1219
- "error-analytics",
1220
- "error",
1221
- ({ path, error, source }) => {
1222
- // Track error source statistics
1223
- errorStats[source.type]++;
1224
-
1225
- if (source.hookId) {
1226
- if (!errorStats.byHook[source.hookTag]) {
1227
- errorStats.byHook[source.hookTag] = 0;
1228
- }
1229
- errorStats.byHook[source.hookTag]++;
1230
- }
1231
-
1232
- // Log detailed error info
1233
- console.error(`[${source.timestamp}] Error in ${path}:`);
1234
- console.error(` Type: ${source.type}`);
1235
- console.error(` Message: ${error.message}`);
1236
-
1237
- if (source.type === "function") {
1238
- // Function-level error - might be a bug in implementation
1239
- console.error(" Action: Review function implementation");
1240
- } else {
1241
- // Hook-level error - might be a bug in hook logic
1242
- console.error(` Action: Review ${source.hookTag} hook (${source.type})`);
1243
- }
1244
-
1245
- // Send to monitoring service
1246
- sendToMonitoring({
1247
- timestamp: source.timestamp,
1248
- path,
1249
- errorType: source.type,
1250
- hookId: source.hookId,
1251
- hookTag: source.hookTag,
1252
- message: error.message,
1253
- stack: source.stack
1254
- });
1255
- },
1256
- { pattern: "**" }
1257
- );
135
+ ### Install
1258
136
 
1259
- // Later: Analyze error patterns
1260
- console.log("Error Statistics:", errorStats);
1261
- // {
1262
- // function: 5,
1263
- // before: 2,
1264
- // after: 1,
1265
- // always: 0,
1266
- // byHook: {
1267
- // "validate-input": 2,
1268
- // "format-output": 1
1269
- // }
1270
- // }
137
+ ```bash
138
+ npm install @cldmv/slothlet
1271
139
  ```
1272
140
 
1273
- **Important Notes:**
1274
-
1275
- - Errors from `before` and `after` hooks are re-thrown after error hooks execute
1276
- - Errors from `always` hooks are caught and logged but do NOT crash execution
1277
- - Error hooks themselves do not receive errors from other error hooks (no recursion)
1278
- - The `_hookSourceReported` flag prevents double-reporting of errors
141
+ ---
1279
142
 
1280
- #### Cross-Mode Compatibility
143
+ ## 🚀 Quick Start
1281
144
 
1282
- Hooks work identically across all configurations:
145
+ ### ESM (ES Modules)
1283
146
 
1284
147
  ```javascript
1285
- // Eager + AsyncLocalStorage
1286
- const api1 = await slothlet({ dir: "./api", lazy: false, runtime: "async", hooks: true });
1287
-
1288
- // Eager + Live Bindings
1289
- const api2 = await slothlet({ dir: "./api", lazy: false, runtime: "live", hooks: true });
1290
-
1291
- // Lazy + AsyncLocalStorage
1292
- const api3 = await slothlet({ dir: "./api", lazy: true, runtime: "async", hooks: true });
1293
-
1294
- // Lazy + Live Bindings
1295
- const api4 = await slothlet({ dir: "./api", lazy: true, runtime: "live", hooks: true });
1296
-
1297
- // Same hook code works with all configurations
1298
- [api1, api2, api3, api4].forEach((api) => {
1299
- api.hooks.on(
1300
- "universal",
1301
- "before",
1302
- ({ args }) => {
1303
- return [args[0] * 10, args[1] * 10];
1304
- },
1305
- { pattern: "math.add" }
1306
- );
1307
- });
1308
- ```
1309
-
1310
- **Key Benefits:**
1311
-
1312
- - ✅ **Universal**: Works across all 4 mode/runtime combinations
1313
- - ✅ **Flexible**: Pattern matching with wildcards and priorities
1314
- - ✅ **Powerful**: Modify args, transform results, observe execution
1315
- - ✅ **Composable**: Chain multiple hooks with priority control
1316
- - ✅ **Dynamic**: Enable/disable at runtime globally or by pattern
1317
- - ✅ **Observable**: Separate hook types for different responsibilities
1318
-
1319
- ### API Mode Configuration
1320
-
1321
- The `api_mode` option controls how slothlet handles root-level default function exports:
1322
-
1323
- #### Auto-Detection (Recommended)
148
+ import slothlet from "@cldmv/slothlet";
1324
149
 
1325
- ```javascript
150
+ // Direct usage - eager mode by default
1326
151
  const api = await slothlet({
1327
- api_mode: "auto" // Default - automatically detects structure
152
+ dir: "./api",
153
+ context: { user: "alice" }
1328
154
  });
1329
155
 
1330
- // If you have a root-level function export:
1331
- // root-function.mjs: export default function(name) { return `Hello, ${name}!` }
1332
- // Result: api("World") works AND api.otherModule.method() works
156
+ // Eager mode: Functions behave as originally defined
157
+ const result = api.math.add(2, 3); // Sync function - no await needed
158
+ const asyncResult = await api.async.processData({ data: "async" });
1333
159
 
1334
- // If you only have object exports:
1335
- // Result: api.math.add() works, api("World") doesn't exist
160
+ // Access both ESM and CJS modules seamlessly
161
+ const esmResult = api.mathEsm.multiply(4, 5);
162
+ const cjsResult = api.mathCjs.divide(10, 2);
1336
163
  ```
1337
164
 
1338
- #### Explicit Function Mode
165
+ ### CommonJS (CJS)
1339
166
 
1340
167
  ```javascript
168
+ const slothlet = require("@cldmv/slothlet");
169
+
170
+ // Same usage pattern works with CommonJS
1341
171
  const api = await slothlet({
1342
- api_mode: "function" // Force callable interface
172
+ dir: "./api",
173
+ context: { env: "production" }
1343
174
  });
1344
175
 
1345
- // Always creates callable API even without root default export
1346
- // Useful when you know you have root functions
1347
- const result = api("World"); // Calls root default function
1348
- const math = api.math.add(2, 3); // Also access other modules
176
+ const result = api.math.multiply(4, 5);
177
+ const mixedResult = await api.interop.processData({ data: "test" });
1349
178
  ```
1350
179
 
1351
- #### Explicit Object Mode
180
+ ### Lazy Loading Mode
1352
181
 
1353
182
  ```javascript
183
+ import slothlet from "@cldmv/slothlet";
184
+
185
+ // Lazy mode with copy-left materialization
1354
186
  const api = await slothlet({
1355
- api_mode: "object" // Force object-only interface
187
+ mode: "lazy", // Preferred syntax
188
+ dir: "./api",
189
+ apiDepth: 3
1356
190
  });
1357
191
 
1358
- // Always creates object interface even with root default export
1359
- // api("World") won't work, but api.rootFunction("World") will
1360
- const result = api.rootFunction("World"); // Access via property
1361
- const math = api.math.add(2, 3); // Normal module access
1362
- ```
1363
-
1364
- ---
1365
-
1366
- ## 🏗 Module Structure & Examples
1367
-
1368
- Slothlet supports sophisticated module organization patterns with seamless ESM/CJS interoperability:
1369
-
1370
- ### Root-Level Modules
1371
-
1372
- ```text
1373
- root-math.mjs → api.rootMath (dash-to-camelCase)
1374
- rootstring.mjs → api.rootstring
1375
- config.mjs → api.config
1376
- ```
1377
-
1378
- ### Filename-Folder Matching Modules
1379
-
1380
- ```text
1381
- math/math.mjs → api.math (filename matches folder)
1382
- string/string.mjs → api.string (filename matches folder)
1383
- util/util.cjs → api.util (CJS support with filename matching)
1384
- ```
1385
-
1386
- ### Multi-File Modules
1387
-
1388
- ```text
1389
- multi/
1390
- ├── alpha.mjs → api.multi.alpha
1391
- ├── beta.mjs → api.multi.beta
1392
- └── gamma.cjs → api.multi.gamma (mixed ESM/CJS)
1393
- ```
1394
-
1395
- ### Function-Based Modules
1396
-
1397
- ```text
1398
- funcmod/funcmod.mjs → api.funcmod() (callable function)
1399
- multi_func/
1400
- ├── alpha.mjs → api.multi_func.alpha()
1401
- └── beta.cjs → api.multi_func.beta() (CJS callable)
1402
- ```
1403
-
1404
- ### Mixed ESM/CJS Modules
1405
-
1406
- ```text
1407
- interop/
1408
- ├── esm-module.mjs → api.interop.esmModule
1409
- ├── cjs-module.cjs → api.interop.cjsModule
1410
- └── mixed.mjs → api.interop.mixed (calls both ESM and CJS)
1411
- ```
1412
-
1413
- ### Hybrid Export Patterns
1414
-
1415
- ```text
1416
- exportDefault/exportDefault.mjs → api.exportDefault() (callable with methods)
1417
- objectDefaultMethod/ → api.objectDefaultMethod() (object with default)
1418
- ```
1419
-
1420
- ### Nested Structure
192
+ // First access: materialization overhead (~1.45ms average)
193
+ const result1 = await api.math.add(2, 3);
1421
194
 
1422
- ```text
1423
- nested/
1424
- └── date/
1425
- ├── date.mjs → api.nested.date
1426
- └── util.cjs → api.nested.dateUtil
1427
- advanced/
1428
- ├── selfObject/ → api.advanced.selfObject
1429
- └── nest*/ → Various nesting examples
195
+ // Subsequent access: materialized function (near-eager performance)
196
+ const result2 = await api.math.add(5, 7);
1430
197
  ```
1431
198
 
1432
- ### Utility Modules
1433
-
1434
- ```text
1435
- util/
1436
- ├── controller.mjs → api.util.controller
1437
- ├── extract.cjs → api.util.extract (CJS utility)
1438
- └── url/
1439
- ├── parser.mjs → api.util.url.parser
1440
- └── builder.cjs → api.util.url.builder (mixed)
1441
- ```
199
+ ### Hook System Example
1442
200
 
1443
- ### Smart Function Naming Examples
201
+ ```javascript
202
+ import slothlet from "@cldmv/slothlet";
1444
203
 
1445
- ```text
1446
- task/auto-ip.mjs (exports autoIP) → api.task.autoIP (preserves function name)
1447
- util/parseJSON.mjs → api.util.parseJSON (preserves JSON casing)
1448
- api/getHTTPStatus.mjs → api.api.getHTTPStatus (preserves HTTP casing)
1449
- ```
204
+ const api = await slothlet({
205
+ dir: "./api",
206
+ hooks: true // Enable hooks
207
+ });
1450
208
 
1451
- ## 🏗️ API Flattening Rules
209
+ // Before hook: Modify arguments
210
+ api.hooks.on(
211
+ "validate",
212
+ "before",
213
+ ({ path, args }) => {
214
+ console.log(`Calling ${path} with args:`, args);
215
+ return [args[0] * 2, args[1] * 2];
216
+ },
217
+ { pattern: "math.add", priority: 100 }
218
+ );
1452
219
 
1453
- Slothlet uses intelligent flattening rules to create clean, intuitive API structures. Understanding these rules helps you organize your modules for the best developer experience:
220
+ // After hook: Transform result
221
+ api.hooks.on(
222
+ "format",
223
+ "after",
224
+ ({ path, result }) => {
225
+ console.log(`${path} returned:`, result);
226
+ return result * 10;
227
+ },
228
+ { pattern: "math.*", priority: 100 }
229
+ );
1454
230
 
1455
- ### 1. **Filename-Folder Matching** (Single Named Export)
231
+ // Always hook: Observe final result
232
+ api.hooks.on(
233
+ "observe",
234
+ "always",
235
+ ({ path, result, hasError }) => {
236
+ console.log(hasError ? `${path} failed` : `${path} succeeded`);
237
+ },
238
+ { pattern: "**" }
239
+ );
1456
240
 
1457
- **When:** A file exports a single named export that matches the sanitized filename
1458
- **Why:** Avoids redundant nesting (`api.math.math.add()` → `api.math.add()`)
1459
- **Reasoning:** When file purpose matches folder purpose, eliminate the duplicate layer
241
+ // Error hook: Monitor errors with source tracking
242
+ api.hooks.on(
243
+ "error-logger",
244
+ "error",
245
+ ({ path, error, source }) => {
246
+ console.error(`Error in ${path}:`, error.message);
247
+ console.error(`Source: ${source.type}`); // 'before', 'after', 'function', 'always'
248
+ },
249
+ { pattern: "**" }
250
+ );
1460
251
 
1461
- ```text
1462
- math/math.mjs (exports { math: {...} }) → api.math (flattened)
1463
- string/string.mjs (exports { string: {...} }) → api.string (flattened)
1464
- util/util.mjs (exports { util: {...} }) → api.util (flattened)
252
+ // Call function - hooks execute automatically
253
+ const result = await api.math.add(2, 3);
1465
254
  ```
1466
255
 
1467
- ### 2. **No Default Export + Only Named Exports** ⭐ NEW
1468
-
1469
- **When:** A file has **no default export** and **only named exports**
1470
- **Why:** The file acts as a pure function collection, not a module with a main export
1471
- **Reasoning:** If there's no "main thing" (default export), treat all functions as equals at the root level
256
+ ### Dynamic API Extension with addApi()
1472
257
 
1473
- ```text
1474
- connection.mjs (exports { connect, disconnect, isConnected })
1475
- → api.connect(), api.disconnect(), api.isConnected()
1476
- Because: No default export = no main "connection" object needed
258
+ Load additional modules at runtime and extend your API dynamically:
1477
259
 
1478
- app.mjs (exports { getAllApps, getCurrentApp, setApp })
1479
- api.getAllApps(), api.getCurrentApp(), api.setApp()
1480
- Because: No default export = these are standalone utility functions
260
+ ```javascript
261
+ import slothlet from "@cldmv/slothlet";
1481
262
 
1482
- state.mjs (exports { cloneState, emitLog, reset, update })
1483
- → api.cloneState(), api.emitLog(), api.reset(), api.update()
1484
- Because: No default export = treat as individual state utilities
1485
- ```
263
+ const api = await slothlet({ dir: "./api" });
1486
264
 
1487
- ### 3. **Has Default Export** (Namespace Preservation)
265
+ // Add plugins at runtime
266
+ await api.addApi("plugins", "./plugins-folder");
267
+ api.plugins.myPlugin();
1488
268
 
1489
- **When:** A file has a default export (with or without named exports)
1490
- **Why:** The default export indicates there's a "main thing" that should be the namespace
1491
- **Reasoning:** Default export signals intentional module structure that should be preserved
269
+ // Create nested API structures
270
+ await api.addApi("runtime.plugins", "./more-plugins");
271
+ api.runtime.plugins.loader();
1492
272
 
1493
- ```text
1494
- config.mjs (exports default + named exports) → api.config.*
1495
- Because: Default export indicates a main config object with methods
273
+ // Add with metadata for security/authorization
274
+ await api.addApi("plugins.trusted", "./trusted-plugins", {
275
+ trusted: true,
276
+ permissions: ["read", "write", "admin"],
277
+ version: "1.0.0"
278
+ });
1496
279
 
1497
- input.mjs (exports default + named exports) → api.input.*
1498
- Because: Default export indicates a main input handler with utilities
280
+ await api.addApi("plugins.external", "./third-party", {
281
+ trusted: false,
282
+ permissions: ["read"]
283
+ });
1499
284
 
1500
- volume.mjs (exports default + named exports) → api.volume.*
1501
- Because: Default export indicates a main volume controller with methods
285
+ // Access metadata on functions
286
+ const meta = api.plugins.trusted.someFunc.__metadata;
287
+ console.log(meta.trusted); // true
288
+ console.log(meta.permissions); // ["read", "write", "admin"]
1502
289
  ```
1503
290
 
1504
- ### 4. **Root-Level Special Cases**
291
+ **Security & Authorization with metadataAPI:**
1505
292
 
1506
- **When:** Files are at the root directory level (not in subfolders)
1507
- **Why:** Prevents accidental API pollution and maintains clear root structure
1508
- **Reasoning:** Root files are explicitly placed there and should maintain their intended naming
293
+ ```javascript
294
+ // Inside your modules, use metadataAPI for runtime introspection
295
+ import { metadataAPI } from "@cldmv/slothlet/runtime";
1509
296
 
1510
- ```text
1511
- root-math.mjs → api.rootMath (namespace preserved)
1512
- Because: Explicitly named "root-math" = keep as intended namespace
297
+ export async function sensitiveOperation() {
298
+ // Check caller's metadata
299
+ const caller = await metadataAPI.caller();
1513
300
 
1514
- rootstring.mjs → api.rootstring (namespace preserved)
1515
- Because: Root-level placement = developer wants this specific API structure
301
+ if (!caller?.trusted) {
302
+ throw new Error("Unauthorized: Caller is not trusted");
303
+ }
1516
304
 
1517
- config.mjs → api.config (namespace preserved)
1518
- Because: Root config file = keep as clear config namespace, don't flatten
1519
- ```
305
+ if (!caller.permissions.includes("admin")) {
306
+ throw new Error("Unauthorized: Admin permission required");
307
+ }
1520
308
 
1521
- ### 5. **Self-Referential Prevention**
309
+ // Proceed with secure operation
310
+ return "Success";
311
+ }
1522
312
 
1523
- **When:** A file would create circular/redundant nesting (`api.config.config`)
1524
- **Why:** Prevents infinite nesting and maintains clean API structure
1525
- **Reasoning:** When file/folder names match, assume they represent the same logical concept
313
+ // Get metadata by path
314
+ const meta = await metadataAPI.get("plugins.trusted.someFunc");
1526
315
 
1527
- ```text
1528
- config/config.mjs api.config (prevented: api.config.config.config...)
1529
- Because: config.mjs in config/ folder = same concept, use folder name only
316
+ // Get current function's metadata
317
+ const self = await metadataAPI.self();
318
+ console.log("My version:", self.version);
1530
319
  ```
1531
320
 
1532
- ### 🎯 Flattening Decision Tree
1533
-
1534
- ```mermaid
1535
- flowchart TD
1536
- FILE[Module File] --> ROOT{Root Level?}
1537
-
1538
- ROOT -->|Yes| PRESERVE[Preserve Namespace<br/>api.rootMath, api.config]
1539
-
1540
- ROOT -->|No| SELFREFER{Self-Referential?}
1541
- SELFREFER -->|Yes| NAMESPACE[Use Namespace<br/>api.config]
1542
-
1543
- SELFREFER -->|No| HASDEFAULT{Has Default Export?}
1544
- HASDEFAULT -->|Yes| NAMESPACE
1545
-
1546
- HASDEFAULT -->|No| NAMEDONLY{Only Named Exports?}
1547
- NAMEDONLY -->|Yes| FLATTEN["Flatten All Named Exports<br/>api.connect, api.disconnect"]
321
+ 🔒 **For complete metadata system documentation, see [docs/METADATA.md](https://github.com/CLDMV/slothlet/blob/master/docs/METADATA.md)**
1548
322
 
1549
- NAMEDONLY -->|No| SINGLENAMED{Single Named Export<br/>Matching Filename?}
1550
- SINGLENAMED -->|Yes| FLATTENSINGLE[Flatten Single Export<br/>api.math]
1551
- SINGLENAMED -->|No| NAMESPACE
1552
-
1553
- style FLATTEN fill:#e1f5fe,stroke:#0277bd,stroke-width:2px,color:#000
1554
- style FLATTENSINGLE fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px,color:#000
1555
- style NAMESPACE fill:#fff3e0,stroke:#e65100,stroke-width:2px,color:#000
1556
- style PRESERVE fill:#fce4ec,stroke:#c2185b,stroke-width:2px,color:#000
1557
- ```
323
+ ---
1558
324
 
1559
- ### 🚀 Benefits of Smart Flattening
325
+ ## 📚 Configuration Options
326
+
327
+ | Option | Type | Default | Description |
328
+ | ------------------- | --------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
329
+ | `dir` | `string` | `"api"` | Directory to load API modules from (absolute or relative path) |
330
+ | `mode` | `string` | `"eager"` | **New** loading mode - `"lazy"` for on-demand loading, `"eager"` for immediate loading |
331
+ | `lazy` | `boolean` | `false` | **Legacy** loading strategy (use `mode` instead) |
332
+ | `engine` | `string` | `"singleton"` | Execution environment: `"singleton"`, `"vm"`, `"worker"`, or `"fork"` (experimental modes) |
333
+ | `runtime` | `string` | `"async"` | Runtime binding system: `"async"` for AsyncLocalStorage (requires Node.js v16.4.0+), `"live"` for live-bindings (works on Node.js v12.20.0+) |
334
+ | `apiDepth` | `number` | `Infinity` | Directory traversal depth - `0` for root only, `Infinity` for all levels |
335
+ | `debug` | `boolean` | `false` | Enable verbose logging (also via `--slothletdebug` flag or `SLOTHLET_DEBUG=true` env var) |
336
+ | `api_mode` | `string` | `"auto"` | API structure behavior: `"auto"` (detect), `"function"` (force callable), `"object"` (force object) |
337
+ | `allowApiOverwrite` | `boolean` | `true` | Allow `addApi()` to overwrite existing endpoints (`false` = prevent overwrites with warning) |
338
+ | `context` | `object` | `{}` | Context data injected into live-binding (available via `import { context } from "@cldmv/slothlet/runtime"`) |
339
+ | `reference` | `object` | `{}` | Reference object merged into API root level |
340
+ | `sanitize` | `object` | `{}` | Advanced filename-to-API transformation control with `lowerFirst`, `preserveAllUpper`, `preserveAllLower`, and `rules` (supports exact matches, glob patterns `*json*`, and boundary patterns `**url**`) |
341
+ | `hooks` | `mixed` | `false` | Enable hook system: `true` (enable all), `"pattern"` (enable with pattern), or object with `enabled`, `pattern`, `suppressErrors` options |
342
+
343
+ **For complete API documentation with detailed parameter descriptions and examples, see [docs/generated/API.md](https://github.com/CLDMV/slothlet/blob/master/docs/generated/API.md)**
1560
344
 
1561
- - **Cleaner APIs**: `api.connect()` instead of `api.connection.connect()`
1562
- _Why it matters:_ Reduces typing, improves readability, and matches how you'd naturally call connection functions
1563
- - **Intuitive Structure**: File organization matches API usage patterns
1564
- _Why it matters:_ Files with only utility functions flatten (no main export = no namespace needed), while files with main exports preserve their intended structure
1565
- - **Flexible Organization**: Mix flattened and nested patterns as needed
1566
- _Why it matters:_ You can organize files by purpose (`connection.mjs` for utilities, `config.mjs` for main objects) and slothlet automatically creates the right API structure
1567
- - **Developer Intent Respected**: Export structure signals your architectural intentions
1568
- _Why it matters:_ Default exports = "this is a main thing with methods", named exports only = "these are utility functions"
1569
- - **Backward Compatibility**: Existing APIs continue to work as expected
1570
- _Why it matters:_ The rules are additive - existing filename-matching and default export patterns still work exactly the same
345
+ ---
1571
346
 
1572
347
  ## 🔀 How Slothlet Works: Loading Modes Explained
1573
348
 
@@ -1695,59 +470,105 @@ flowchart TD
1695
470
 
1696
471
  ### Eager Mode (Default - Production Ready)
1697
472
 
473
+ **Best for:** Production environments, maximum runtime performance, predictable behavior
474
+
1698
475
  ```javascript
1699
476
  const api = await slothlet({ dir: "./api" }); // lazy: false by default
1700
477
 
1701
- // Functions behave as originally defined - no await needed for sync functions
1702
- const result = api.math.add(2, 3); // Sync function - direct call
1703
- const greeting = api("World"); // Instant if callable
1704
-
1705
- // Async functions still need await (as originally defined)
1706
- const asyncResult = await api.async.processData({ data: "test" }); // Original async function
1707
-
1708
- // ESM+CJS works seamlessly with native behavior
1709
- const mixed = api.interop.process({ data: "test" }); // Sync or async as defined
478
+ // Functions behave as originally defined
479
+ const result = api.math.add(2, 3); // Sync - no await needed
480
+ const asyncResult = await api.async.processData({ data: "test" }); // Async needs await
1710
481
  ```
1711
482
 
1712
483
  **Benefits:**
1713
484
 
1714
- - ✅ Fastest function calls (0.36μs average)
1715
- - ✅ Predictable performance
1716
- - ✅ No materialization delays
1717
- - ✅ Functions behave exactly as originally defined (sync stays sync, async stays async)
1718
- - ✅ Optimal for production environments
485
+ - ✅ Fastest function calls (0.90μs average)
486
+ - ✅ Predictable performance (no materialization delays)
487
+ - ✅ Functions behave exactly as originally defined
1719
488
 
1720
489
  ### Lazy Mode with Copy-Left Materialization (Production Ready)
1721
490
 
1722
- ```javascript
1723
- const api = await slothlet({ lazy: true, dir: "./api" });
491
+ **Best for:** Startup-sensitive applications, memory efficiency, loading only what you use
1724
492
 
1725
- // ALL function calls must be awaited in lazy mode (due to materialization)
1726
- const result1 = await api.math.add(2, 3); // First access: ~310μs (materialization)
1727
- const result2 = await api.math.add(5, 7); // Subsequent: ~0.5μs (materialized)
493
+ ```javascript
494
+ const api = await slothlet({ mode: "lazy", dir: "./api" });
1728
495
 
1729
- // Even originally sync functions need await in lazy mode
1730
- const greeting = await api("World"); // Callable interface also needs await
1731
- const syncResult = await api.string.format("Hello"); // Originally sync, but needs await
496
+ // ALL calls must be awaited (materialization process)
497
+ const result1 = await api.math.add(2, 3); // First: ~371μs (materialization)
498
+ const result2 = await api.math.add(5, 7); // Subsequent: 0.99μs (materialized)
1732
499
  ```
1733
500
 
1734
501
  **Benefits:**
1735
502
 
1736
- - ✅ 4.3x faster startup (564.17μs vs 2.45ms)
503
+ - ✅ 2.9x faster startup (4.89ms vs 14.29ms)
504
+ - ✅ Near-equal function call performance (0.99μs vs 0.90μs eager)
1737
505
  - ✅ Memory efficient (loads only what you use)
1738
506
  - ✅ Copy-left optimization (once loaded, stays loaded)
1739
- - ✅ Optimal for startup-sensitive applications
1740
- - ⚠️ All function calls require await (regardless of original sync/async nature)
1741
-
1742
- **Performance Summary:**
1743
507
 
1744
508
  > [!TIP]
1745
- > **Choose your loading strategy based on your needs:**
509
+ > **Choose your strategy:**
1746
510
  >
1747
- > - **Startup**: Lazy wins (4.3x faster - 564.17μs vs 2.45ms)
1748
- > - **Function calls**: Eager wins (1.1x faster - 0.65μs vs 0.72μs)
1749
- > - **Memory**: Lazy wins (loads only what you use)
1750
- > - **Predictability**: Eager wins (no materialization delays)
511
+ > - **Startup-sensitive?** Lazy mode (2.9x faster startup)
512
+ > - **Call-intensive?** Eager mode (1.1x faster calls)
513
+ > - **Need predictability?** Eager mode (no materialization delays)
514
+ > - **Large API, use subset?** → Lazy mode (memory efficient)
515
+
516
+ ---
517
+
518
+ ## 📊 Performance Analysis
519
+
520
+ For comprehensive performance benchmarks, analysis, and recommendations:
521
+
522
+ **📈 [See docs/PERFORMANCE.md](https://github.com/CLDMV/slothlet/blob/master/docs/PERFORMANCE.md)**
523
+
524
+ Key highlights:
525
+
526
+ - Detailed startup vs runtime performance comparison
527
+ - Memory usage analysis by loading mode
528
+ - Materialization cost breakdown by module type
529
+ - Real-world performance recommendations
530
+
531
+ [![CodeFactor]][codefactor_url] [![npms.io score]][npms_url]
532
+
533
+ [![npm unpacked size]][npm_size_url] [![Repo size]][repo_size_url]
534
+
535
+ ---
536
+
537
+ ## 📚 Documentation
538
+
539
+ ### Core Documentation
540
+
541
+ - **[API Documentation](https://github.com/CLDMV/slothlet/blob/master/docs/generated/API.md)** - Complete API reference with examples and detailed parameter descriptions
542
+ - **[Performance Analysis](https://github.com/CLDMV/slothlet/blob/master/docs/PERFORMANCE.md)** - Detailed benchmarks and recommendations
543
+ - **[Contributing Guide](CONTRIBUTING.md)** - How to contribute to the project
544
+ - **[Security Policy](SECURITY.md)** - Security guidelines and reporting
545
+ - **[Test Documentation](api_tests)** - Comprehensive test module examples
546
+
547
+ ### Technical Guides
548
+
549
+ - **[Hook System](https://github.com/CLDMV/slothlet/blob/master/docs/HOOKS.md)** - Complete hook system documentation with 4 hook types, pattern matching, and examples
550
+ - **[Context Propagation](https://github.com/CLDMV/slothlet/blob/master/docs/CONTEXT-PROPAGATION.md)** - EventEmitter and class instance context preservation
551
+ - **[Metadata System](https://github.com/CLDMV/slothlet/blob/master/docs/METADATA.md)** - Function metadata tagging and runtime introspection for security, authorization, and auditing
552
+ - **[Module Structure](https://github.com/CLDMV/slothlet/blob/master/docs/MODULE-STRUCTURE.md)** - Comprehensive module organization patterns and examples
553
+ - **[API Flattening](https://github.com/CLDMV/slothlet/blob/master/docs/API-FLATTENING.md)** - The 5 flattening rules with decision tree and benefits
554
+
555
+ ### API Rules & Transformation
556
+
557
+ - **[API Rules](https://github.com/CLDMV/slothlet/blob/master/docs/API-RULES.md)** - Systematically verified API transformation rules with real examples and test cases
558
+ - **[API Rules Conditions](https://github.com/CLDMV/slothlet/blob/master/docs/API-RULES-CONDITIONS.md)** - Complete technical reference of all 26 conditional statements that control API generation
559
+
560
+ ### Changelog
561
+
562
+ - **[v2.9](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.9.md)** - Per-Request Context Isolation & API Builder Modularization (December 30, 2025)
563
+ - **[v2.8](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.8.md)** - NPM security fixes and package workflow updates (December 26, 2025)
564
+ - **[v2.7](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.7.md)** - Hook System with 4 interceptor types (December 20, 2025)
565
+ - **[v2.6](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.6.md)** - Mode/Engine options and deep nested path fixes (November 10, 2025)
566
+ - **[v2.5](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.5.md)** - Architectural consolidation and API consistency (October 20, 2025)
567
+ - **[v2.4](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.4.md)** - Multi-default export handling with file-based naming (October 18, 2025)
568
+ - **[v2.3](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.3.md)** - EventEmitter & Class Context Propagation (October 16, 2025)
569
+ - **[v2.2](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.2.md)** - Case preservation options (preserveAllUpper/preserveAllLower) (October 14, 2025)
570
+ - **[v2.1](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.1.md)** - Advanced sanitization with boundary patterns (October 12, 2025)
571
+ - **[v2.0](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v2.0.md)** - Complete Architectural Rewrite (September 9, 2025)
1751
572
 
1752
573
  ---
1753
574
 
@@ -1767,27 +588,6 @@ try {
1767
588
  }
1768
589
  ```
1769
590
 
1770
- **Planned Enhanced Error Features (v3.0.0):**
1771
-
1772
- > [!TIP]
1773
- > **Coming Soon**: Enhanced error handling with descriptive messages and module suggestions:
1774
- >
1775
- > ```javascript
1776
- > try {
1777
- > await api.nonexistent.method();
1778
- > } catch (error) {
1779
- > console.error(error.message);
1780
- > // Planned: "Module 'nonexistent' not found in './api'. Available modules: math, string, util. Did you mean 'util'?"
1781
- > }
1782
- > ```
1783
- >
1784
- > **Planned Features:**
1785
- >
1786
- > - 🔍 **Module discovery**: Show available modules and suggest alternatives
1787
- > - 📍 **Context information**: Include directory path and configuration details
1788
- > - 🎯 **Actionable suggestions**: Provide specific guidance for resolution
1789
- > - 🚀 **Development mode**: Additional debugging information when debug flag is enabled
1790
-
1791
591
  ---
1792
592
 
1793
593
  ## 🔧 Production vs Development Modes
@@ -1815,8 +615,6 @@ try {
1815
615
  > - **Fork Mode**: Process isolation (in development)
1816
616
  > - **Child Mode**: Child process execution (in development)
1817
617
  > - **VM Mode**: Virtual machine context (in development)
1818
- >
1819
- > The experimental modes are located in `src/lib/engine/` and should not be used in production environments.
1820
618
 
1821
619
  ---
1822
620
 
@@ -1825,47 +623,26 @@ try {
1825
623
  ### Key Changes
1826
624
 
1827
625
  1. **Import paths**: `@cldmv/slothlet` instead of specific file paths
1828
- 2. **Configuration**: New options (`api_mode`, `context`, `reference`)
626
+ 2. **Configuration**: New options (`api_mode`, `context`, `reference`, `hooks`)
1829
627
  3. **Function names**: Enhanced preservation of original capitalization
1830
628
  4. **Module structure**: Mixed ESM/CJS support
1831
629
  5. **Live bindings**: Dual runtime system with AsyncLocalStorage and live-bindings options
630
+ 6. **Automatic instances**: No more query strings or `withInstanceId()` methods
1832
631
 
1833
632
  ### Migration Steps
1834
633
 
1835
634
  ```javascript
1836
- // v1.3.x - API creation (same pattern as v2.x)
1837
- import slothlet from "@cldmv/slothlet";
1838
- const api = await slothlet({
1839
- dir: "./api",
1840
- lazy: true
1841
- });
1842
-
1843
635
  // v1.3.x - Multiple instances required query strings or withInstanceId()
1844
636
  const api1 = await slothlet({ dir: "./api?instanceId=alice" });
1845
637
  const api2 = slothlet.withInstanceId("bob");
1846
638
  const bobApi = await api2({ dir: "./api" });
1847
639
 
1848
- // v2.0 - Same API creation, but automatic instance isolation
1849
- import slothlet from "@cldmv/slothlet";
1850
- const api = await slothlet({
1851
- dir: "./api",
1852
- lazy: true,
1853
- context: { user: "alice" }, // New: context injection
1854
- api_mode: "auto" // New: API mode control
1855
- });
1856
-
1857
- // v2.0 - Multiple instances automatically isolated (no query strings needed)
640
+ // v2.x - Automatic instance isolation (no query strings needed)
1858
641
  const api1 = await slothlet({ dir: "./api", context: { tenant: "alice" } });
1859
642
  const api2 = await slothlet({ dir: "./api", context: { tenant: "bob" } });
643
+ // Instances completely isolated with their own contexts
1860
644
  ```
1861
645
 
1862
- ### Performance Improvements
1863
-
1864
- - **Architectural optimizations** with copy-left materialization and AsyncLocalStorage integration
1865
- - **Zero dependencies** - pure Node.js implementation reduces overhead
1866
- - **Enhanced materialization** with copy-left optimization in lazy mode
1867
- - **Modular design** improves maintainability and potential optimization opportunities
1868
-
1869
646
  ---
1870
647
 
1871
648
  ## 🤝 Contributing
@@ -1878,46 +655,12 @@ We welcome contributions! The experimental modes in particular need development
1878
655
  4. **Provide feedback** on API design and performance
1879
656
  5. **Documentation improvements** are always appreciated
1880
657
 
1881
- See [CONTRIBUTING.md](https://github.com/CLDMV/slothlet/blob/HEAD/CONTRIBUTING.md) for detailed contribution guidelines.
658
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed contribution guidelines.
1882
659
 
1883
660
  [![Contributors]][contributors_url] [![Sponsor shinrai]][sponsor_url]
1884
661
 
1885
662
  ---
1886
663
 
1887
- ## 📊 Performance Analysis
1888
-
1889
- For comprehensive performance benchmarks, analysis, and recommendations:
1890
-
1891
- **📈 [See PERFORMANCE.md](https://github.com/CLDMV/slothlet/blob/HEAD/PERFORMANCE.md)**
1892
-
1893
- Key highlights:
1894
-
1895
- - Detailed startup vs runtime performance comparison
1896
- - Memory usage analysis by loading mode
1897
- - Materialization cost breakdown by module type
1898
- - Real-world performance recommendations
1899
-
1900
- [![CodeFactor]][codefactor_url] [![npms.io score]][npms_url]
1901
-
1902
- [![npm unpacked size]][npm_size_url] [![Repo size]][repo_size_url]
1903
-
1904
- ---
1905
-
1906
- ## 📚 Documentation
1907
-
1908
- - **[API Documentation](https://github.com/CLDMV/slothlet/blob/HEAD/docs/API.md)** - Complete API reference with examples
1909
- - **[Performance Analysis](https://github.com/CLDMV/slothlet/blob/HEAD/PERFORMANCE.md)** - Detailed benchmarks and recommendations
1910
- - **[Contributing Guide](https://github.com/CLDMV/slothlet/blob/HEAD/CONTRIBUTING.md)** - How to contribute to the project
1911
- - **[Security Policy](https://github.com/CLDMV/slothlet/blob/HEAD/SECURITY.md)** - Security guidelines and reporting
1912
- - **[Test Documentation](https://github.com/CLDMV/slothlet/blob/HEAD/api_tests)** - Comprehensive test module examples
1913
-
1914
- ### 🔧 Technical Documentation
1915
-
1916
- - **[API Rules](https://github.com/CLDMV/slothlet/blob/HEAD/API-RULES.md)** - Systematically verified API transformation rules with real examples and test cases
1917
- - **[API Rules Conditions](https://github.com/CLDMV/slothlet/blob/HEAD/API-RULES-CONDITIONS.md)** - Complete technical reference of all 26 conditional statements that control API generation
1918
-
1919
- ---
1920
-
1921
664
  ## 🔗 Links
1922
665
 
1923
666
  - **npm**: [@cldmv/slothlet](https://www.npmjs.com/package/@cldmv/slothlet)