@cldmv/slothlet 1.0.1 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +862 -73
  2. package/dist/lib/engine/README.md +21 -0
  3. package/dist/lib/engine/slothlet_child.mjs +58 -0
  4. package/dist/lib/engine/slothlet_engine.mjs +371 -0
  5. package/dist/lib/engine/slothlet_esm.mjs +229 -0
  6. package/dist/lib/engine/slothlet_helpers.mjs +454 -0
  7. package/dist/lib/engine/slothlet_worker.mjs +148 -0
  8. package/dist/lib/helpers/resolve-from-caller.mjs +141 -0
  9. package/dist/lib/helpers/sanitize.mjs +78 -0
  10. package/dist/lib/modes/slothlet_eager.mjs +80 -0
  11. package/dist/lib/modes/slothlet_lazy.mjs +342 -0
  12. package/dist/lib/runtime/runtime.mjs +249 -0
  13. package/dist/slothlet.mjs +1092 -0
  14. package/index.cjs +81 -0
  15. package/index.mjs +76 -0
  16. package/package.json +136 -14
  17. package/types/dist/lib/engine/slothlet_child.d.mts +2 -0
  18. package/types/dist/lib/engine/slothlet_child.d.mts.map +1 -0
  19. package/types/dist/lib/engine/slothlet_engine.d.mts +31 -0
  20. package/types/dist/lib/engine/slothlet_engine.d.mts.map +1 -0
  21. package/types/dist/lib/engine/slothlet_esm.d.mts +19 -0
  22. package/types/dist/lib/engine/slothlet_esm.d.mts.map +1 -0
  23. package/types/dist/lib/engine/slothlet_helpers.d.mts +24 -0
  24. package/types/dist/lib/engine/slothlet_helpers.d.mts.map +1 -0
  25. package/types/dist/lib/engine/slothlet_worker.d.mts +2 -0
  26. package/types/dist/lib/engine/slothlet_worker.d.mts.map +1 -0
  27. package/types/dist/lib/helpers/resolve-from-caller.d.mts +149 -0
  28. package/types/dist/lib/helpers/resolve-from-caller.d.mts.map +1 -0
  29. package/types/dist/lib/helpers/sanitize.d.mts +138 -0
  30. package/types/dist/lib/helpers/sanitize.d.mts.map +1 -0
  31. package/types/dist/lib/modes/slothlet_eager.d.mts +66 -0
  32. package/types/dist/lib/modes/slothlet_eager.d.mts.map +1 -0
  33. package/types/dist/lib/modes/slothlet_lazy.d.mts +32 -0
  34. package/types/dist/lib/modes/slothlet_lazy.d.mts.map +1 -0
  35. package/types/dist/lib/runtime/runtime.d.mts +49 -0
  36. package/types/dist/lib/runtime/runtime.d.mts.map +1 -0
  37. package/types/dist/slothlet.d.mts +110 -0
  38. package/types/dist/slothlet.d.mts.map +1 -0
  39. package/types/index.d.mts +23 -0
  40. package/slothlet.mjs +0 -1218
package/README.md CHANGED
@@ -1,115 +1,904 @@
1
1
  # @cldmv/slothlet
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/@cldmv/slothlet.svg)](https://www.npmjs.com/package/@cldmv/slothlet)
4
- [![license](https://img.shields.io/github/license/CLDMV/slothlet.svg)](LICENSE)
5
- ![size](https://img.shields.io/npm/unpacked-size/@cldmv/slothlet.svg)
6
- ![npm-downloads](https://img.shields.io/npm/dm/@cldmv/slothlet.svg)
7
- ![github-downloads](https://img.shields.io/github/downloads/CLDMV/slothlet/total)
3
+ <div align="center">
4
+ <img src="images/slothlet-logo-v1-horizontal-transparent.png" alt="Slothlet Logo" width="600">
5
+ </div>
8
6
 
9
- > **⚠️ WARNING: This module is under active development!**
7
+ **@cldmv/slothlet** is a sophisticated module loading framework that revolutionizes how you work with massive APIs in Node.js. Built for developers who demand smart, efficient module loading without compromising performance or developer experience.
8
+
9
+ Choose your loading strategy based on your needs: **lazy mode** loads modules on-demand for faster startup and lower memory usage, while **eager mode** loads everything upfront for maximum runtime performance and predictable behavior.
10
+
11
+ With our **copy-left materialization** in lazy mode, you get the best of both worlds: the memory efficiency of on-demand loading with near-eager performance on repeated calls. Once a module is materialized, it stays materialized—no re-processing overhead.
12
+
13
+ The name might suggest we're taking it easy, but don't be fooled. **Slothlet delivers speed where it counts**, with smart optimizations that make your APIs fly.
14
+
15
+ > _"slothlet is anything but slow."_
16
+
17
+ [![npm version]][npm_version_url] [![npm downloads]][npm_downloads_url] <!-- [![GitHub release]][github_release_url] -->[![GitHub downloads]][github_downloads_url] [![Last commit]][last_commit_url] <!-- [![Release date]][release_date_url] -->[![npm last update]][npm_last_update_url]
18
+
19
+ > [!NOTE]
20
+ > **🚀 Production Ready Modes:**
21
+ >
22
+ > - **Eager Mode**: Fully stable and production-ready for immediate module loading
23
+ > - **Lazy Mode**: Production-ready with advanced copy-left materialization and 4.3x faster startup (1.1x slower function calls)
24
+
25
+ > [!CAUTION]
26
+ > **⚙️ Experimental Modes:**
10
27
  >
11
- > - The standard **eager mode** works well and is stable for production use.
12
- > - **Lazy mode** has been tested and works for most use cases.
13
- > - **Experimental modes** (such as worker, child process, and advanced context binding) are in development and may not be fully functional or stable.
28
+ > - **Worker, Fork, Child, VM modes**: In active development, not recommended for production use
14
29
  >
15
- > Please report issues, contribute, and use experimental features with caution.
30
+ > Please report issues and contribute feedback to help improve the experimental features.
31
+
32
+ [![Contributors]][contributors_url] [![Sponsor shinrai]][sponsor_url]
33
+
34
+ ---
35
+
36
+ ## ✨ What's New in v2.0
37
+
38
+ ### 🎯 **Complete Architectural Rewrite**
39
+
40
+ v2.0 represents a ground-up rewrite with enterprise-grade features:
41
+
42
+ - **Universal Module Support**: Load both ESM (`.mjs`) and CommonJS (`.cjs`) files seamlessly
43
+ - **AsyncLocalStorage Integration**: Advanced context isolation and live-binding system
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
47
+
48
+ ### 🏗️ **Enhanced Architecture**
49
+
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
+ ### 📊 **Performance Optimizations**
56
+
57
+ - **Startup**: Lazy mode 4.3x faster (564.17μs vs 2.45ms)
58
+ - **Function Calls**: Eager mode 1.1x faster (0.65μs vs 0.72μs) after materialization
59
+ - **Memory**: On-demand loading scales with actual usage
60
+ - **Predictability**: Consistent performance characteristics per mode
61
+
62
+ ---
63
+
64
+ ## 🚀 Key Features
65
+
66
+ ### 🎯 **Dual Loading Strategies**
67
+
68
+ - **Eager Loading**: Immediate loading for maximum performance in production environments
69
+ - **Lazy Loading**: Copy-left materialization with look-ahead proxies (4.3x faster startup, 1.1x slower calls after materialization)
70
+
71
+ > [!IMPORTANT]
72
+ > **Function Call Patterns:**
73
+ >
74
+ > - **Lazy Mode**: ALL function calls must be awaited (`await api.math.add(2, 3)`) due to materialization process
75
+ > - **Eager Mode**: Functions behave as originally defined - sync functions are sync (`api.math.add(2, 3)`), async functions are async (`await api.async.process()`)
76
+
77
+ ### ⚡ Performance Excellence
78
+
79
+ - **📊 For comprehensive performance analysis, benchmarks, and recommendations, see [PERFORMANCE.md](PERFORMANCE.md)**
80
+
81
+ ### 🔧 **Smart API Management**
16
82
 
17
- **@cldmv/slothlet** is a modern, lazy modular API loader for Node.js projects. Designed for developers who want fast, flexible, and memory-efficient access to large modular APIs, it dynamically loads API modules and submodules only when accessed. Slothlet supports both lazy and eager loading, automatic flattening of single-file modules, and descriptive error handling—all with a fun branding twist: "slothlet is anything but slow."
83
+ - **Callable Interface**: Use `slothlet(options)` for direct API creation
84
+ - **Automatic Flattening**: Single-file modules become direct API properties (`math/math.mjs` → `api.math`)
85
+ - **Intelligent Naming**: Dash-separated names convert automatically (`root-math.mjs` → `api.rootMath`)
86
+ - **Function Name Preservation**: Maintains original capitalization (`auto-ip.mjs` with `autoIP` → `api.autoIP`)
87
+ - **Hybrid Exports**: Support for callable APIs with methods, default + named exports, and mixed patterns
18
88
 
19
- ## Features
89
+ > [!TIP]
90
+ > **📁 For comprehensive examples of API flattening, naming conventions, and function preservation patterns, see the test modules in [api_tests/](api_tests/) and their documentation in [docs/api_tests/](docs/api_tests/)**
20
91
 
21
- - **Lazy loading:** API endpoints are loaded on demand using ES6 Proxy, minimizing initial load time and memory usage.
22
- - **Eager loading:** Optionally load all modules up front for maximum performance.
23
- - **Automatic flattening:** Single-file modules (e.g., `math/math.mjs`) become `api.math`.
24
- - **CamelCase mapping:** Filenames and folders with dashes are mapped to camelCase API properties (e.g., `root-math.mjs` → `api.rootMath`).
25
- - **Descriptive errors:** Throws clear errors for missing API paths or methods.
26
- - **Configurable:** Set root directory and lazy loading depth.
27
- - **ESM-first:** Clean, standards-based API.
28
- - **TypeScript-friendly:** JSDoc-annotated API for editor support.
29
- - **Lightweight:** No dependencies, minimal footprint.
92
+ ### 🔗 **Advanced Binding System**
30
93
 
31
- ## Installation
94
+ - **Live Bindings**: Dynamic context and reference binding for runtime API mutation
95
+ - **AsyncLocalStorage**: Per-instance context isolation with seamless integration
96
+ - **Copy-Left Preservation**: Materialized functions stay materialized, preserving performance gains
97
+ - **Bubble-Up Updates**: Parent API synchronization ensures consistency across the API tree
98
+ - **Mixed Module Support**: Seamlessly blend ESM and CommonJS modules in the same API
32
99
 
33
- ```sh
100
+ ### 🛠 **Developer Experience**
101
+
102
+ - **Standard Error Handling**: Clear JavaScript errors with plans for enhanced descriptive errors in v2.1.0
103
+ - **TypeScript-Friendly**: Comprehensive JSDoc annotations for excellent editor support with auto-generated declarations
104
+ - **Configurable Debug**: Detailed logging for development and troubleshooting via CLI flags or environment variables
105
+ - **Multiple Instances**: Parameter-based isolation for complex applications with instance ID management
106
+ - **Development Checks**: Built-in environment detection with silent production behavior
107
+
108
+ ### 🏗 **Architecture & Compatibility**
109
+
110
+ - **ESM-First**: Built for modern JavaScript with full ES module support
111
+ - **Universal Loading**: CommonJS and ESM files work together seamlessly
112
+ - **Zero Dependencies**: Lightweight footprint with no external dependencies
113
+ - **Cross-Platform**: Works seamlessly across all Node.js environments
114
+ - **Extensible**: Modular architecture designed for future plugin system (in development)
115
+
116
+ ---
117
+
118
+ ## 📦 Installation
119
+
120
+ ### Requirements
121
+
122
+ - **Node.js v16.4.0 or higher** (for stable AsyncLocalStorage support)
123
+ - **ESM support** (ES modules with `import`/`export`)
124
+
125
+ > [!IMPORTANT]
126
+ > **v2.x Breaking Change**: Slothlet v2.x requires AsyncLocalStorage for its comprehensive live-binding system, which was stabilized in Node.js v16.4.0+ (June 2021). If you need older Node.js versions, please use slothlet v1.x (which requires Node.js v12.20.0+ (November 2020) for ESM support, dynamic imports, and query string imports). Note that v1.x live-binding worked in ESM (including multiple APIs via query strings) but was not available for multiple API instances in CommonJS.
127
+
128
+ ### Install
129
+
130
+ ```bash
34
131
  npm install @cldmv/slothlet
35
132
  ```
36
133
 
37
- ## Usage
134
+ ---
38
135
 
39
- > **Note:**
40
- >
41
- > - When using **lazy mode**, all API calls must be `await`ed, as modules are loaded asynchronously on access.
42
- > - If you need to create more than one slothlet instance, you must import the slothlet module using a param string (e.g., `import slothlet from "./slothlet.mjs?instance=1"`).
43
- > - **Caveat:** Live bindings (`self`, `context`, `reference`) will only work correctly if you use the same param string for both the loader and any submodules that import those bindings. Mismatched param strings will result in separate module instances and broken live bindings.
136
+ ## 🚀 Quick Start
137
+
138
+ ### ESM (ES Modules)
139
+
140
+ ```javascript
141
+ import slothlet from "@cldmv/slothlet";
142
+
143
+ // Direct usage - eager mode by default (auto-detects callable interface)
144
+ const api = await slothlet({
145
+ dir: "./api",
146
+ context: { user: "alice" }
147
+ });
148
+
149
+ // Eager mode: Functions behave as originally defined
150
+ const result = api.math.add(2, 3); // Sync function - no await needed
151
+ const greeting = api("World"); // Instant if callable
152
+
153
+ // Original async functions still need await in eager mode
154
+ const asyncResult = await api.async.processData({ data: "async" });
155
+
156
+ // Access both ESM and CJS modules seamlessly
157
+ const esmResult = api.mathEsm.multiply(4, 5); // 20 (sync)
158
+ const cjsResult = await api.mathCjs.divide(10, 2); // 5 (if originally async)
159
+ ```
160
+
161
+ ### CommonJS (CJS)
162
+
163
+ ```javascript
164
+ const slothlet = require("@cldmv/slothlet");
165
+
166
+ // Same usage pattern works with CommonJS
167
+ const api = await slothlet({
168
+ dir: "./api",
169
+ context: { env: "production" }
170
+ });
171
+
172
+ const result = api.math.multiply(4, 5); // 20
173
+ const mixedResult = await api.interop.processData({ data: "test" }); // CJS+ESM interop
174
+ ```
175
+
176
+ ### Lazy Loading Mode
177
+
178
+ ```javascript
179
+ import slothlet from "@cldmv/slothlet";
44
180
 
45
- ### Node.js API
181
+ // Lazy mode with copy-left materialization (opt-in)
182
+ const api = await slothlet({
183
+ lazy: true,
184
+ dir: "./api",
185
+ apiDepth: 3
186
+ });
46
187
 
47
- ```js
188
+ // First access: ~310μs (materialization overhead)
189
+ const result1 = await api.math.add(2, 3);
190
+
191
+ // Subsequent access: ~0.5μs (materialized function)
192
+ const result2 = await api.math.add(5, 7); // 700x faster than first call!
193
+ ```
194
+
195
+ ### Advanced Configuration
196
+
197
+ ```javascript
198
+ import slothlet from "@cldmv/slothlet";
199
+
200
+ const api = await slothlet({
201
+ dir: "./api",
202
+ lazy: false, // Loading strategy
203
+ api_mode: "auto", // API structure behavior
204
+ apiDepth: Infinity, // Directory traversal depth
205
+ debug: false, // Enable verbose logging
206
+ context: {
207
+ // Injected into live-binding
208
+ user: "alice",
209
+ env: "production",
210
+ config: { timeout: 5000 }
211
+ },
212
+ reference: {
213
+ // Merged into API root
214
+ version: "2.0.0",
215
+ helpers: {
216
+ /* ... */
217
+ }
218
+ }
219
+ });
220
+ ```
221
+
222
+ ### Multiple Instances
223
+
224
+ In v2.x, each call to `slothlet(options)` automatically creates a new isolated instance with its own context and configuration:
225
+
226
+ #### ESM (ES Modules)
227
+
228
+ ```javascript
48
229
  import slothlet from "@cldmv/slothlet";
49
230
 
50
- // Lazy load from default directory
51
- const api = await slothlet.create({ lazy: true, context });
231
+ // Each call creates a new isolated instance automatically
232
+ const api1 = await slothlet({ dir: "./api1", context: { tenant: "alice" } });
233
+ const api2 = await slothlet({ dir: "./api2", context: { tenant: "bob" } });
234
+
235
+ // Instances are completely isolated
236
+ console.log(api1.context.tenant); // "alice"
237
+ console.log(api2.context.tenant); // "bob"
238
+ ```
239
+
240
+ #### CommonJS (CJS)
241
+
242
+ ```javascript
243
+ const slothlet = require("@cldmv/slothlet");
244
+
245
+ // Each call creates a new isolated instance automatically
246
+ const api1 = await slothlet({ dir: "./api1", context: { tenant: "alice" } });
247
+ const api2 = await slothlet({ dir: "./api2", context: { tenant: "bob" } });
248
+
249
+ // Instances are completely isolated with their own AsyncLocalStorage contexts
250
+ console.log(api1.context.tenant); // "alice"
251
+ console.log(api2.context.tenant); // "bob"
252
+ ```
253
+
254
+ > [!NOTE]
255
+ > **v2.x Simplification**: Unlike v1.x which required query string parameters or `withInstanceId()` methods, v2.x automatically creates isolated instances with each `slothlet()` call, leveraging AsyncLocalStorage for complete context separation.
256
+
257
+ ---
258
+
259
+ ## 📚 API Reference
260
+
261
+ ### Core Methods
262
+
263
+ #### `slothlet(options)` ⇒ `Promise<object>`
264
+
265
+ Creates and loads an API instance with the specified configuration.
266
+
267
+ **Parameters:**
268
+
269
+ | Param | Type | Description |
270
+ | ------- | -------- | --------------------- |
271
+ | options | `object` | Configuration options |
272
+
273
+ **Returns:** `Promise<object>` - The bound API object
52
274
 
53
- // Access API endpoints
54
- const sum = await api.math.add(2, 3); // 5
55
- const upper = await api.string.upper("abc"); // 'ABC'
56
- const today = await api.nested.date.today(); // '2025-08-15'
275
+ **Options:**
57
276
 
277
+ | Option | Type | Default | Description |
278
+ | ----------- | --------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
279
+ | `dir` | `string` | `"api"` | Directory to load API modules from. Can be absolute or relative path. If relative, resolved from process.cwd(). |
280
+ | `lazy` | `boolean` | `false` | Loading strategy - `true` for lazy loading (on-demand), `false` for eager loading (immediate) |
281
+ | `apiDepth` | `number` | `Infinity` | Directory traversal depth control - `0` for root only, `Infinity` for all levels |
282
+ | `debug` | `boolean` | `false` | Enable verbose logging. Can also be set via `--slothletdebug` command line flag or `SLOTHLET_DEBUG=true` environment variable |
283
+ | `mode` | `string` | `"singleton"` | Execution environment mode - `"singleton"`, `"vm"`, `"worker"`, or `"fork"` |
284
+ | `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) |
285
+ | `context` | `object` | `{}` | Context data object injected into live-binding `context` reference. Available to all loaded modules via `import { context } from '@cldmv/slothlet/runtime'` |
286
+ | `reference` | `object` | `{}` | Reference object merged into the API root level. Properties not conflicting with loaded modules are added directly to the API |
58
287
 
288
+ #### `slothlet.getApi()` ⇒ `object`
59
289
 
60
- // Eager load from a custom directory
61
- const api = await slothlet.create({ lazy: false, dir: "./api_test" context });
290
+ Returns the raw API object (Proxy or plain object).
62
291
 
63
- // Access API endpoints
64
- const sum = api.math.add(2, 3); // 5
65
- const upper = api.string.upper("abc"); // 'ABC'
66
- const today = api.nested.date.today(); // '2025-08-15'
292
+ **Returns:** `function | object` - The raw API object or function
293
+
294
+ #### `slothlet.getBoundApi()` `object`
295
+
296
+ Returns the bound API object with context and reference.
297
+
298
+ **Returns:** `function | object` - The bound API object or function with live bindings and context
299
+
300
+ #### `slothlet.isLoaded()` ⇒ `boolean`
301
+
302
+ Returns true if the API is loaded.
303
+
304
+ **Returns:** `boolean` - Whether the API has been loaded
305
+
306
+ #### `slothlet.shutdown()` ⇒ `Promise<void>`
307
+
308
+ Gracefully shuts down the API and cleans up resources.
309
+
310
+ **Returns:** `Promise<void>` - Resolves when shutdown is complete
311
+
312
+ > [!NOTE]
313
+ > **📚 For detailed API documentation with comprehensive parameter descriptions, method signatures, and examples, see [docs/API.md](docs/API.md)**
314
+
315
+ ### Live Bindings
316
+
317
+ Access live-bound references in your API modules:
318
+
319
+ ```javascript
320
+ // Create API with reference functions
321
+ const api = await slothlet({
322
+ dir: "./api",
323
+ reference: {
324
+ md5: (str) => crypto.createHash("md5").update(str).digest("hex"),
325
+ version: "2.0.0",
326
+ utils: { format: (msg) => `[LOG] ${msg}` }
327
+ }
328
+ });
67
329
  ```
68
330
 
69
- ## API Reference
331
+ ```javascript
332
+ // In your API modules (ESM)
333
+ import { self, context, reference } from "@cldmv/slothlet/runtime";
70
334
 
71
- ### Main Methods
335
+ export function myFunction() {
336
+ console.log(context.user); // Access live context
337
+ return self.otherModule.helper(); // Access other API modules
72
338
 
73
- - `slothlet.create(options)` Loads API modules and returns a bound API object. Options include lazy/eager mode, context, reference, and directory.
74
- - `slothlet.load(config, ctxRef)` — Loads API modules (lazy or eager) and binds context/reference. Returns the API object.
75
- - `slothlet.createBoundApi(context, reference)` Returns an API object bound to the provided context and reference.
76
- - `slothlet.getApi()` — Returns the loaded API object (Proxy or plain object).
77
- - `slothlet.getBoundApi()` — Returns the bound API object (with context/reference).
78
- - `slothlet.isLoaded()` — Returns true if the API is loaded.
79
- - `slothlet.shutdown()` — Gracefully shuts down the API and internal resources.
339
+ // Reference functions are available directly on self
340
+ const hash = self.md5("hello world"); // Access reference function
341
+ console.log(self.version); // Access reference data
342
+ }
80
343
 
81
- ### Config Options
344
+ // Mixed module example (ESM accessing CJS)
345
+ export function processData(data) {
346
+ // Call a CJS module from ESM
347
+ const processed = self.cjsModule.process(data);
82
348
 
83
- - `lazy` (boolean): Enable lazy loading (default: true)
84
- - `lazyDepth` (number): How deep to lazy load subdirectories (default: Infinity)
85
- - `dir` (string): Directory to load API modules from (default: loader's directory)
86
- - `debug` (boolean): Enable debug logging (default: false)
349
+ // Use reference utilities directly
350
+ const logged = self.utils.format(`Processed: ${processed}`);
351
+ return self.md5(logged); // Hash the result
352
+ }
353
+ ```
87
354
 
88
- ### Context & Reference
355
+ ```javascript
356
+ // In your CJS modules
357
+ const { self, context, reference } = require("@cldmv/slothlet/runtime");
89
358
 
90
- - `context`: Object passed to API modules for contextual data (e.g., user/session info)
91
- - `reference`: Object passed to API modules for additional references or configuration
359
+ function cjsFunction(data) {
360
+ console.log(context.env); // Access live context
92
361
 
93
- ### Error Handling
362
+ // Reference functions available directly on self
363
+ const hash = self.md5(data); // Direct access to reference function
94
364
 
95
- - Throws descriptive errors for missing API paths or methods
96
- - All errors include the requested path and directory for easier debugging
365
+ return self.esmModule.transform(hash); // Access ESM modules from CJS
366
+ }
97
367
 
98
- ### JSDoc
368
+ module.exports = { cjsFunction };
369
+ ```
370
+
371
+ ### API Mode Configuration
372
+
373
+ The `api_mode` option controls how slothlet handles root-level default function exports:
374
+
375
+ #### Auto-Detection (Recommended)
99
376
 
100
- See JSDoc comments in the source code for detailed type annotations and usage examples.
377
+ ```javascript
378
+ const api = await slothlet({
379
+ api_mode: "auto" // Default - automatically detects structure
380
+ });
381
+
382
+ // If you have a root-level function export:
383
+ // root-function.mjs: export default function(name) { return `Hello, ${name}!` }
384
+ // Result: api("World") works AND api.otherModule.method() works
385
+
386
+ // If you only have object exports:
387
+ // Result: api.math.add() works, api("World") doesn't exist
388
+ ```
101
389
 
102
- ## Module Structure
390
+ #### Explicit Function Mode
103
391
 
104
- - Single-file modules: `api_test/math/math.mjs` → `api.math`
105
- - Multi-file modules: `api_test/multi/alpha.mjs` → `api.multi.alpha`, `api_test/multi/beta.mjs` `api.multi.beta`
106
- - Dashes in names: `api_test/root-math.mjs` → `api.rootMath`
392
+ ```javascript
393
+ const api = await slothlet({
394
+ api_mode: "function" // Force callable interface
395
+ });
396
+
397
+ // Always creates callable API even without root default export
398
+ // Useful when you know you have root functions
399
+ const result = api("World"); // Calls root default function
400
+ const math = api.math.add(2, 3); // Also access other modules
401
+ ```
402
+
403
+ #### Explicit Object Mode
404
+
405
+ ```javascript
406
+ const api = await slothlet({
407
+ api_mode: "object" // Force object-only interface
408
+ });
409
+
410
+ // Always creates object interface even with root default export
411
+ // api("World") won't work, but api.rootFunction("World") will
412
+ const result = api.rootFunction("World"); // Access via property
413
+ const math = api.math.add(2, 3); // Normal module access
414
+ ```
107
415
 
108
- ## Safety & Errors
416
+ ---
109
417
 
110
- - Throws descriptive errors for missing API paths or methods
111
- - Only loads modules when accessed (lazy) or all at once (eager)
418
+ ## 🏗 Module Structure & Examples
112
419
 
113
- ## License
420
+ Slothlet supports sophisticated module organization patterns with seamless ESM/CJS interoperability:
421
+
422
+ ### Root-Level Modules
423
+
424
+ ```text
425
+ root-math.mjs → api.rootMath (dash-to-camelCase)
426
+ rootstring.mjs → api.rootstring
427
+ config.mjs → api.config
428
+ ```
429
+
430
+ ### Single-File Modules
431
+
432
+ ```text
433
+ math/math.mjs → api.math (automatic flattening)
434
+ string/string.mjs → api.string
435
+ util/util.cjs → api.util (CJS support)
436
+ ```
437
+
438
+ ### Multi-File Modules
439
+
440
+ ```text
441
+ multi/
442
+ ├── alpha.mjs → api.multi.alpha
443
+ ├── beta.mjs → api.multi.beta
444
+ └── gamma.cjs → api.multi.gamma (mixed ESM/CJS)
445
+ ```
446
+
447
+ ### Function-Based Modules
448
+
449
+ ```text
450
+ funcmod/funcmod.mjs → api.funcmod() (callable function)
451
+ multi_func/
452
+ ├── alpha.mjs → api.multi_func.alpha()
453
+ └── beta.cjs → api.multi_func.beta() (CJS callable)
454
+ ```
455
+
456
+ ### Mixed ESM/CJS Modules
457
+
458
+ ```text
459
+ interop/
460
+ ├── esm-module.mjs → api.interop.esmModule
461
+ ├── cjs-module.cjs → api.interop.cjsModule
462
+ └── mixed.mjs → api.interop.mixed (calls both ESM and CJS)
463
+ ```
464
+
465
+ ### Hybrid Export Patterns
466
+
467
+ ```text
468
+ exportDefault/exportDefault.mjs → api.exportDefault() (callable with methods)
469
+ objectDefaultMethod/ → api.objectDefaultMethod() (object with default)
470
+ ```
471
+
472
+ ### Nested Structure
473
+
474
+ ```text
475
+ nested/
476
+ └── date/
477
+ ├── date.mjs → api.nested.date
478
+ └── util.cjs → api.nested.dateUtil
479
+ advanced/
480
+ ├── selfObject/ → api.advanced.selfObject
481
+ └── nest*/ → Various nesting examples
482
+ ```
483
+
484
+ ### Utility Modules
485
+
486
+ ```text
487
+ util/
488
+ ├── controller.mjs → api.util.controller
489
+ ├── extract.cjs → api.util.extract (CJS utility)
490
+ └── url/
491
+ ├── parser.mjs → api.util.url.parser
492
+ └── builder.cjs → api.util.url.builder (mixed)
493
+ ```
494
+
495
+ ### Smart Function Naming Examples
496
+
497
+ ```text
498
+ task/auto-ip.mjs (exports autoIP) → api.task.autoIP (preserves function name)
499
+ util/parseJSON.mjs → api.util.parseJSON (preserves JSON casing)
500
+ api/getHTTPStatus.mjs → api.api.getHTTPStatus (preserves HTTP casing)
501
+ ```
502
+
503
+ ## 🔀 How Slothlet Works: Loading Modes Explained
504
+
505
+ ```mermaid
506
+ flowchart TD
507
+ MODULEFOLDERS --> SLOTHLET
508
+ SLOTHLET --> CHOOSEMODE
509
+
510
+ CHOOSEMODE --> LAZY
511
+ CHOOSEMODE --> EAGER
512
+
513
+ subgraph EAGER ["⚡ Eager Mode"]
514
+ direction TB
515
+ EAGER0 ~~~ EAGER1
516
+ EAGER2 ~~~ EAGER3
517
+
518
+ EAGER0@{ shape: braces, label: "📥 All modules loaded immediately" }
519
+ EAGER1@{ shape: braces, label: "✅ API methods available right away" }
520
+ EAGER2@{ shape: braces, label: "🔄 Function calls behave as originally defined" }
521
+ EAGER3@{ shape: braces, label: "📞 Sync stays sync: api.math.add(2,3)<br/>🔄 Async stays async: await api.async.process()" }
522
+ end
523
+
524
+ subgraph LAZY ["💤 Lazy Mode"]
525
+ direction TB
526
+ LAZY0 ~~~ LAZY1
527
+ LAZY2 ~~~ LAZY3
528
+ LAZY4 ~~~ LAZY5
529
+
530
+ LAZY0@{ shape: braces, label: "📦 Modules not loaded yet" }
531
+ LAZY1@{ shape: braces, label: "🎭 API methods are placeholders/proxies" }
532
+ LAZY2@{ shape: braces, label: "📞 First call triggers materialization" }
533
+ LAZY3@{ shape: braces, label: "⏳ All calls must be awaited<br/>await api.math.add(2,3)" }
534
+ LAZY4@{ shape: braces, label: "💾 Module stays loaded after materialization<br/>Copy-left materialization" }
535
+ LAZY5@{ shape: braces, label: "🚀 Subsequent calls nearly as fast as eager mode" }
536
+ end
537
+
538
+ subgraph EAGERCALL ["⚡ Eager Mode Calls"]
539
+ direction TB
540
+ end
541
+
542
+ subgraph LAZYCALL ["💤 Lazy Mode Calls"]
543
+ direction TB
544
+ LAZYCALL0 --> LAZYCALL2
545
+
546
+ LAZYCALL0@{ shape: rounded, label: "📞 First call" }
547
+ LAZYCALL1@{ shape: rounded, label: "🔁 Sequential calls" }
548
+ LAZYCALL2@{ shape: rounded, label: "🧩 Materialize" }
549
+ end
550
+
551
+ EAGER --> READYTOUSE
552
+ LAZY --> READYTOUSE
553
+
554
+ READYTOUSE --> CALL
555
+ CALL -.-> EAGERCALL
556
+ CALL -.-> LAZYCALL
557
+
558
+ EAGERCALL --> MATERIALIZEDFUNCTION
559
+ LAZYCALL1 --> MATERIALIZEDFUNCTION
560
+ LAZYCALL2 --> MATERIALIZEDFUNCTION
561
+
562
+ READYTOUSE@{ shape: rounded, label: "🎯 Ready to Use" }
563
+ MATERIALIZEDFUNCTION@{ shape: rounded, label: "✅ Materialized method/property" }
564
+ CALL@{ shape: trap-b, label: "📞 Call" }
565
+
566
+ %% Notes as unattached nodes with braces shape
567
+ subgraph ALWAYS ["✨ Extras Always On"]
568
+ direction TB
569
+ ALWAYS0 ~~~ ALWAYS1
570
+ ALWAYS1 ~~~ ALWAYS2
571
+
572
+ ALWAYS0@{ shape: rounded, label: "🔗 Live Bindings ALS<br/>Per-instance context isolation" }
573
+ ALWAYS1@{ shape: rounded, label: "🏷️ Smart Naming & Flattening<br/>math/math.mjs → api.math" }
574
+ ALWAYS2@{ shape: rounded, label: "🔄 Mixed Module Support<br/>Seamlessly mix .mjs and .cjs" }
575
+ end
576
+
577
+ MODULEFOLDERS@{ shape: st-rect, label: "📁 Modules Folder<br/>.mjs and/or .cjs files<br/>math.mjs, string.cjs, async.mjs" }
578
+ SLOTHLET@{ shape: rounded, label: "🔧 Call slothlet(options)" }
579
+ CHOOSEMODE@{ shape: diamond, label: "Choose Mode<br/>in options" }
580
+
581
+ style EAGER0 stroke:#9BC66B,color:#9BC66B,opacity:0.5
582
+ style EAGER1 stroke:#9BC66B,color:#9BC66B,opacity:0.5
583
+ style EAGER2 stroke:#9BC66B,color:#9BC66B,opacity:0.5
584
+ style EAGER3 stroke:#9BC66B,color:#9BC66B,opacity:0.5
585
+
586
+ style LAZY0 stroke:#9BC66B,color:#9BC66B,opacity:0.5
587
+ style LAZY1 stroke:#9BC66B,color:#9BC66B,opacity:0.5
588
+ style LAZY2 stroke:#9BC66B,color:#9BC66B,opacity:0.5
589
+ style LAZY3 stroke:#9BC66B,color:#9BC66B,opacity:0.5
590
+ style LAZY4 stroke:#9BC66B,color:#9BC66B,opacity:0.5
591
+ style LAZY5 stroke:#9BC66B,color:#9BC66B,opacity:0.5
592
+
593
+ %% Slothlet brand colors - #9BC66B primary on dark theme
594
+ style MODULEFOLDERS fill:#1a1a1a,stroke:#9BC66B,stroke-width:2px,color:#9BC66B,opacity:0.5
595
+ style SLOTHLET fill:#1a1a1a,stroke:#9BC66B,stroke-width:2px,color:#9BC66B,opacity:0.5
596
+ style CHOOSEMODE fill:#1a1a1a,stroke:#9BC66B,stroke-width:2px,color:#9BC66B,opacity:0.5
597
+ style READYTOUSE fill:#1a1a1a,stroke:#9BC66B,stroke-width:2px,color:#9BC66B,opacity:0.5
598
+ style CALL fill:#1a1a1a,stroke:#9BC66B,stroke-width:2px,color:#9BC66B,opacity:0.5
599
+ style MATERIALIZEDFUNCTION fill:#1a1a1a,stroke:#9BC66B,stroke-width:2px,color:#9BC66B,opacity:0.5
600
+
601
+ %% Eager mode - primary green
602
+ style EAGER fill:#0d1a0d,stroke:#9BC66B,stroke-width:3px,color:#9BC66B,opacity:0.5
603
+ style EAGERCALL fill:#0d1a0d,stroke:#9BC66B,stroke-width:2px,color:#9BC66B,opacity:0.5
604
+
605
+ %% Lazy mode - lighter green tint
606
+ style LAZY fill:#0d1a0d,stroke:#B8D982,stroke-width:3px,color:#B8D982,opacity:0.5
607
+ style LAZYCALL fill:#0d1a0d,stroke:#B8D982,stroke-width:2px,color:#B8D982,opacity:0.5
608
+ style LAZYCALL0 fill:#1a1a1a,stroke:#B8D982,stroke-width:2px,color:#B8D982,opacity:0.5
609
+ style LAZYCALL1 fill:#1a1a1a,stroke:#B8D982,stroke-width:2px,color:#B8D982,opacity:0.5
610
+ style LAZYCALL2 fill:#1a1a1a,stroke:#B8D982,stroke-width:2px,color:#B8D982,opacity:0.5
611
+
612
+ %% Always available - accent green
613
+ style ALWAYS fill:#0d1a0d,stroke:#7FA94F,stroke-width:3px,color:#7FA94F,opacity:0.5
614
+ style ALWAYS0 fill:#1a1a1a,stroke:#7FA94F,stroke-width:1px,color:#7FA94F,opacity:0.5
615
+ style ALWAYS1 fill:#1a1a1a,stroke:#7FA94F,stroke-width:1px,color:#7FA94F,opacity:0.5
616
+ style ALWAYS2 fill:#1a1a1a,stroke:#7FA94F,stroke-width:1px,color:#7FA94F,opacity:0.5
617
+
618
+ %% Arrow styling
619
+ linkStyle default stroke:#9BC66B,stroke-width:3px,opacity:0.5
620
+ linkStyle 4,5,6,7,8,18,19 stroke-width:0px
621
+ ```
622
+
623
+ ---
624
+
625
+ ## 🚀 Performance Modes
626
+
627
+ ### Eager Mode (Default - Production Ready)
628
+
629
+ ```javascript
630
+ const api = await slothlet({ dir: "./api" }); // lazy: false by default
631
+
632
+ // Functions behave as originally defined - no await needed for sync functions
633
+ const result = api.math.add(2, 3); // Sync function - direct call
634
+ const greeting = api("World"); // Instant if callable
635
+
636
+ // Async functions still need await (as originally defined)
637
+ const asyncResult = await api.async.processData({ data: "test" }); // Original async function
638
+
639
+ // ESM+CJS works seamlessly with native behavior
640
+ const mixed = api.interop.process({ data: "test" }); // Sync or async as defined
641
+ ```
642
+
643
+ **Benefits:**
644
+
645
+ - ✅ Fastest function calls (0.36μs average)
646
+ - ✅ Predictable performance
647
+ - ✅ No materialization delays
648
+ - ✅ Functions behave exactly as originally defined (sync stays sync, async stays async)
649
+ - ✅ Optimal for production environments
650
+
651
+ ### Lazy Mode with Copy-Left Materialization (Production Ready)
652
+
653
+ ```javascript
654
+ const api = await slothlet({ lazy: true, dir: "./api" });
655
+
656
+ // ALL function calls must be awaited in lazy mode (due to materialization)
657
+ const result1 = await api.math.add(2, 3); // First access: ~310μs (materialization)
658
+ const result2 = await api.math.add(5, 7); // Subsequent: ~0.5μs (materialized)
659
+
660
+ // Even originally sync functions need await in lazy mode
661
+ const greeting = await api("World"); // Callable interface also needs await
662
+ const syncResult = await api.string.format("Hello"); // Originally sync, but needs await
663
+ ```
664
+
665
+ **Benefits:**
666
+
667
+ - ✅ 4.3x faster startup (564.17μs vs 2.45ms)
668
+ - ✅ Memory efficient (loads only what you use)
669
+ - ✅ Copy-left optimization (once loaded, stays loaded)
670
+ - ✅ Optimal for startup-sensitive applications
671
+ - ⚠️ All function calls require await (regardless of original sync/async nature)
672
+
673
+ **Performance Summary:**
674
+
675
+ > [!TIP]
676
+ > **Choose your loading strategy based on your needs:**
677
+ >
678
+ > - **Startup**: Lazy wins (4.3x faster - 564.17μs vs 2.45ms)
679
+ > - **Function calls**: Eager wins (1.1x faster - 0.65μs vs 0.72μs)
680
+ > - **Memory**: Lazy wins (loads only what you use)
681
+ > - **Predictability**: Eager wins (no materialization delays)
682
+
683
+ ---
684
+
685
+ ## 🛡 Error Handling
686
+
687
+ > [!NOTE]
688
+ > **Current Error Behavior**: Slothlet currently uses standard JavaScript error handling. Enhanced error handling with module suggestions is planned for v2.1.0 but not yet implemented.
689
+
690
+ **Current behavior:**
691
+
692
+ ```javascript
693
+ try {
694
+ console.log(api.nonexistent); // Returns: undefined
695
+ await api.nonexistent.method(); // Throws: "Cannot read properties of undefined (reading 'method')"
696
+ } catch (error) {
697
+ console.error(error.message); // Standard JavaScript error message
698
+ }
699
+ ```
700
+
701
+ **Planned Enhanced Error Features (v2.1.0):**
702
+
703
+ > [!TIP]
704
+ > **Coming Soon**: Enhanced error handling with descriptive messages and module suggestions:
705
+ >
706
+ > ```javascript
707
+ > try {
708
+ > await api.nonexistent.method();
709
+ > } catch (error) {
710
+ > console.error(error.message);
711
+ > // Planned: "Module 'nonexistent' not found in './api'. Available modules: math, string, util. Did you mean 'util'?"
712
+ > }
713
+ > ```
714
+ >
715
+ > **Planned Features:**
716
+ >
717
+ > - 🔍 **Module discovery**: Show available modules and suggest alternatives
718
+ > - 📍 **Context information**: Include directory path and configuration details
719
+ > - 🎯 **Actionable suggestions**: Provide specific guidance for resolution
720
+ > - 🚀 **Development mode**: Additional debugging information when debug flag is enabled
721
+
722
+ ---
723
+
724
+ ## 🔧 Production vs Development Modes
725
+
726
+ ### Production Ready ✅
727
+
728
+ - **Eager Mode**: Stable, battle-tested, maximum performance
729
+ - **Lazy Mode**: Production-ready with copy-left optimization
730
+ - **Singleton Mode**: Default mode for standard applications
731
+ - **Mixed Module Loading**: ESM/CJS interoperability fully supported
732
+
733
+ ### Development Features 🛠️
734
+
735
+ - **Development Check**: `devcheck.mjs` for environment validation
736
+ - **Debug Mode**: Comprehensive logging via `--slothletdebug` flag or `SLOTHLET_DEBUG=true`
737
+ - **Performance Monitoring**: Built-in timing and performance analysis
738
+ - **Source Detection**: Automatic `src/` vs `dist/` mode detection
739
+
740
+ ### Experimental ⚠️
741
+
742
+ > [!WARNING]
743
+ > The following modes are in active development and not recommended for production use:
744
+ >
745
+ > - **Worker Mode**: Thread isolation (in development)
746
+ > - **Fork Mode**: Process isolation (in development)
747
+ > - **Child Mode**: Child process execution (in development)
748
+ > - **VM Mode**: Virtual machine context (in development)
749
+ >
750
+ > The experimental modes are located in `src/lib/engine/` and should not be used in production environments.
751
+
752
+ ---
753
+
754
+ ## 🌟 Migration from v1.x
755
+
756
+ ### Key Changes
757
+
758
+ 1. **Import paths**: `@cldmv/slothlet` instead of specific file paths
759
+ 2. **Configuration**: New options (`api_mode`, `context`, `reference`)
760
+ 3. **Function names**: Enhanced preservation of original capitalization
761
+ 4. **Module structure**: Mixed ESM/CJS support
762
+ 5. **Live bindings**: New runtime system with AsyncLocalStorage
763
+
764
+ ### Migration Steps
765
+
766
+ ```javascript
767
+ // v1.3.x - API creation (same pattern as v2.x)
768
+ import slothlet from "@cldmv/slothlet";
769
+ const api = await slothlet({
770
+ dir: "./api",
771
+ lazy: true
772
+ });
773
+
774
+ // v1.3.x - Multiple instances required query strings or withInstanceId()
775
+ const api1 = await slothlet({ dir: "./api?instanceId=alice" });
776
+ const api2 = slothlet.withInstanceId("bob");
777
+ const bobApi = await api2({ dir: "./api" });
778
+
779
+ // v2.0 - Same API creation, but automatic instance isolation
780
+ import slothlet from "@cldmv/slothlet";
781
+ const api = await slothlet({
782
+ dir: "./api",
783
+ lazy: true,
784
+ context: { user: "alice" }, // New: context injection
785
+ api_mode: "auto" // New: API mode control
786
+ });
787
+
788
+ // v2.0 - Multiple instances automatically isolated (no query strings needed)
789
+ const api1 = await slothlet({ dir: "./api", context: { tenant: "alice" } });
790
+ const api2 = await slothlet({ dir: "./api", context: { tenant: "bob" } });
791
+ ```
792
+
793
+ ### Performance Improvements
794
+
795
+ - **Architectural optimizations** with copy-left materialization and AsyncLocalStorage integration
796
+ - **Zero dependencies** - pure Node.js implementation reduces overhead
797
+ - **Enhanced materialization** with copy-left optimization in lazy mode
798
+ - **Modular design** improves maintainability and potential optimization opportunities
799
+
800
+ ---
801
+
802
+ ## 🤝 Contributing
803
+
804
+ We welcome contributions! The experimental modes in particular need development and testing. Please:
805
+
806
+ 1. **Review the code** in `src/lib/engine/` for experimental features
807
+ 2. **Report issues** with detailed reproduction steps
808
+ 3. **Submit pull requests** with comprehensive tests
809
+ 4. **Provide feedback** on API design and performance
810
+ 5. **Documentation improvements** are always appreciated
811
+
812
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed contribution guidelines.
813
+
814
+ [![Contributors]][contributors_url] [![Sponsor shinrai]][sponsor_url]
815
+
816
+ ---
817
+
818
+ ## 📊 Performance Analysis
819
+
820
+ For comprehensive performance benchmarks, analysis, and recommendations:
821
+
822
+ **📈 [See PERFORMANCE.md](PERFORMANCE.md)**
823
+
824
+ Key highlights:
825
+
826
+ - Detailed startup vs runtime performance comparison
827
+ - Memory usage analysis by loading mode
828
+ - Materialization cost breakdown by module type
829
+ - Real-world performance recommendations
830
+
831
+ [![CodeFactor]][codefactor_url] [![npms.io score]][npms_url]
832
+
833
+ [![npm unpacked size]][npm_size_url] [![Repo size]][repo_size_url]
834
+
835
+ ---
836
+
837
+ ## 📚 Documentation
838
+
839
+ - **[API Documentation](docs/API.md)** - Complete API reference with examples
840
+ - **[Performance Analysis](PERFORMANCE.md)** - Detailed benchmarks and recommendations
841
+ - **[Contributing Guide](CONTRIBUTING.md)** - How to contribute to the project
842
+ - **[Security Policy](SECURITY.md)** - Security guidelines and reporting
843
+ - **[Test Documentation](api_tests/)** - Comprehensive test module examples
844
+
845
+ ---
846
+
847
+ ## 🔗 Links
848
+
849
+ - **npm**: [@cldmv/slothlet](https://www.npmjs.com/package/@cldmv/slothlet)
850
+ - **GitHub**: [CLDMV/slothlet](https://github.com/CLDMV/slothlet)
851
+ - **Issues**: [GitHub Issues](https://github.com/CLDMV/slothlet/issues)
852
+ - **Releases**: [GitHub Releases](https://github.com/CLDMV/slothlet/releases)
853
+
854
+ ---
855
+
856
+ ## 📄 License
857
+
858
+ [![GitHub license]][github_license_url] [![npm license]][npm_license_url]
114
859
 
115
860
  Apache-2.0 © Shinrai / CLDMV
861
+
862
+ ---
863
+
864
+ ## 🙏 Acknowledgments
865
+
866
+ Slothlet v2.0 represents a complete architectural rewrite with enterprise-grade features and performance. Special thanks to all contributors who made this comprehensive enhancement possible.
867
+
868
+ **🎉 Welcome to the future of module loading with Slothlet v2.0!**
869
+
870
+ > _Where sophisticated architecture meets blazing performance - slothlet is anything but slow._
871
+
872
+ <!-- [github release]: https://img.shields.io/github/v/release/CLDMV/slothlet?style=for-the-badge&logo=github&logoColor=white&labelColor=181717 -->
873
+ <!-- [github_release_url]: https://github.com/CLDMV/slothlet/releases -->
874
+
875
+ [npm version]: https://img.shields.io/npm/v/%40cldmv%2Fslothlet.svg?style=for-the-badge&logo=npm&logoColor=white&labelColor=CB3837
876
+ [npm_version_url]: https://www.npmjs.com/package/@cldmv/slothlet
877
+ [last commit]: https://img.shields.io/github/last-commit/CLDMV/slothlet?style=for-the-badge&logo=github&logoColor=white&labelColor=181717
878
+ [last_commit_url]: https://github.com/CLDMV/slothlet/commits
879
+
880
+ <!-- [release date]: https://img.shields.io/github/release-date/CLDMV/slothlet?style=for-the-badge&logo=github&logoColor=white&labelColor=181717 -->
881
+ <!-- [release_date_url]: https://github.com/CLDMV/slothlet/releases -->
882
+
883
+ [npm last update]: https://img.shields.io/npm/last-update/%40cldmv%2Fslothlet?style=for-the-badge&logo=npm&logoColor=white&labelColor=CB3837
884
+ [npm_last_update_url]: https://www.npmjs.com/package/@cldmv/slothlet
885
+ [codefactor]: https://img.shields.io/codefactor/grade/github/CLDMV/slothlet?style=for-the-badge&logo=codefactor&logoColor=white&labelColor=F44A6A
886
+ [codefactor_url]: https://www.codefactor.io/repository/github/cldmv/slothlet
887
+ [npms.io score]: https://img.shields.io/npms-io/final-score/%40cldmv%2Fslothlet?style=for-the-badge&logo=npms&logoColor=white&labelColor=0B5D57
888
+ [npms_url]: https://npms.io/search?q=%40cldmv%2Fslothlet
889
+ [npm downloads]: https://img.shields.io/npm/dm/%40cldmv%2Fslothlet.svg?style=for-the-badge&logo=npm&logoColor=white&labelColor=CB3837
890
+ [npm_downloads_url]: https://www.npmjs.com/package/@cldmv/slothlet
891
+ [github downloads]: https://img.shields.io/github/downloads/CLDMV/slothlet/total?style=for-the-badge&logo=github&logoColor=white&labelColor=181717
892
+ [github_downloads_url]: https://github.com/CLDMV/slothlet/releases
893
+ [npm unpacked size]: https://img.shields.io/npm/unpacked-size/%40cldmv%2Fslothlet.svg?style=for-the-badge&logo=npm&logoColor=white&labelColor=CB3837
894
+ [npm_size_url]: https://www.npmjs.com/package/@cldmv/slothlet
895
+ [repo size]: https://img.shields.io/github/repo-size/CLDMV/slothlet?style=for-the-badge&logo=github&logoColor=white&labelColor=181717
896
+ [repo_size_url]: https://github.com/CLDMV/slothlet
897
+ [github license]: https://img.shields.io/github/license/CLDMV/slothlet.svg?style=for-the-badge&logo=github&logoColor=white&labelColor=181717
898
+ [github_license_url]: LICENSE
899
+ [npm license]: https://img.shields.io/npm/l/%40cldmv%2Fslothlet.svg?style=for-the-badge&logo=npm&logoColor=white&labelColor=CB3837
900
+ [npm_license_url]: https://www.npmjs.com/package/@cldmv/slothlet
901
+ [contributors]: https://img.shields.io/github/contributors/CLDMV/slothlet.svg?style=for-the-badge&logo=github&logoColor=white&labelColor=181717
902
+ [contributors_url]: https://github.com/CLDMV/slothlet/graphs/contributors
903
+ [sponsor shinrai]: https://img.shields.io/github/sponsors/shinrai?style=for-the-badge&logo=githubsponsors&logoColor=white&labelColor=EA4AAA&label=Sponsor
904
+ [sponsor_url]: https://github.com/sponsors/shinrai