@cldmv/slothlet 3.2.3 → 3.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -9
- package/REFERENCE.md +23 -0
- package/dist/lib/builders/api-assignment.mjs +1 -589
- package/dist/lib/builders/api_builder.mjs +1 -1155
- package/dist/lib/builders/builder.mjs +1 -78
- package/dist/lib/builders/modes-processor.mjs +1 -1800
- package/dist/lib/errors.mjs +9 -211
- package/dist/lib/factories/component-base.mjs +1 -80
- package/dist/lib/factories/context.mjs +1 -22
- package/dist/lib/handlers/api-cache-manager.mjs +1 -200
- package/dist/lib/handlers/api-manager.mjs +1 -2513
- package/dist/lib/handlers/context-async.mjs +1 -168
- package/dist/lib/handlers/context-live.mjs +1 -168
- package/dist/lib/handlers/hook-manager.mjs +1 -773
- package/dist/lib/handlers/lifecycle-token.mjs +1 -28
- package/dist/lib/handlers/lifecycle.mjs +1 -115
- package/dist/lib/handlers/materialize-manager.mjs +1 -48
- package/dist/lib/handlers/metadata.mjs +1 -501
- package/dist/lib/handlers/ownership.mjs +1 -322
- package/dist/lib/handlers/permission-manager.mjs +17 -0
- package/dist/lib/handlers/unified-wrapper.mjs +1 -3042
- package/dist/lib/handlers/version-manager.mjs +1 -885
- package/dist/lib/helpers/class-instance-wrapper.mjs +1 -109
- package/dist/lib/helpers/config.mjs +1 -355
- package/dist/lib/helpers/eventemitter-context.mjs +1 -349
- package/dist/lib/helpers/hint-detector.mjs +1 -47
- package/dist/lib/helpers/modes-utils.mjs +1 -37
- package/dist/lib/helpers/pattern-matcher.mjs +17 -0
- package/dist/lib/helpers/resolve-from-caller.mjs +1 -169
- package/dist/lib/helpers/sanitize.mjs +1 -340
- package/dist/lib/helpers/utilities.mjs +1 -70
- package/dist/lib/i18n/languages/de-de.json +21 -1
- package/dist/lib/i18n/languages/en-gb.json +21 -1
- package/dist/lib/i18n/languages/en-us.json +21 -1
- package/dist/lib/i18n/languages/es-mx.json +21 -1
- package/dist/lib/i18n/languages/fr-fr.json +21 -1
- package/dist/lib/i18n/languages/hi-in.json +21 -1
- package/dist/lib/i18n/languages/ja-jp.json +21 -1
- package/dist/lib/i18n/languages/ko-kr.json +21 -1
- package/dist/lib/i18n/languages/pt-br.json +21 -1
- package/dist/lib/i18n/languages/ru-ru.json +21 -1
- package/dist/lib/i18n/languages/zh-cn.json +21 -1
- package/dist/lib/i18n/translations.mjs +1 -126
- package/dist/lib/modes/eager.mjs +1 -59
- package/dist/lib/modes/lazy.mjs +1 -81
- package/dist/lib/processors/flatten.mjs +1 -437
- package/dist/lib/processors/loader.mjs +1 -339
- package/dist/lib/processors/type-generator.mjs +1 -275
- package/dist/lib/processors/typescript.mjs +1 -172
- package/dist/lib/runtime/runtime-asynclocalstorage.mjs +1 -113
- package/dist/lib/runtime/runtime-livebindings.mjs +1 -78
- package/dist/lib/runtime/runtime.mjs +1 -102
- package/dist/slothlet.mjs +1 -808
- package/package.json +37 -31
- package/types/dist/lib/builders/api-assignment.d.mts +3 -92
- package/types/dist/lib/builders/api-assignment.d.mts.map +1 -1
- package/types/dist/lib/builders/api_builder.d.mts +102 -91
- package/types/dist/lib/builders/api_builder.d.mts.map +1 -1
- package/types/dist/lib/builders/builder.d.mts +1 -55
- package/types/dist/lib/builders/builder.d.mts.map +1 -1
- package/types/dist/lib/builders/modes-processor.d.mts +3 -27
- package/types/dist/lib/builders/modes-processor.d.mts.map +1 -1
- package/types/dist/lib/errors.d.mts +19 -109
- package/types/dist/lib/errors.d.mts.map +1 -1
- package/types/dist/lib/factories/component-base.d.mts +7 -177
- package/types/dist/lib/factories/component-base.d.mts.map +1 -1
- package/types/dist/lib/factories/context.d.mts +4 -22
- package/types/dist/lib/factories/context.d.mts.map +1 -1
- package/types/dist/lib/handlers/api-cache-manager.d.mts +20 -203
- package/types/dist/lib/handlers/api-cache-manager.d.mts.map +1 -1
- package/types/dist/lib/handlers/api-manager.d.mts +33 -408
- package/types/dist/lib/handlers/api-manager.d.mts.map +1 -1
- package/types/dist/lib/handlers/context-async.d.mts +23 -61
- package/types/dist/lib/handlers/context-async.d.mts.map +1 -1
- package/types/dist/lib/handlers/context-live.d.mts +22 -59
- package/types/dist/lib/handlers/context-live.d.mts.map +1 -1
- package/types/dist/lib/handlers/hook-manager.d.mts +46 -185
- package/types/dist/lib/handlers/hook-manager.d.mts.map +1 -1
- package/types/dist/lib/handlers/lifecycle-token.d.mts +3 -48
- package/types/dist/lib/handlers/lifecycle-token.d.mts.map +1 -1
- package/types/dist/lib/handlers/lifecycle.d.mts +5 -82
- package/types/dist/lib/handlers/lifecycle.d.mts.map +1 -1
- package/types/dist/lib/handlers/materialize-manager.d.mts +8 -70
- package/types/dist/lib/handlers/materialize-manager.d.mts.map +1 -1
- package/types/dist/lib/handlers/metadata.d.mts +17 -221
- package/types/dist/lib/handlers/metadata.d.mts.map +1 -1
- package/types/dist/lib/handlers/ownership.d.mts +44 -160
- package/types/dist/lib/handlers/ownership.d.mts.map +1 -1
- package/types/dist/lib/handlers/permission-manager.d.mts +47 -0
- package/types/dist/lib/handlers/permission-manager.d.mts.map +1 -0
- package/types/dist/lib/handlers/unified-wrapper.d.mts +26 -239
- package/types/dist/lib/handlers/unified-wrapper.d.mts.map +1 -1
- package/types/dist/lib/handlers/version-manager.d.mts +28 -225
- package/types/dist/lib/handlers/version-manager.d.mts.map +1 -1
- package/types/dist/lib/helpers/class-instance-wrapper.d.mts +2 -52
- package/types/dist/lib/helpers/class-instance-wrapper.d.mts.map +1 -1
- package/types/dist/lib/helpers/config.d.mts +125 -123
- package/types/dist/lib/helpers/config.d.mts.map +1 -1
- package/types/dist/lib/helpers/eventemitter-context.d.mts +3 -29
- package/types/dist/lib/helpers/eventemitter-context.d.mts.map +1 -1
- package/types/dist/lib/helpers/hint-detector.d.mts +2 -15
- package/types/dist/lib/helpers/hint-detector.d.mts.map +1 -1
- package/types/dist/lib/helpers/modes-utils.d.mts +3 -30
- package/types/dist/lib/helpers/modes-utils.d.mts.map +1 -1
- package/types/dist/lib/helpers/pattern-matcher.d.mts +4 -0
- package/types/dist/lib/helpers/pattern-matcher.d.mts.map +1 -0
- package/types/dist/lib/helpers/resolve-from-caller.d.mts +3 -27
- package/types/dist/lib/helpers/resolve-from-caller.d.mts.map +1 -1
- package/types/dist/lib/helpers/sanitize.d.mts +4 -92
- package/types/dist/lib/helpers/sanitize.d.mts.map +1 -1
- package/types/dist/lib/helpers/utilities.d.mts +4 -52
- package/types/dist/lib/helpers/utilities.d.mts.map +1 -1
- package/types/dist/lib/i18n/translations.d.mts +4 -37
- package/types/dist/lib/i18n/translations.d.mts.map +1 -1
- package/types/dist/lib/modes/eager.d.mts +8 -30
- package/types/dist/lib/modes/eager.d.mts.map +1 -1
- package/types/dist/lib/modes/lazy.d.mts +10 -43
- package/types/dist/lib/modes/lazy.d.mts.map +1 -1
- package/types/dist/lib/processors/flatten.d.mts +56 -107
- package/types/dist/lib/processors/flatten.d.mts.map +1 -1
- package/types/dist/lib/processors/loader.d.mts +6 -41
- package/types/dist/lib/processors/loader.d.mts.map +1 -1
- package/types/dist/lib/processors/type-generator.d.mts +2 -16
- package/types/dist/lib/processors/type-generator.d.mts.map +1 -1
- package/types/dist/lib/processors/typescript.d.mts +6 -53
- package/types/dist/lib/processors/typescript.d.mts.map +1 -1
- package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts +3 -71
- package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts.map +1 -1
- package/types/dist/lib/runtime/runtime-livebindings.d.mts +2 -37
- package/types/dist/lib/runtime/runtime-livebindings.d.mts.map +1 -1
- package/types/dist/lib/runtime/runtime.d.mts +3 -39
- package/types/dist/lib/runtime/runtime.d.mts.map +1 -1
- package/types/dist/slothlet.d.mts +3 -249
- package/types/dist/slothlet.d.mts.map +1 -1
- package/types/index.d.mts +36 -16
- package/types/index.d.mts.map +1 -0
- package/AGENT-USAGE.md +0 -736
- package/docs/API-RULES.md +0 -712
package/AGENT-USAGE.md
DELETED
|
@@ -1,736 +0,0 @@
|
|
|
1
|
-
# AGENT-USAGE.md: Building Slothlet API Folders
|
|
2
|
-
|
|
3
|
-
> **Critical**: This guide prevents AI agents from making architectural mistakes when building Slothlet API modules.
|
|
4
|
-
|
|
5
|
-
## 📋 Related Documentation
|
|
6
|
-
|
|
7
|
-
- **[`docs/API-RULES.md`](docs/API-RULES.md)** - All 13 API transformation rules with verified test examples
|
|
8
|
-
- **[`README.md`](README.md)** - Complete project overview and usage examples
|
|
9
|
-
- **[`api_tests/*/README.md`](api_tests/)** - Live examples demonstrating each pattern below
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## 🚫 NEVER DO: Cross-Module Imports
|
|
14
|
-
|
|
15
|
-
**The #1 mistake AI agents make with Slothlet**: Importing API files from each other.
|
|
16
|
-
|
|
17
|
-
```js
|
|
18
|
-
// ❌ WRONG - Do NOT import API modules from each other
|
|
19
|
-
import { math } from "./math/math.mjs"; // BREAKS SLOTHLET
|
|
20
|
-
import { config } from "../config.mjs"; // BREAKS SLOTHLET
|
|
21
|
-
import { util } from "./util/util.mjs"; // BREAKS SLOTHLET
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
**Why this breaks Slothlet**:
|
|
25
|
-
|
|
26
|
-
- Slothlet builds API structure dynamically at runtime
|
|
27
|
-
- Cross-imports create circular dependencies
|
|
28
|
-
- Breaks lazy loading and context isolation
|
|
29
|
-
- Defeats the purpose of the module loading framework
|
|
30
|
-
|
|
31
|
-
## ✅ CORRECT: Use Slothlet's Live-Binding System
|
|
32
|
-
|
|
33
|
-
```js
|
|
34
|
-
// ✅ CORRECT - Import from Slothlet runtime for cross-module access
|
|
35
|
-
import { self, context } from "@cldmv/slothlet/runtime";
|
|
36
|
-
|
|
37
|
-
export const myModule = {
|
|
38
|
-
async processData(input) {
|
|
39
|
-
// Access other API modules via `self` (live binding - always current)
|
|
40
|
-
const mathResult = self.math.add(2, 3);
|
|
41
|
-
const configValue = self.config.get("setting");
|
|
42
|
-
// context holds the current request/call context
|
|
43
|
-
console.log(`Caller: ${context.userId}`);
|
|
44
|
-
return `Processed: ${input}, Math: ${mathResult}`;
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
## 🏗️ API Module Patterns
|
|
52
|
-
|
|
53
|
-
### Pattern 1: Simple Object Export (Most Common)
|
|
54
|
-
|
|
55
|
-
**File**: `math/math.mjs` → **API**: `api.math.add()`, `api.math.multiply()`
|
|
56
|
-
|
|
57
|
-
```js
|
|
58
|
-
export const math = {
|
|
59
|
-
add(a, b) { return a + b; },
|
|
60
|
-
multiply(a, b) { return a * b; }
|
|
61
|
-
};
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
**Result**: Filename matches folder (`math/math.mjs`) → Auto-flattening → `api.math.add()` (not `api.math.math.add()`)
|
|
65
|
-
|
|
66
|
-
> 📖 See [API-RULES.md Rule 1](docs/API-RULES.md) for flattening details.
|
|
67
|
-
|
|
68
|
-
### Pattern 2: Multiple Files in Folder
|
|
69
|
-
|
|
70
|
-
**Files**: `multi/alpha.mjs`, `multi/beta.mjs` → **API**: `api.multi.alpha.hello()`, `api.multi.beta.world()`
|
|
71
|
-
|
|
72
|
-
```js
|
|
73
|
-
// File: multi/alpha.mjs
|
|
74
|
-
export const alpha = { hello() { return "alpha hello"; } };
|
|
75
|
-
|
|
76
|
-
// File: multi/beta.mjs
|
|
77
|
-
export const beta = { world() { return "beta world"; } };
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
**Result**: Different filenames from folder → No flattening → Nested structure preserved.
|
|
81
|
-
|
|
82
|
-
### Pattern 3: Default Function Export
|
|
83
|
-
|
|
84
|
-
**File**: `funcmod/funcmod.mjs` → **API**: `api.funcmod(name)`
|
|
85
|
-
|
|
86
|
-
```js
|
|
87
|
-
export default function funcmod(name) {
|
|
88
|
-
return `Hello, ${name}!`;
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
**Result**: Filename matches folder + default export → Function flattened to `api.funcmod()`.
|
|
93
|
-
|
|
94
|
-
### Pattern 4: Root-Level API Functions
|
|
95
|
-
|
|
96
|
-
**File**: `root-function.mjs` → **API**: `api(name)` + `api.rootFunctionShout()`
|
|
97
|
-
|
|
98
|
-
```js
|
|
99
|
-
export default function greet(name) {
|
|
100
|
-
return `Hello, ${name}!`;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export function rootFunctionShout(message) {
|
|
104
|
-
return message.toUpperCase();
|
|
105
|
-
}
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
**Result**: Root file with default export → `api()` callable + named exports as top-level `api.methodName()`.
|
|
109
|
-
|
|
110
|
-
### Pattern 5: AddApi Special File Pattern (Rule 11)
|
|
111
|
-
|
|
112
|
-
Files named `addapi.mjs` always flatten regardless of `autoFlatten` setting:
|
|
113
|
-
|
|
114
|
-
```js
|
|
115
|
-
// File: plugins/addapi.mjs
|
|
116
|
-
export function initializePlugin() { return "Plugin initialized"; }
|
|
117
|
-
export function cleanup() { return "Plugin cleaned up"; }
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
```js
|
|
121
|
-
await api.slothlet.api.add("plugins", "./plugins-folder");
|
|
122
|
-
api.plugins.initializePlugin(); // ✅ Direct extension - no intermediate namespace
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
> 📖 See [API-RULES.md Rule 11](docs/API-RULES.md) for addApi flattening details.
|
|
126
|
-
|
|
127
|
-
---
|
|
128
|
-
|
|
129
|
-
## 🔄 Operating Modes
|
|
130
|
-
|
|
131
|
-
Slothlet supports two loading modes set via `mode:` in the config:
|
|
132
|
-
|
|
133
|
-
### Eager Mode (default)
|
|
134
|
-
|
|
135
|
-
All modules are loaded synchronously at `await slothlet(...)`. The API is fully populated before `slothlet()` resolves.
|
|
136
|
-
|
|
137
|
-
```js
|
|
138
|
-
const api = await slothlet({ dir: "./api" }); // mode: "eager" is default
|
|
139
|
-
// All api.* properties are immediately available
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
### Lazy Mode
|
|
143
|
-
|
|
144
|
-
Modules are loaded on first access via transparent proxy. `slothlet()` resolves immediately without loading any files.
|
|
145
|
-
|
|
146
|
-
```js
|
|
147
|
-
const api = await slothlet({
|
|
148
|
-
dir: "./api",
|
|
149
|
-
mode: "lazy"
|
|
150
|
-
});
|
|
151
|
-
// api.math is a proxy - file not loaded yet
|
|
152
|
-
const result = api.math.add(2, 3); // First access triggers load
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
#### Background Materialization
|
|
156
|
-
|
|
157
|
-
Enable `backgroundMaterialize: true` to pre-load all modules in the background immediately after init (still non-blocking):
|
|
158
|
-
|
|
159
|
-
```js
|
|
160
|
-
const api = await slothlet({
|
|
161
|
-
dir: "./api",
|
|
162
|
-
mode: "lazy",
|
|
163
|
-
backgroundMaterialize: true
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
// Subscribe to completion event
|
|
167
|
-
api.slothlet.lifecycle.on("materialized:complete", (data) => {
|
|
168
|
-
console.log(`${data.total} modules materialized`);
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
// Or await all modules to be ready
|
|
172
|
-
await api.slothlet.materialize.wait();
|
|
173
|
-
|
|
174
|
-
// Or check current progress
|
|
175
|
-
const stats = api.slothlet.materialize.get();
|
|
176
|
-
// { total, materialized, remaining, percentage }
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
**Important**: Lazy mode hot reload intentionally restores modules to an unmaterialized state on reload (references are not preserved). Eager mode preserves existing references by merging into the live wrapper.
|
|
180
|
-
|
|
181
|
-
---
|
|
182
|
-
|
|
183
|
-
## 🎣 Hook System
|
|
184
|
-
|
|
185
|
-
Hooks intercept API function calls. They work across all modes. See [`docs/HOOKS.md`](docs/HOOKS.md) for the full reference.
|
|
186
|
-
|
|
187
|
-
### Hook Configuration
|
|
188
|
-
|
|
189
|
-
```js
|
|
190
|
-
// Simple enable (default pattern "**")
|
|
191
|
-
const api = await slothlet({ dir: "./api", hook: true });
|
|
192
|
-
|
|
193
|
-
// Enable with default pattern filter
|
|
194
|
-
const api = await slothlet({ dir: "./api", hook: "database.*" });
|
|
195
|
-
|
|
196
|
-
// Full configuration
|
|
197
|
-
const api = await slothlet({
|
|
198
|
-
dir: "./api",
|
|
199
|
-
hook: {
|
|
200
|
-
enabled: true,
|
|
201
|
-
pattern: "**",
|
|
202
|
-
suppressErrors: false // true = errors suppressed (returns undefined instead of throwing)
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
### Hook Types
|
|
208
|
-
|
|
209
|
-
- **`before`** - Executes before the function. Can modify arguments or short-circuit. **Must be synchronous.**
|
|
210
|
-
- **`after`** - Executes after successful completion. Can transform the return value.
|
|
211
|
-
- **`always`** - Read-only observer. Always executes (even on short-circuit). Return value ignored.
|
|
212
|
-
- **`error`** - Executes only when an error occurs. Receives error with source tracking.
|
|
213
|
-
|
|
214
|
-
### Basic Hook Usage
|
|
215
|
-
|
|
216
|
-
The `hook.on(typePattern, handler, options)` signature uses `"type:pattern"` as the first argument:
|
|
217
|
-
|
|
218
|
-
```js
|
|
219
|
-
// Before hook - modify arguments
|
|
220
|
-
api.slothlet.hook.on(
|
|
221
|
-
"before:math.add",
|
|
222
|
-
({ path, args, ctx }) => {
|
|
223
|
-
return [args[0] * 2, args[1] * 2]; // Return array to replace arguments
|
|
224
|
-
// Return any non-array non-undefined value to short-circuit (skip function)
|
|
225
|
-
// Return undefined to continue with original args
|
|
226
|
-
},
|
|
227
|
-
{ id: "double-args", priority: 100 }
|
|
228
|
-
);
|
|
229
|
-
|
|
230
|
-
// After hook - transform result
|
|
231
|
-
api.slothlet.hook.on(
|
|
232
|
-
"after:math.*",
|
|
233
|
-
({ path, args, result, ctx }) => {
|
|
234
|
-
return result * 10; // Return value to replace result; undefined = no change
|
|
235
|
-
},
|
|
236
|
-
{ id: "scale-result" }
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
// Always hook - observe (read-only)
|
|
240
|
-
api.slothlet.hook.on(
|
|
241
|
-
"always:**",
|
|
242
|
-
({ path, result, hasError, errors }) => {
|
|
243
|
-
if (hasError) console.error(`${path} failed:`, errors);
|
|
244
|
-
else console.log(`${path} returned:`, result);
|
|
245
|
-
// Return value is ignored
|
|
246
|
-
},
|
|
247
|
-
{ id: "logger" }
|
|
248
|
-
);
|
|
249
|
-
|
|
250
|
-
// Error hook - monitor failures
|
|
251
|
-
api.slothlet.hook.on(
|
|
252
|
-
"error:**",
|
|
253
|
-
({ path, error, source }) => {
|
|
254
|
-
// source.type: "before" | "after" | "always" | "function"
|
|
255
|
-
console.error(`Error in ${path} (from ${source.type}):`, error.message);
|
|
256
|
-
},
|
|
257
|
-
{ id: "error-monitor" }
|
|
258
|
-
);
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
### Pattern Matching
|
|
262
|
-
|
|
263
|
-
| Syntax | Description | Example |
|
|
264
|
-
|---|---|---|
|
|
265
|
-
| `exact.path` | Exact match | `"before:math.add"` |
|
|
266
|
-
| `namespace.*` | All functions in namespace | `"after:math.*"` |
|
|
267
|
-
| `*.funcName` | Function name across namespaces | `"always:*.add"` |
|
|
268
|
-
| `**` | All functions | `"error:**"` |
|
|
269
|
-
| `{a,b}` | Brace expansion | `"before:{math,utils}.*"` |
|
|
270
|
-
| `!pattern` | Negation | `"before:!internal.*"` |
|
|
271
|
-
|
|
272
|
-
### Hook Subsets
|
|
273
|
-
|
|
274
|
-
Each hook type has three ordered execution phases:
|
|
275
|
-
|
|
276
|
-
| Subset | Order | Typical use |
|
|
277
|
-
|---|---|---|
|
|
278
|
-
| `"before"` | First | Auth checks, security validation |
|
|
279
|
-
| `"primary"` | Middle (default) | Main hook logic |
|
|
280
|
-
| `"after"` | Last | Audit trails, cleanup |
|
|
281
|
-
|
|
282
|
-
```js
|
|
283
|
-
api.slothlet.hook.on(
|
|
284
|
-
"before:protected.*",
|
|
285
|
-
({ ctx }) => { if (!ctx.user) throw new Error("Unauthorized"); },
|
|
286
|
-
{ id: "auth", subset: "before", priority: 2000 }
|
|
287
|
-
);
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
### Hook Management
|
|
291
|
-
|
|
292
|
-
```js
|
|
293
|
-
// Remove by ID
|
|
294
|
-
api.slothlet.hook.remove({ id: "my-hook" });
|
|
295
|
-
api.slothlet.hook.off("my-hook"); // alias for remove
|
|
296
|
-
|
|
297
|
-
// Remove by filter
|
|
298
|
-
api.slothlet.hook.remove({ type: "before", pattern: "math.*" });
|
|
299
|
-
|
|
300
|
-
// Remove all
|
|
301
|
-
api.slothlet.hook.clear();
|
|
302
|
-
|
|
303
|
-
// List hooks
|
|
304
|
-
const all = api.slothlet.hook.list();
|
|
305
|
-
const active = api.slothlet.hook.list({ enabled: true });
|
|
306
|
-
|
|
307
|
-
// Enable / disable without unregistering
|
|
308
|
-
api.slothlet.hook.disable(); // disable all
|
|
309
|
-
api.slothlet.hook.disable({ pattern: "math.*" });
|
|
310
|
-
api.slothlet.hook.enable(); // re-enable all
|
|
311
|
-
api.slothlet.hook.enable({ type: "before" });
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
---
|
|
315
|
-
|
|
316
|
-
## 🔄 Per-Request Context
|
|
317
|
-
|
|
318
|
-
Execute functions with temporary merged context using `api.slothlet.context`:
|
|
319
|
-
|
|
320
|
-
```js
|
|
321
|
-
const api = await slothlet({
|
|
322
|
-
dir: "./api",
|
|
323
|
-
context: { appName: "MyApp", version: "3.0" }
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
// run() - execute a function inside a scoped context
|
|
327
|
-
await api.slothlet.context.run({ userId: "alice", role: "admin" }, async () => {
|
|
328
|
-
// Inside this scope: context = { appName, version, userId, role }
|
|
329
|
-
await api.database.query();
|
|
330
|
-
await api.audit.log();
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
// scope() - return a new API object with merged context
|
|
334
|
-
const scopedApi = api.slothlet.context.scope({ userId: "bob" });
|
|
335
|
-
await scopedApi.database.query(); // context includes userId: "bob"
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
### Deep Merge Strategy
|
|
339
|
-
|
|
340
|
-
```js
|
|
341
|
-
// Default: shallow merge (top-level properties replaced)
|
|
342
|
-
await api.slothlet.context.run({ newProp: "value" }, handler);
|
|
343
|
-
|
|
344
|
-
// Deep merge: nested objects recursively merged
|
|
345
|
-
await api.slothlet.context.run(
|
|
346
|
-
{ nested: { prop: "value" } },
|
|
347
|
-
handler,
|
|
348
|
-
{ mergeStrategy: "deep" }
|
|
349
|
-
);
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
### Automatic EventEmitter Context Propagation
|
|
353
|
-
|
|
354
|
-
Context propagates automatically through EventEmitter callbacks:
|
|
355
|
-
|
|
356
|
-
```js
|
|
357
|
-
import net from "net";
|
|
358
|
-
import { context } from "@cldmv/slothlet/runtime";
|
|
359
|
-
|
|
360
|
-
export const server = {
|
|
361
|
-
async start() {
|
|
362
|
-
const tcpServer = net.createServer((socket) => {
|
|
363
|
-
// Context automatically available in connection handler
|
|
364
|
-
console.log(`User ${context.userId} connected`);
|
|
365
|
-
|
|
366
|
-
socket.on("data", (data) => {
|
|
367
|
-
// Context preserved in nested event callbacks
|
|
368
|
-
console.log(`Data from ${context.userId}: ${data}`);
|
|
369
|
-
});
|
|
370
|
-
});
|
|
371
|
-
tcpServer.listen(3000);
|
|
372
|
-
}
|
|
373
|
-
};
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
Works with: TCP servers, HTTP servers, custom EventEmitters, unlimited nested callbacks.
|
|
377
|
-
|
|
378
|
-
> 📖 See [`docs/CONTEXT-PROPAGATION.md`](docs/CONTEXT-PROPAGATION.md) for full documentation.
|
|
379
|
-
|
|
380
|
-
---
|
|
381
|
-
|
|
382
|
-
## 🏷️ Metadata System
|
|
383
|
-
|
|
384
|
-
Tag API paths with metadata for authorization, auditing, and security. See [`docs/METADATA.md`](docs/METADATA.md) for the full reference.
|
|
385
|
-
|
|
386
|
-
```js
|
|
387
|
-
// Set metadata when loading (via api.slothlet.api.add)
|
|
388
|
-
await api.slothlet.api.add("plugins/trusted", "./trusted-dir", {
|
|
389
|
-
metadata: { trusted: true, securityLevel: "high" }
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
// Set metadata at runtime
|
|
393
|
-
api.slothlet.metadata.set("plugins.trusted.someFunc", { version: 2 });
|
|
394
|
-
api.slothlet.metadata.setGlobal({ environment: "production" });
|
|
395
|
-
api.slothlet.metadata.setFor("plugins/trusted", { owner: "core-team" });
|
|
396
|
-
|
|
397
|
-
// Read metadata inside a module
|
|
398
|
-
import { self } from "@cldmv/slothlet/runtime";
|
|
399
|
-
|
|
400
|
-
export const secureOperation = {
|
|
401
|
-
async execute() {
|
|
402
|
-
// Access metadata via api.slothlet.metadata from within a module via self
|
|
403
|
-
// Or read it externally:
|
|
404
|
-
// const meta = api.slothlet.metadata.get("plugins.trusted.execute");
|
|
405
|
-
return "Authorized execution";
|
|
406
|
-
}
|
|
407
|
-
};
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
---
|
|
411
|
-
|
|
412
|
-
## 🌍 Environment Snapshot (v3.1+)
|
|
413
|
-
|
|
414
|
-
Slothlet captures a **frozen snapshot of `process.env` at init time** and exposes it at `api.slothlet.env`. The snapshot is deeply read-only — mutating `process.env` after init does not affect `api.slothlet.env`.
|
|
415
|
-
|
|
416
|
-
```js
|
|
417
|
-
const api = await slothlet({
|
|
418
|
-
dir: "./api",
|
|
419
|
-
env: true,
|
|
420
|
-
// env: { include: ["NODE_ENV", "DATABASE_URL", "PORT"] } // allowlist
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
// Access inside any module:
|
|
424
|
-
import { self } from "@cldmv/slothlet/runtime";
|
|
425
|
-
|
|
426
|
-
export const getConfig = () => ({
|
|
427
|
-
mode: self.slothlet.env.NODE_ENV,
|
|
428
|
-
dbUrl: self.slothlet.env.DATABASE_URL
|
|
429
|
-
});
|
|
430
|
-
```
|
|
431
|
-
|
|
432
|
-
**Key behaviors:**
|
|
433
|
-
- `env: true` → all `process.env` variables are captured
|
|
434
|
-
- `env: { include: [...] }` → only the listed keys are captured (recommended for security)
|
|
435
|
-
- `api.slothlet.env` is a frozen object — writes throw in strict mode
|
|
436
|
-
- Snapshot is taken at init time — late `process.env` mutations are NOT reflected
|
|
437
|
-
|
|
438
|
-
---
|
|
439
|
-
|
|
440
|
-
## 🔁 Hot Reload / Dynamic API Management
|
|
441
|
-
|
|
442
|
-
```js
|
|
443
|
-
// Add new modules at runtime
|
|
444
|
-
await api.slothlet.api.add("newModule", "./new-module-path");
|
|
445
|
-
await api.slothlet.api.add("plugins", "./plugins", { collision: "merge" });
|
|
446
|
-
|
|
447
|
-
// Remove modules by path
|
|
448
|
-
await api.slothlet.api.remove("oldModule");
|
|
449
|
-
|
|
450
|
-
// Reload all modules
|
|
451
|
-
await api.slothlet.reload();
|
|
452
|
-
|
|
453
|
-
// Reload specific API path
|
|
454
|
-
await api.slothlet.api.reload("database.*");
|
|
455
|
-
await api.slothlet.api.reload("plugins.auth");
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
> **Lazy mode reload behavior**: In lazy mode, reload restores modules to an unmaterialized proxy state - existing references to lazy wrappers are intentionally not preserved. Eager mode merges new module exports into the existing live wrapper, preserving references.
|
|
459
|
-
|
|
460
|
-
> 📖 See [`docs/RELOAD.md`](docs/RELOAD.md) for reload system documentation.
|
|
461
|
-
|
|
462
|
-
---
|
|
463
|
-
|
|
464
|
-
## ⚡ Lifecycle Events
|
|
465
|
-
|
|
466
|
-
Subscribe to internal API events via `api.slothlet.lifecycle`:
|
|
467
|
-
|
|
468
|
-
```js
|
|
469
|
-
// Available events
|
|
470
|
-
api.slothlet.lifecycle.on("materialized:complete", (data) => {
|
|
471
|
-
console.log(`${data.total} modules materialized`);
|
|
472
|
-
});
|
|
473
|
-
|
|
474
|
-
api.slothlet.lifecycle.on("impl:changed", (data) => {
|
|
475
|
-
console.log(`Module at ${data.apiPath} was reloaded`);
|
|
476
|
-
});
|
|
477
|
-
|
|
478
|
-
// Unsubscribe
|
|
479
|
-
const handler = (data) => console.log(data);
|
|
480
|
-
api.slothlet.lifecycle.on("materialized:complete", handler);
|
|
481
|
-
api.slothlet.lifecycle.off("materialized:complete", handler);
|
|
482
|
-
```
|
|
483
|
-
|
|
484
|
-
**Available events**: `"materialized:complete"`, `"impl:created"`, `"impl:changed"`, `"impl:removed"`
|
|
485
|
-
|
|
486
|
-
---
|
|
487
|
-
|
|
488
|
-
## 🔀 API Path Versioning (v3.2+)
|
|
489
|
-
|
|
490
|
-
Mount multiple versions of the same logical path and dispatch to the correct version automatically based on the caller's version metadata.
|
|
491
|
-
|
|
492
|
-
### Setup
|
|
493
|
-
|
|
494
|
-
```js
|
|
495
|
-
const api = await slothlet({
|
|
496
|
-
dir: "./api",
|
|
497
|
-
versionDispatcher: "version" // use caller's versionMetadata.version field
|
|
498
|
-
// versionDispatcher: (allVersions, caller) => { ... } // custom function
|
|
499
|
-
});
|
|
500
|
-
|
|
501
|
-
// Register versioned modules — 4th argument is versionConfig
|
|
502
|
-
await api.slothlet.api.add("auth", "./api/v1", {}, { version: "v1", default: true });
|
|
503
|
-
await api.slothlet.api.add("auth", "./api/v2", {}, { version: "v2" });
|
|
504
|
-
```
|
|
505
|
-
|
|
506
|
-
### Access Patterns
|
|
507
|
-
|
|
508
|
-
```js
|
|
509
|
-
// Dispatcher — routes via discriminator (use this in most cases)
|
|
510
|
-
api.auth.login(user, pass) // → routes to v1 or v2 based on caller metadata
|
|
511
|
-
|
|
512
|
-
// Direct versioned access — bypasses dispatcher entirely
|
|
513
|
-
api.v1.auth.login(user, pass) // → always v1
|
|
514
|
-
api.v2.auth.login(user, pass) // → always v2
|
|
515
|
-
```
|
|
516
|
-
|
|
517
|
-
### Attaching Version Metadata to a Caller
|
|
518
|
-
|
|
519
|
-
```js
|
|
520
|
-
// Register a module WITH a version tag so the discriminator can use it
|
|
521
|
-
await api.slothlet.api.add("services/payments", "./payments", {}, {
|
|
522
|
-
version: "v2",
|
|
523
|
-
metadata: { stable: true } // versionConfig.metadata — stored in VersionManager only
|
|
524
|
-
});
|
|
525
|
-
|
|
526
|
-
// options.metadata (3rd arg) → regular Metadata system (metadata.caller() etc.)
|
|
527
|
-
// versionConfig.metadata (4th arg) → version-system only, used by the discriminator
|
|
528
|
-
```
|
|
529
|
-
|
|
530
|
-
### Runtime Version Management
|
|
531
|
-
|
|
532
|
-
```js
|
|
533
|
-
// List registered versions for a path
|
|
534
|
-
api.slothlet.versioning.list("auth");
|
|
535
|
-
// → { versions: { v1: { ... }, v2: { ... } }, default: "v2" }
|
|
536
|
-
|
|
537
|
-
// Change the default dispatcher fallback
|
|
538
|
-
api.slothlet.versioning.setDefault("auth", "v1");
|
|
539
|
-
|
|
540
|
-
// Unregister a version (removes api.v1.auth; dispatcher updates automatically)
|
|
541
|
-
await api.slothlet.versioning.unregister("auth", "v1");
|
|
542
|
-
|
|
543
|
-
// Read version metadata stored at registration
|
|
544
|
-
api.slothlet.versioning.getVersionMetadata(moduleID);
|
|
545
|
-
```
|
|
546
|
-
|
|
547
|
-
> 📖 See [`docs/VERSIONING.md`](docs/VERSIONING.md) for full documentation.
|
|
548
|
-
|
|
549
|
-
---
|
|
550
|
-
|
|
551
|
-
## 📁 File Organization Best Practices
|
|
552
|
-
|
|
553
|
-
### ✅ Clean Folder Structure
|
|
554
|
-
|
|
555
|
-
```text
|
|
556
|
-
api/
|
|
557
|
-
├── config.mjs → api.config.*
|
|
558
|
-
├── math/
|
|
559
|
-
│ └── math.mjs → api.math.* (flattened - filename matches folder)
|
|
560
|
-
├── util/
|
|
561
|
-
│ ├── util.mjs → api.util.* (flattened methods)
|
|
562
|
-
│ ├── extract.mjs → api.util.extract.*
|
|
563
|
-
│ └── controller.mjs → api.util.controller.*
|
|
564
|
-
├── nested/
|
|
565
|
-
│ └── date/
|
|
566
|
-
│ └── date.mjs → api.nested.date.*
|
|
567
|
-
└── multi/
|
|
568
|
-
├── alpha.mjs → api.multi.alpha.*
|
|
569
|
-
└── beta.mjs → api.multi.beta.*
|
|
570
|
-
```
|
|
571
|
-
|
|
572
|
-
### ✅ Naming Conventions
|
|
573
|
-
|
|
574
|
-
- **Filename matches folder** → Auto-flattening (`math/math.mjs` → `api.math.*`)
|
|
575
|
-
- **Different filename** → Nested structure preserved
|
|
576
|
-
- **Dash-separated names** → camelCase API (`auto-ip.mjs` → `api.autoIP`)
|
|
577
|
-
- **Function name preferred** → Original capitalization kept over sanitized form
|
|
578
|
-
(see [Rule 9](docs/API-RULES.md))
|
|
579
|
-
|
|
580
|
-
---
|
|
581
|
-
|
|
582
|
-
## 🚨 Common AI Agent Mistakes
|
|
583
|
-
|
|
584
|
-
### ❌ Mistake 1: Cross-Module Imports
|
|
585
|
-
|
|
586
|
-
```js
|
|
587
|
-
// ❌ WRONG
|
|
588
|
-
import { config } from "./config.mjs";
|
|
589
|
-
// ✅ CORRECT
|
|
590
|
-
import { self } from "@cldmv/slothlet/runtime";
|
|
591
|
-
// then: self.config.get(...)
|
|
592
|
-
```
|
|
593
|
-
|
|
594
|
-
### ❌ Mistake 2: Using V2 API Surface
|
|
595
|
-
|
|
596
|
-
```js
|
|
597
|
-
// ❌ WRONG (v2 API - does not exist in v3)
|
|
598
|
-
await api.addApi("plugins", "./dir");
|
|
599
|
-
await api.reloadApi("math.*");
|
|
600
|
-
api.hooks.on("validate", "before", handler, { pattern: "math.*" });
|
|
601
|
-
await api.run({ userId: "alice" }, fn);
|
|
602
|
-
|
|
603
|
-
// ✅ CORRECT (v3 API)
|
|
604
|
-
await api.slothlet.api.add("plugins", "./dir");
|
|
605
|
-
await api.slothlet.api.reload("math.*");
|
|
606
|
-
api.slothlet.hook.on("before:math.*", handler);
|
|
607
|
-
await api.slothlet.context.run({ userId: "alice" }, fn);
|
|
608
|
-
```
|
|
609
|
-
|
|
610
|
-
### ❌ Mistake 3: Wrong Hook Config Key
|
|
611
|
-
|
|
612
|
-
```js
|
|
613
|
-
// ❌ WRONG
|
|
614
|
-
const api = await slothlet({ dir: "./api", hooks: true }); // "hooks" plural
|
|
615
|
-
|
|
616
|
-
// ✅ CORRECT
|
|
617
|
-
const api = await slothlet({ dir: "./api", hook: true }); // "hook" singular
|
|
618
|
-
```
|
|
619
|
-
|
|
620
|
-
### ❌ Mistake 4: Breaking Auto-Flattening
|
|
621
|
-
|
|
622
|
-
```js
|
|
623
|
-
// File: math/calculator.mjs (different name from folder)
|
|
624
|
-
export const math = { /* methods */ };
|
|
625
|
-
// Result: api.math.calculator.math.* ← extra nesting, not flattened
|
|
626
|
-
|
|
627
|
-
// ✅ CORRECT: File math/math.mjs
|
|
628
|
-
export const math = { /* methods */ };
|
|
629
|
-
// Result: api.math.* ← flattened
|
|
630
|
-
```
|
|
631
|
-
|
|
632
|
-
### ❌ Mistake 5: Using lifecycle.subscribe / lifecycle.emit
|
|
633
|
-
|
|
634
|
-
```js
|
|
635
|
-
// ❌ WRONG - subscribe/emit are internal
|
|
636
|
-
api.slothlet.lifecycle.subscribe("materialized:complete", handler);
|
|
637
|
-
api.slothlet.lifecycle.emit("impl:changed", data);
|
|
638
|
-
|
|
639
|
-
// ✅ CORRECT - public surface is on/off only
|
|
640
|
-
api.slothlet.lifecycle.on("materialized:complete", handler);
|
|
641
|
-
api.slothlet.lifecycle.off("materialized:complete", handler);
|
|
642
|
-
```
|
|
643
|
-
|
|
644
|
-
### ❌ Mistake 6: Assuming `api.v1.auth` Goes Through the Dispatcher
|
|
645
|
-
|
|
646
|
-
```js
|
|
647
|
-
// ❌ WRONG — direct versioned path bypasses the discriminator entirely
|
|
648
|
-
api.v1.auth.login(user, pass); // always v1, no routing logic
|
|
649
|
-
|
|
650
|
-
// ✅ CORRECT — use the logical dispatcher path for dynamic routing
|
|
651
|
-
api.auth.login(user, pass); // routes based on caller version metadata
|
|
652
|
-
```
|
|
653
|
-
|
|
654
|
-
### ❌ Mistake 7: Wrong Config Key for Versioning
|
|
655
|
-
|
|
656
|
-
```js
|
|
657
|
-
// ❌ WRONG
|
|
658
|
-
const api = await slothlet({ dir: "./api", versionResolver: "version" });
|
|
659
|
-
|
|
660
|
-
// ✅ CORRECT
|
|
661
|
-
const api = await slothlet({ dir: "./api", versionDispatcher: "version" });
|
|
662
|
-
```
|
|
663
|
-
|
|
664
|
-
### ❌ Mistake 8: Conflating versionConfig.metadata with options.metadata
|
|
665
|
-
|
|
666
|
-
```js
|
|
667
|
-
// ❌ WRONG — puts version tag in the regular Metadata system instead of VersionManager
|
|
668
|
-
await api.slothlet.api.add("auth", "./v2", { metadata: { version: "v2" } });
|
|
669
|
-
|
|
670
|
-
// ✅ CORRECT
|
|
671
|
-
// options.metadata (3rd arg) → regular Metadata system (metadata.caller() etc.)
|
|
672
|
-
// versionConfig.metadata (4th arg) → VersionManager only, used by the discriminator
|
|
673
|
-
await api.slothlet.api.add("auth", "./v2",
|
|
674
|
-
{ metadata: { role: "core" } },
|
|
675
|
-
{ version: "v2", metadata: { stable: true } }
|
|
676
|
-
);
|
|
677
|
-
```
|
|
678
|
-
|
|
679
|
-
---
|
|
680
|
-
|
|
681
|
-
## ✅ AI Agent Checklist
|
|
682
|
-
|
|
683
|
-
- [ ] **No cross-module imports** - use `self` from `@cldmv/slothlet/runtime` instead
|
|
684
|
-
- [ ] **Match filename to folder** for cleaner APIs (auto-flattening)
|
|
685
|
-
- [ ] **Hook config key is `hook:` (singular)**, not `hooks:`
|
|
686
|
-
- [ ] **Hook API** is `api.slothlet.hook.*`, not `api.hooks.*`
|
|
687
|
-
- [ ] **Context API** is `api.slothlet.context.run/scope()`, not `api.run/scope()`
|
|
688
|
-
- [ ] **Reload/add/remove** is `api.slothlet.api.add/remove/reload()`, not `api.addApi()` etc.
|
|
689
|
-
- [ ] **Lifecycle** uses `api.slothlet.lifecycle.on/off()` only
|
|
690
|
-
- [ ] **Lazy mode**: if using background materialization, use `api.slothlet.materialize.wait()` before accessing the API
|
|
691
|
-
- [ ] **Hook subsets**: auth/security → `subset: "before"`, main logic → `"primary"`, audit → `"after"`
|
|
692
|
-
- [ ] **Versioning config key is `versionDispatcher:`**, not `versionResolver:` or `versionDiscriminator:`
|
|
693
|
-
- [ ] **Use `api.auth` (dispatcher path) for dynamic routing**, not `api.v1.auth` (direct path bypasses discriminator)
|
|
694
|
-
- [ ] **`versionConfig.metadata` (4th arg)** and **`options.metadata` (3rd arg)** are separate systems — don't conflate them
|
|
695
|
-
- [ ] **Double quotes everywhere** - follow Slothlet coding standards
|
|
696
|
-
|
|
697
|
-
---
|
|
698
|
-
|
|
699
|
-
## 📚 Reference Examples
|
|
700
|
-
|
|
701
|
-
- **Auto-flattening**: `api_tests/api_test/math/math.mjs`
|
|
702
|
-
- **Multi-file folders**: `api_tests/api_test/multi/`
|
|
703
|
-
- **Cross-module calls**: `api_tests/api_test_mixed/`
|
|
704
|
-
- **Root-level APIs**: `api_tests/api_test/root-function.mjs`
|
|
705
|
-
- **Nested structures**: `api_tests/api_test/nested/date/`
|
|
706
|
-
|
|
707
|
-
---
|
|
708
|
-
|
|
709
|
-
## 📖 Essential Documentation
|
|
710
|
-
|
|
711
|
-
### Core Architecture
|
|
712
|
-
|
|
713
|
-
- **[`docs/API-RULES.md`](docs/API-RULES.md)** - All 13 API transformation rules
|
|
714
|
-
- **[`docs/API-RULES/API-RULES-CONDITIONS.md`](docs/API-RULES/API-RULES-CONDITIONS.md)** - All C01–C34 conditional logic
|
|
715
|
-
- **[`docs/API-RULES/API-FLATTENING.md`](docs/API-RULES/API-FLATTENING.md)** - Flattening rules F01–F08
|
|
716
|
-
|
|
717
|
-
### Configuration & Features
|
|
718
|
-
|
|
719
|
-
- **[`docs/CONFIGURATION.md`](docs/CONFIGURATION.md)** - All config options
|
|
720
|
-
- **[`docs/HOOKS.md`](docs/HOOKS.md)** - Hook system (types, subsets, patterns, management)
|
|
721
|
-
- **[`docs/METADATA.md`](docs/METADATA.md)** - Metadata system
|
|
722
|
-
- **[`docs/CONTEXT-PROPAGATION.md`](docs/CONTEXT-PROPAGATION.md)** - Per-request context and EventEmitter propagation
|
|
723
|
-
- **[`docs/RELOAD.md`](docs/RELOAD.md)** - Hot reload and dynamic API management
|
|
724
|
-
- **[`docs/LIFECYCLE.md`](docs/LIFECYCLE.md)** - Lazy mode, materialization, and lifecycle events
|
|
725
|
-
- **[`docs/SANITIZATION.md`](docs/SANITIZATION.md)** - Property name sanitization rules
|
|
726
|
-
- **[`docs/I18N.md`](docs/I18N.md)** - Internationalization and language support
|
|
727
|
-
- **[`docs/PERFORMANCE.md`](docs/PERFORMANCE.md)** - Performance characteristics and benchmarks
|
|
728
|
-
|
|
729
|
-
### Critical Reading Order for AI Agents
|
|
730
|
-
|
|
731
|
-
1. **This file** - Prevents architectural mistakes
|
|
732
|
-
2. **[`README.md`](README.md)** - Project overview and quickstart
|
|
733
|
-
3. **[`docs/API-RULES.md`](docs/API-RULES.md)** - API transformation rules
|
|
734
|
-
4. **[`docs/HOOKS.md`](docs/HOOKS.md)** - Hook system (if needed)
|
|
735
|
-
5. **[`docs/METADATA.md`](docs/METADATA.md)** - Metadata system (if needed)
|
|
736
|
-
6. **[`api_tests/api_test/README.md`](api_tests/api_test/README.md)** - Live examples
|