@cldmv/slothlet 3.3.0 → 3.4.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 (139) hide show
  1. package/README.md +9 -10
  2. package/REFERENCE.md +23 -0
  3. package/dist/lib/builders/api-assignment.mjs +1 -589
  4. package/dist/lib/builders/api_builder.mjs +1 -1385
  5. package/dist/lib/builders/builder.mjs +1 -78
  6. package/dist/lib/builders/modes-processor.mjs +1 -1800
  7. package/dist/lib/errors.mjs +9 -211
  8. package/dist/lib/factories/component-base.mjs +1 -80
  9. package/dist/lib/factories/context.mjs +1 -22
  10. package/dist/lib/handlers/api-cache-manager.mjs +1 -200
  11. package/dist/lib/handlers/api-manager.mjs +1 -2536
  12. package/dist/lib/handlers/context-async.mjs +1 -172
  13. package/dist/lib/handlers/context-live.mjs +1 -173
  14. package/dist/lib/handlers/hook-manager.mjs +1 -667
  15. package/dist/lib/handlers/lifecycle-token.mjs +1 -28
  16. package/dist/lib/handlers/lifecycle.mjs +1 -115
  17. package/dist/lib/handlers/materialize-manager.mjs +1 -48
  18. package/dist/lib/handlers/metadata.mjs +1 -501
  19. package/dist/lib/handlers/ownership.mjs +1 -322
  20. package/dist/lib/handlers/permission-manager.mjs +1 -392
  21. package/dist/lib/handlers/unified-wrapper.mjs +1 -3110
  22. package/dist/lib/handlers/version-manager.mjs +1 -885
  23. package/dist/lib/helpers/class-instance-wrapper.mjs +1 -109
  24. package/dist/lib/helpers/config.mjs +1 -439
  25. package/dist/lib/helpers/eventemitter-context.mjs +1 -349
  26. package/dist/lib/helpers/hint-detector.mjs +1 -47
  27. package/dist/lib/helpers/modes-utils.mjs +1 -37
  28. package/dist/lib/helpers/pattern-matcher.mjs +1 -125
  29. package/dist/lib/helpers/resolve-from-caller.mjs +1 -169
  30. package/dist/lib/helpers/sanitize.mjs +1 -340
  31. package/dist/lib/helpers/utilities.mjs +1 -70
  32. package/dist/lib/i18n/languages/de-de.json +1 -0
  33. package/dist/lib/i18n/languages/en-gb.json +1 -0
  34. package/dist/lib/i18n/languages/en-us.json +1 -0
  35. package/dist/lib/i18n/languages/es-es.json +412 -0
  36. package/dist/lib/i18n/languages/es-mx.json +1 -0
  37. package/dist/lib/i18n/languages/fr-fr.json +1 -0
  38. package/dist/lib/i18n/languages/hi-in.json +2 -1
  39. package/dist/lib/i18n/languages/ja-jp.json +1 -0
  40. package/dist/lib/i18n/languages/ko-kr.json +1 -0
  41. package/dist/lib/i18n/languages/pt-br.json +21 -20
  42. package/dist/lib/i18n/languages/ru-ru.json +2 -1
  43. package/dist/lib/i18n/languages/zh-cn.json +6 -5
  44. package/dist/lib/i18n/translations.mjs +1 -126
  45. package/dist/lib/modes/eager.mjs +1 -59
  46. package/dist/lib/modes/lazy.mjs +1 -81
  47. package/dist/lib/processors/flatten.mjs +1 -437
  48. package/dist/lib/processors/loader.mjs +1 -339
  49. package/dist/lib/processors/type-generator.mjs +1 -275
  50. package/dist/lib/processors/typescript.mjs +1 -172
  51. package/dist/lib/runtime/runtime-asynclocalstorage.mjs +1 -113
  52. package/dist/lib/runtime/runtime-livebindings.mjs +1 -78
  53. package/dist/lib/runtime/runtime.mjs +1 -102
  54. package/dist/slothlet.mjs +1 -817
  55. package/package.json +35 -31
  56. package/types/dist/lib/builders/api-assignment.d.mts +3 -92
  57. package/types/dist/lib/builders/api-assignment.d.mts.map +1 -1
  58. package/types/dist/lib/builders/api_builder.d.mts +102 -91
  59. package/types/dist/lib/builders/api_builder.d.mts.map +1 -1
  60. package/types/dist/lib/builders/builder.d.mts +1 -55
  61. package/types/dist/lib/builders/builder.d.mts.map +1 -1
  62. package/types/dist/lib/builders/modes-processor.d.mts +3 -27
  63. package/types/dist/lib/builders/modes-processor.d.mts.map +1 -1
  64. package/types/dist/lib/errors.d.mts +19 -109
  65. package/types/dist/lib/errors.d.mts.map +1 -1
  66. package/types/dist/lib/factories/component-base.d.mts +7 -177
  67. package/types/dist/lib/factories/component-base.d.mts.map +1 -1
  68. package/types/dist/lib/factories/context.d.mts +4 -22
  69. package/types/dist/lib/factories/context.d.mts.map +1 -1
  70. package/types/dist/lib/handlers/api-cache-manager.d.mts +20 -203
  71. package/types/dist/lib/handlers/api-cache-manager.d.mts.map +1 -1
  72. package/types/dist/lib/handlers/api-manager.d.mts +34 -408
  73. package/types/dist/lib/handlers/api-manager.d.mts.map +1 -1
  74. package/types/dist/lib/handlers/context-async.d.mts +23 -61
  75. package/types/dist/lib/handlers/context-async.d.mts.map +1 -1
  76. package/types/dist/lib/handlers/context-live.d.mts +22 -59
  77. package/types/dist/lib/handlers/context-live.d.mts.map +1 -1
  78. package/types/dist/lib/handlers/hook-manager.d.mts +46 -185
  79. package/types/dist/lib/handlers/hook-manager.d.mts.map +1 -1
  80. package/types/dist/lib/handlers/lifecycle-token.d.mts +3 -48
  81. package/types/dist/lib/handlers/lifecycle-token.d.mts.map +1 -1
  82. package/types/dist/lib/handlers/lifecycle.d.mts +5 -82
  83. package/types/dist/lib/handlers/lifecycle.d.mts.map +1 -1
  84. package/types/dist/lib/handlers/materialize-manager.d.mts +8 -70
  85. package/types/dist/lib/handlers/materialize-manager.d.mts.map +1 -1
  86. package/types/dist/lib/handlers/metadata.d.mts +17 -221
  87. package/types/dist/lib/handlers/metadata.d.mts.map +1 -1
  88. package/types/dist/lib/handlers/ownership.d.mts +44 -160
  89. package/types/dist/lib/handlers/ownership.d.mts.map +1 -1
  90. package/types/dist/lib/handlers/permission-manager.d.mts +40 -141
  91. package/types/dist/lib/handlers/permission-manager.d.mts.map +1 -1
  92. package/types/dist/lib/handlers/unified-wrapper.d.mts +26 -239
  93. package/types/dist/lib/handlers/unified-wrapper.d.mts.map +1 -1
  94. package/types/dist/lib/handlers/version-manager.d.mts +28 -225
  95. package/types/dist/lib/handlers/version-manager.d.mts.map +1 -1
  96. package/types/dist/lib/helpers/class-instance-wrapper.d.mts +2 -52
  97. package/types/dist/lib/helpers/class-instance-wrapper.d.mts.map +1 -1
  98. package/types/dist/lib/helpers/config.d.mts +125 -139
  99. package/types/dist/lib/helpers/config.d.mts.map +1 -1
  100. package/types/dist/lib/helpers/eventemitter-context.d.mts +3 -29
  101. package/types/dist/lib/helpers/eventemitter-context.d.mts.map +1 -1
  102. package/types/dist/lib/helpers/hint-detector.d.mts +2 -15
  103. package/types/dist/lib/helpers/hint-detector.d.mts.map +1 -1
  104. package/types/dist/lib/helpers/modes-utils.d.mts +3 -30
  105. package/types/dist/lib/helpers/modes-utils.d.mts.map +1 -1
  106. package/types/dist/lib/helpers/pattern-matcher.d.mts +3 -43
  107. package/types/dist/lib/helpers/pattern-matcher.d.mts.map +1 -1
  108. package/types/dist/lib/helpers/resolve-from-caller.d.mts +3 -27
  109. package/types/dist/lib/helpers/resolve-from-caller.d.mts.map +1 -1
  110. package/types/dist/lib/helpers/sanitize.d.mts +4 -92
  111. package/types/dist/lib/helpers/sanitize.d.mts.map +1 -1
  112. package/types/dist/lib/helpers/utilities.d.mts +4 -52
  113. package/types/dist/lib/helpers/utilities.d.mts.map +1 -1
  114. package/types/dist/lib/i18n/translations.d.mts +4 -37
  115. package/types/dist/lib/i18n/translations.d.mts.map +1 -1
  116. package/types/dist/lib/modes/eager.d.mts +8 -30
  117. package/types/dist/lib/modes/eager.d.mts.map +1 -1
  118. package/types/dist/lib/modes/lazy.d.mts +10 -43
  119. package/types/dist/lib/modes/lazy.d.mts.map +1 -1
  120. package/types/dist/lib/processors/flatten.d.mts +56 -107
  121. package/types/dist/lib/processors/flatten.d.mts.map +1 -1
  122. package/types/dist/lib/processors/loader.d.mts +6 -41
  123. package/types/dist/lib/processors/loader.d.mts.map +1 -1
  124. package/types/dist/lib/processors/type-generator.d.mts +2 -16
  125. package/types/dist/lib/processors/type-generator.d.mts.map +1 -1
  126. package/types/dist/lib/processors/typescript.d.mts +6 -53
  127. package/types/dist/lib/processors/typescript.d.mts.map +1 -1
  128. package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts +3 -71
  129. package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts.map +1 -1
  130. package/types/dist/lib/runtime/runtime-livebindings.d.mts +2 -37
  131. package/types/dist/lib/runtime/runtime-livebindings.d.mts.map +1 -1
  132. package/types/dist/lib/runtime/runtime.d.mts +3 -39
  133. package/types/dist/lib/runtime/runtime.d.mts.map +1 -1
  134. package/types/dist/slothlet.d.mts +3 -249
  135. package/types/dist/slothlet.d.mts.map +1 -1
  136. package/types/index.d.mts +36 -16
  137. package/types/index.d.mts.map +1 -0
  138. package/AGENT-USAGE.md +0 -736
  139. package/docs/API-RULES.md +0 -712
package/docs/API-RULES.md DELETED
@@ -1,712 +0,0 @@
1
- # Slothlet API Rules
2
-
3
- **Complete Guide to All API Generation Behaviors**
4
-
5
- ---
6
-
7
- ## Document Hierarchy
8
-
9
- This is the **middle layer** of slothlet's three-tier documentation system:
10
-
11
- ```text
12
- 📋 API-RULES/API-FLATTENING.md (F##) ← User Guide: Clear examples and flowcharts
13
- ↑ links to ↓ links to
14
- 📊 API-RULES.md (1-13) ← YOU ARE HERE: Complete behavior catalog
15
- ↑ links to ↓ links to
16
- 🔧 API-RULES/API-RULES-CONDITIONS.md ← Technical: Exact source code locations
17
- ↓ mapped in
18
- 🗺️ API-RULES/API-RULE-MAPPING.md ← Traceability Matrix: Rule # ↔ F## ↔ C##
19
- ```
20
-
21
- **Cross-Reference Navigation:**
22
-
23
- - **For Users**: See [API-RULES/API-FLATTENING.md](API-RULES/API-FLATTENING.md) for user-friendly explanations with examples
24
- - **For Developers**: See [API-RULES/API-RULES-CONDITIONS.md](API-RULES/API-RULES-CONDITIONS.md) for exact source code locations
25
- - **Rule Mapping**: See [API-RULES/API-RULE-MAPPING.md](API-RULES/API-RULE-MAPPING.md) for complete Rule # ↔ F## ↔ C## traceability matrix
26
-
27
- ---
28
-
29
- ## Overview
30
-
31
- This document catalogs **all 13 API generation behaviors** in slothlet with:
32
-
33
- - Verified examples from actual test files with source attribution
34
- - Cross-references to user guide (F##) and technical details (C##)
35
- - Source code locations with function names and file references
36
- - Test file sources demonstrating each behavior in action
37
- - Processing contexts (Root/Subfolder/Multi-Default/AddApi)
38
-
39
- **Why 13 Rules vs Flattening Patterns?**
40
-
41
- The [Flattening guide](API-RULES/API-FLATTENING.md) focuses on **when content gets promoted/flattened**. This comprehensive guide covers **all API behaviors** including cases where flattening doesn't occur but specific handling is still needed:
42
-
43
- - **Flattening Rules** (1, 7, 8, 10, 11, 13): Core flattening patterns
44
- - **Non-Flattening Rules** (2, 3, 4, 5, 6, 9): Export collection, function naming, empty modules, mixed exports
45
- - **AddApi Rules** (11, 12, 13): Runtime API extension behaviors
46
-
47
- **Methodology**: Each rule has been systematically verified against test files and source code.
48
-
49
- ---
50
-
51
- ## Rule Categories
52
-
53
- | Category | Rules | Focus | Cross-References |
54
- | --------------------- | ------------ | --------------------------- | ---------------- |
55
- | **Basic Flattening** | 1, 7, 8 | Core flattening patterns | [F01-F05](API-RULES/API-FLATTENING.md) → [C01-C11](API-RULES/API-RULES-CONDITIONS.md) |
56
- | **Export Handling** | 2, 4, 5 | Default vs Named exports | [F04-F05](API-RULES/API-FLATTENING.md) → [C08-C21](API-RULES/API-RULES-CONDITIONS.md) |
57
- | **Special Cases** | 3, 6, 9, 10 | Edge cases and protections | [C10, C01, C16-C19](API-RULES/API-RULES-CONDITIONS.md) |
58
- | **AddApi Extensions** | 11, 12, 13 | Runtime API extensions | [F06-F08](API-RULES/API-FLATTENING.md) → [C33, C34](API-RULES/API-RULES-CONDITIONS.md) |
59
-
60
- ---
61
-
62
- ## Table of Contents
63
-
64
- 1. [Rule 1: Filename Matches Container Flattening](#rule-1-filename-matches-container-flattening)
65
- 2. [Rule 2: Named-Only Export Collection](#rule-2-named-only-export-collection)
66
- 3. [Rule 3: Empty Module Handling](#rule-3-empty-module-handling)
67
- 4. [Rule 4: Named Export with Function Name Preservation](#rule-4-named-export-with-function-name-preservation)
68
- 5. [Rule 5: Multiple Module Default Export Handling](#rule-5-multiple-module-default-export-handling)
69
- 6. [Rule 6: Multiple Module Mixed Exports](#rule-6-multiple-module-mixed-exports)
70
- 7. [Rule 7: Single Module Named Export Flattening](#rule-7-single-module-named-export-flattening)
71
- 8. [Rule 8: Single Module Default Export Promotion](#rule-8-single-module-default-export-promotion)
72
- 9. [Rule 9: Function Name Preference Over Sanitization](#rule-9-function-name-preference-over-sanitization)
73
- 10. [Rule 10: Generic Filename Parent-Level Promotion](#rule-10-generic-filename-parent-level-promotion)
74
- 11. [Rule 11: AddApi Special File Pattern](#rule-11-addapi-special-file-pattern)
75
- 12. [Rule 12: Module Ownership and Selective API Overwriting](#rule-12-module-ownership-and-selective-api-overwriting)
76
- 13. [Rule 13: AddApi Path Deduplication Flattening](#rule-13-addapi-path-deduplication-flattening)
77
- 14. [Verification Status](#verification-status)
78
- 15. [Cross-Reference Index](#cross-reference-index)
79
-
80
- ---
81
-
82
- ## Rule 1: Filename Matches Container Flattening
83
-
84
- **Category**: Basic Flattening
85
- **Status**: ✅ Verified (`api_tests/api_test`)
86
- **User Guide**: [F01](API-RULES/API-FLATTENING.md#f01-folder-file-name-matching)
87
- **Technical**: [C05, C09b](API-RULES/API-RULES-CONDITIONS.md#c05)
88
-
89
- **Condition**: Filename matches folder name AND no default export AND has named exports
90
- **Source Files**: `api_tests/api_test/math/math.mjs`
91
- **Implementation**: `buildCategoryDecisions()` → `getFlatteningDecision()` → `processModuleForAPI()`
92
-
93
- **Verified Examples**:
94
-
95
- ```javascript
96
- // File: api_tests/api_test/math/math.mjs
97
- export function add(a, b) {
98
- return a + b;
99
- }
100
- export function subtract(a, b) {
101
- return a - b;
102
- }
103
-
104
- // Without Rule 1: api.math.math.add(2, 3) ❌ (redundant nesting)
105
- // With Rule 1: api.math.add(2, 3) ✅ (clean flattening)
106
- api.math.add(2, 3); // 5
107
- api.math.subtract(5, 2); // 3
108
- ```
109
-
110
- **Technical Implementation**:
111
-
112
- - **Primary Condition**: [C05](API-RULES/API-RULES-CONDITIONS.md#c05) - `fileName === categoryName && !moduleHasDefault && moduleKeys.length > 0`
113
- - **Processing**: [C09b](API-RULES/API-RULES-CONDITIONS.md#c09b) - `flattenToCategory: true` → category-level flattening
114
-
115
- ```javascript
116
- // C05: Filename Matches Container (Category-Level Flatten)
117
- // Location: src/lib/helpers/api_builder/decisions.mjs
118
- if (categoryName && fileName === categoryName && !moduleHasDefault && moduleKeys.length > 0) {
119
- return {
120
- shouldFlatten: true,
121
- flattenToRoot: false,
122
- flattenToCategory: true,
123
- preserveAsNamespace: false,
124
- useAutoFlattening: false,
125
- reason: "filename matches container, flatten to category"
126
- };
127
- }
128
- ```
129
-
130
- **Processing Path**: Subfolder processing via `getFlatteningDecision()` (currentDepth > 0)
131
- **Source Code Location**: `src/lib/helpers/api_builder/decisions.mjs` - `getFlatteningDecision()`
132
-
133
- ---
134
-
135
- ## Rule 2: Named-Only Export Collection
136
-
137
- **Category**: Export Handling
138
- **Status**: ✅ Verified (`api_tests/api_test`)
139
- **User Guide**: [F04](API-RULES/API-FLATTENING.md#f04)
140
- **Technical**: [C15, C09d](API-RULES/API-RULES-CONDITIONS.md#c15)
141
-
142
- **Condition**: Directory contains files with only named exports (no default exports)
143
- **Behavior**: All named exports collected and made accessible at the appropriate namespace level
144
-
145
- **Verified Examples**:
146
-
147
- ```javascript
148
- // File: constants/values.mjs
149
- export const PI = 3.14159;
150
- export const E = 2.71828;
151
-
152
- // File: constants/messages.mjs
153
- export const SUCCESS = "Operation completed";
154
- export const ERROR = "Operation failed";
155
-
156
- api.constants.values.PI; // 3.14159
157
- api.constants.values.E; // 2.71828
158
- api.constants.messages.SUCCESS; // "Operation completed"
159
- api.constants.messages.ERROR; // "Operation failed"
160
- ```
161
-
162
- **Technical Implementation**:
163
-
164
- - **Detection**: [C15](API-RULES/API-RULES-CONDITIONS.md#c15) - `defaultExportCount === 0`
165
- - **Processing**: [C09d](API-RULES/API-RULES-CONDITIONS.md#c09d) - Standard namespace preservation
166
- - **Strategy**: `processingStrategy = "named-only"` → category-level collection
167
-
168
- **Key Behavior**:
169
-
170
- - Preserves all named export names and values
171
- - Maintains clear namespace separation between files
172
- - No flattening when multiple named exports exist (prevents naming conflicts)
173
-
174
- **Source Code Location**: `src/lib/helpers/api_builder/decisions.mjs` - `processModuleForAPI()`
175
- **Processing Path**: Both Root and Subfolder processing via `processModuleForAPI`
176
-
177
- ---
178
-
179
- ## Rule 3: Empty Module Handling
180
-
181
- **Category**: Special Cases
182
- **Status**: ✅ Verified
183
- **Technical**: [C10](API-RULES/API-RULES-CONDITIONS.md#c10)
184
-
185
- **Condition**: Directory contains no loadable module files
186
- **Behavior**: Graceful handling - creates empty namespace
187
- **Processing Path**: Early detection in `buildCategoryDecisions()`
188
-
189
- **Mode Differences**:
190
-
191
- - **EAGER**: Empty folder → `{}` object (not callable)
192
- - **LAZY**: Empty folder → lazy proxy that resolves to `{}` when called
193
-
194
- **Technical Implementation**:
195
-
196
- - **Detection**: [C10](API-RULES/API-RULES-CONDITIONS.md#c10) - `moduleFiles.length === 0`
197
- - **Strategy**: `processingStrategy = "empty"` → graceful empty handling
198
-
199
- ```javascript
200
- // Detection in analyzeDirectoryStructure
201
- if (moduleFiles.length === 0) {
202
- processingStrategy = "empty";
203
- }
204
- ```
205
-
206
- **Source Code Location**: `src/lib/helpers/api_builder/analysis.mjs`
207
- **Processing Path**: All paths (detected in `analyzeDirectoryStructure`)
208
-
209
- ---
210
-
211
- ## Rule 4: Named Export with Function Name Preservation
212
-
213
- **Category**: Export Handling
214
- **Status**: ✅ Verified (`api_tests/api_test`)
215
- **User Guide**: [F04](API-RULES/API-FLATTENING.md#f04)
216
- **Technical**: [C16, C23](API-RULES/API-RULES-CONDITIONS.md#c16)
217
-
218
- **Condition**: Named export with a function name that differs from the sanitized filename
219
- **Behavior**: Preserves the original function name rather than using the filename-derived name
220
- **Priority**: Function names take precedence over filename-based naming
221
-
222
- **Verified Examples**:
223
-
224
- ```javascript
225
- // File: auto-ip.mjs
226
- export function autoIP() { /* ... */ }
227
- api.autoIP(); // ✅ Function name preserved (not api.autoIp)
228
-
229
- // File: json-parser.mjs
230
- export function parseJSON(data) { /* ... */ }
231
- api.parseJSON(data); // ✅ Original casing preserved (not api.jsonParser)
232
- ```
233
-
234
- **Function Name Priority**:
235
-
236
- 1. Original function name (if available)
237
- 2. Filename-based sanitization (if no function name)
238
-
239
- **Technical Implementation**:
240
-
241
- - **Detection**: [C16](API-RULES/API-RULES-CONDITIONS.md#c16) - Function name availability check
242
- - **Processing**: [C23](API-RULES/API-RULES-CONDITIONS.md#c23) - Function name takes precedence
243
-
244
- ---
245
-
246
- ## Rule 5: Multiple Module Default Export Handling
247
-
248
- **Category**: Export Handling
249
- **Status**: ✅ Verified (`api_tests/api_test`)
250
- **Technical**: [C08, C09d](API-RULES/API-RULES-CONDITIONS.md#c08)
251
-
252
- **Condition**: Category contains multiple modules with default exports
253
- **Behavior**: Each module maintains its own namespace with the default export accessible directly
254
- **Processing Path**: Standard namespace preservation (no flattening)
255
-
256
- **Verified Examples**:
257
-
258
- ```javascript
259
- // File: validators/email.mjs
260
- export default function validateEmail(email) { /* ... */ }
261
-
262
- // File: validators/phone.mjs
263
- export default function validatePhone(phone) { /* ... */ }
264
-
265
- api.validators.email("test@example.com"); // ✅ Default function callable
266
- api.validators.phone("+1234567890"); // ✅ Default function callable
267
- ```
268
-
269
- **Technical Implementation**:
270
-
271
- - **Detection**: [C08](API-RULES/API-RULES-CONDITIONS.md#c08) - `moduleCount > 1 && defaultExportCount > 0`
272
- - **Processing**: [C09d](API-RULES/API-RULES-CONDITIONS.md#c09d) - Standard namespace preservation
273
- - **Strategy**: `processingStrategy = "standard"` → no flattening
274
-
275
- **Key Behavior**:
276
-
277
- - Maintains clear namespace separation between modules
278
- - Prevents naming conflicts where multiple defaults would collide
279
- - No automatic flattening when multiple defaults are present
280
-
281
- ---
282
-
283
- ## Rule 6: Multiple Module Mixed Exports
284
-
285
- **Category**: Special Cases
286
- **Status**: ✅ Verified (`api_tests/api_test_mixed`)
287
- **Technical**: [C14, C09d](API-RULES/API-RULES-CONDITIONS.md#c14)
288
-
289
- **Condition**: Category contains modules with mixed export types (some default, some named-only)
290
- **Behavior**: Standard namespace processing - each module maintains a distinct namespace
291
- **Processing Path**: Conservative approach to prevent conflicts
292
-
293
- **Verified Examples**:
294
-
295
- ```javascript
296
- // File: mixed/calculator.mjs (default export)
297
- export default function calculate(operation, a, b) { /* ... */ }
298
-
299
- // File: mixed/constants.mjs (named exports only)
300
- export const PI = 3.14159;
301
- export const E = 2.71828;
302
-
303
- api.mixed.calculator("add", 2, 3); // ✅ Default accessible
304
- api.mixed.constants.PI; // ✅ Named exports accessible
305
- api.mixed.constants.E; // ✅ Clear namespace separation
306
- ```
307
-
308
- **Technical Implementation**:
309
-
310
- - **Detection**: [C14](API-RULES/API-RULES-CONDITIONS.md#c14) - Mixed export types present
311
- - **Processing**: [C09d](API-RULES/API-RULES-CONDITIONS.md#c09d) - Conservative namespace preservation
312
-
313
- ---
314
-
315
- ## Rule 7: Single Module Named Export Flattening
316
-
317
- **Category**: Basic Flattening
318
- **Status**: ✅ Verified (`api_tests/api_test`)
319
- **User Guide**: [F02](API-RULES/API-FLATTENING.md#f02)
320
- **Technical**: [C06, C09b](API-RULES/API-RULES-CONDITIONS.md#c06)
321
-
322
- **Condition**: Category has one module file, module has named exports (no default export), filename ≠ category name
323
- **Source Files**: `api_tests/api_test/config/settings.mjs`
324
- **Implementation**: `getFlatteningDecision()` → single module named export flattening
325
-
326
- **Verified Examples**:
327
-
328
- ```javascript
329
- // File: api_tests/api_test/config/settings.mjs
330
- export const DATABASE_URL = "mongodb://localhost:27017/testdb";
331
- export const API_PORT = 3000;
332
- export const DEBUG_MODE = true;
333
-
334
- // Without Rule 7: api.config.settings.DATABASE_URL ❌ (unnecessary nesting)
335
- // With Rule 7: api.config.DATABASE_URL ✅ (clean flattening)
336
- api.config.DATABASE_URL; // "mongodb://localhost:27017/testdb"
337
- api.config.API_PORT; // 3000
338
- api.config.DEBUG_MODE; // true
339
- ```
340
-
341
- **Technical Implementation**:
342
-
343
- - **Primary Condition**: [C06](API-RULES/API-RULES-CONDITIONS.md#c06) - `moduleCount === 1 && !moduleHasDefault && moduleKeys.length > 0`
344
- - **Processing**: [C09b](API-RULES/API-RULES-CONDITIONS.md#c09b) - `flattenToCategory: true`
345
-
346
- ---
347
-
348
- ## Rule 8: Single Module Default Export Promotion
349
-
350
- **Category**: Basic Flattening
351
- **Status**: ✅ Verified (`api_tests/api_test`)
352
- **User Guide**: [F03](API-RULES/API-FLATTENING.md#f03)
353
- **Technical**: [C07, C09c](API-RULES/API-RULES-CONDITIONS.md#c07)
354
-
355
- **Condition**: Category has one module file with a default export
356
- **Source Files**: `api_tests/api_test/logger.mjs`
357
- **Implementation**: `getFlatteningDecision()` → single module default export promotion
358
-
359
- **Verified Examples**:
360
-
361
- ```javascript
362
- // File: api_tests/api_test/logger.mjs
363
- export default function logger(message) {
364
- console.log(`[LOG] ${message}`);
365
- }
366
-
367
- // Without Rule 8: api.logger.logger("Hello World") ❌ (redundant nesting)
368
- // With Rule 8: api.logger("Hello World") ✅ (direct callable)
369
- api.logger("Hello World"); // [LOG] Hello World
370
- typeof api.logger; // "function"
371
- ```
372
-
373
- **Callable Namespace Pattern**: When a folder contains a file matching the folder name with a default export (e.g. `logger/logger.mjs`), the default function becomes the namespace itself. Other files in the folder become properties on that function:
374
-
375
- ```javascript
376
- // File: logger/logger.mjs → export default function log()
377
- // File: logger/utils.mjs → named exports
378
- api.logger("message"); // calls the default function
379
- api.logger.utils.debug("x"); // other files remain as namespace properties
380
- ```
381
-
382
- This pattern applies consistently at root level and category level.
383
-
384
- **Technical Implementation**:
385
-
386
- - **Primary Condition**: [C07](API-RULES/API-RULES-CONDITIONS.md#c07) - `moduleCount === 1 && moduleHasDefault`
387
- - **Processing**: [C09c](API-RULES/API-RULES-CONDITIONS.md#c09c) - `promoteToCategory: true`
388
-
389
- ---
390
-
391
- ## Rule 9: Function Name Preference Over Sanitization
392
-
393
- **Category**: Special Cases
394
- **Status**: ✅ Fully Verified (autoIP, parseJSON, getHTTPStatus, XMLParser)
395
- **User Guide**: [API-RULES/API-FLATTENING.md - Name Preservation](API-RULES/API-FLATTENING.md)
396
- **Technical**: [C16, C19](API-RULES/API-RULES-CONDITIONS.md#c16)
397
-
398
- **Condition**: Exported function has an explicit name that differs from the sanitized filename
399
- **Behavior**: Preserve the original function name over the filename-based API path
400
-
401
- **Verified Examples**:
402
-
403
- ```javascript
404
- // File: auto-ip.mjs
405
- export function autoIP() { /* Get automatic IP */ }
406
- // Sanitized filename: "autoIp" ❌
407
- // Function name: "autoIP" ✅
408
-
409
- // File: get-http-status.mjs
410
- export function getHTTPStatus() { /* ... */ }
411
- // Sanitized filename: "getHttpStatus" ❌
412
- // Function name: "getHTTPStatus" ✅
413
-
414
- // File: parse-json.mjs
415
- export function parseJSON(data) { /* ... */ }
416
- // Sanitized filename: "parseJson" ❌
417
- // Function name: "parseJSON" ✅
418
- ```
419
-
420
- **Technical Implementation**:
421
-
422
- - **Primary Check**: [C16](API-RULES/API-RULES-CONDITIONS.md#c16) - `exportedFunctionName !== sanitizedName`
423
- - **Detailed Check**: [C19](API-RULES/API-RULES-CONDITIONS.md#c19) - `exportedFunction.name !== sanitizedFileName`
424
- - **Precedence**: Function name takes precedence over filename in API structure
425
-
426
- **Common Preserved Patterns**:
427
-
428
- - Technical acronyms: IP, HTTP, API, URL, JSON, XML, HTML
429
- - Protocol names: TCP, UDP, FTP, SSH, SSL, TLS
430
- - Format specs: JSON, XML, CSV, YAML, TOML
431
- - Industry standards: OAuth, JWT, REST, GraphQL
432
-
433
- ---
434
-
435
- ## Rule 10: Generic Filename Parent-Level Promotion
436
-
437
- **Category**: Special Cases
438
- **Status**: ✅ Verified (`api_tests/api_test/nest4/singlefile.mjs`)
439
- **User Guide**: [API-RULES/API-FLATTENING.md - Index File Pattern](API-RULES/API-FLATTENING.md)
440
- **Technical**: [C17](API-RULES/API-RULES-CONDITIONS.md#c17)
441
-
442
- **Condition**: File has a generic name (`index`, `main`, `default`, etc.)
443
- **Behavior**: Generic filename becomes transparent; content is promoted to the meaningful parent name
444
-
445
- **Verified Examples**:
446
-
447
- ```javascript
448
- // File: database/main.mjs
449
- export function connect() { /* ... */ }
450
- export function query() { /* ... */ }
451
-
452
- // Without Rule 10: api.database.main.connect() ❌ (generic 'main' adds no value)
453
- // With Rule 10: api.database.connect() ✅ (promoted to parent level)
454
-
455
- // File: auth/index.mjs
456
- export function login() { /* ... */ }
457
- export function logout() { /* ... */ }
458
-
459
- // Without Rule 10: api.auth.index.login() ❌ (generic 'index' is noise)
460
- // With Rule 10: api.auth.login() ✅ (clean parent-level promotion)
461
- ```
462
-
463
- **Technical Implementation**:
464
-
465
- - **Detection**: [C17](API-RULES/API-RULES-CONDITIONS.md#c17) - `isGenericFilename(fileName)`
466
- - **Promotion**: Content promoted to parent namespace; generic filename becomes invisible
467
-
468
- **Note**: Promotion is guarded against name collisions - checked against existing parent namespace properties before promoting.
469
-
470
- ---
471
-
472
- ## Rule 11: AddApi Special File Pattern
473
-
474
- **Category**: AddApi
475
- **Status**: ✅ Verified (`api_tests/api_smart_flatten_addapi`)
476
- **User Guide**: [F06](API-RULES/API-FLATTENING.md#f06)
477
- **Technical**: [C33](API-RULES/API-RULES-CONDITIONS.md#c33)
478
-
479
- **Condition**: A file named `addapi.mjs` is loaded via `api.slothlet.api.add()`
480
- **Behavior**: Exports are always flattened to the mount namespace regardless of other settings
481
- **Processing Path**: Detection in `getFlatteningDecision()` (`src/lib/processors/flatten.mjs`); execution in `src/lib/builders/modes-processor.mjs`
482
-
483
- **Verified Example**:
484
-
485
- ```javascript
486
- // File: plugin-folder/addapi.mjs
487
- export function initializePlugin() { /* ... */ }
488
- export function cleanup() { /* ... */ }
489
- export function configure() { /* ... */ }
490
-
491
- await api.slothlet.api.add("plugins", "./plugin-folder");
492
-
493
- // addapi.mjs exports are always flattened - never nested:
494
- api.plugins.initializePlugin(); // ✅
495
- api.plugins.cleanup(); // ✅
496
- api.plugins.configure(); // ✅
497
- // NOT: api.plugins.addapi.initializePlugin() ❌
498
- ```
499
-
500
- **Technical Implementation**:
501
-
502
- ```javascript
503
- // C33: AddApi Special File Detection
504
- if (moduleKeys.includes("addapi")) {
505
- const addapiModule = newModules["addapi"];
506
- const otherModules = { ...newModules };
507
- delete otherModules["addapi"];
508
- modulesToMerge = { ...addapiModule, ...otherModules };
509
- }
510
- ```
511
-
512
- **Use Cases**:
513
-
514
- - Plugin systems that extend the API at a known namespace
515
- - Hot-reloadable API extension points
516
- - Clean integration of external modules into a live API surface
517
-
518
- ---
519
-
520
- ## Rule 12: Module Ownership and Selective API Overwriting
521
-
522
- **Category**: AddApi
523
- **Status**: ✅ Implemented (`src/lib/handlers/ownership.mjs`)
524
- **User Guide**: [F07](API-RULES/API-FLATTENING.md#f07)
525
- **Technical**: [C19-C22](API-RULES/API-RULES-CONDITIONS.md#c19)
526
-
527
- **Purpose**: Track which module registered each API path, enabling safe hot-reloading and cross-module conflict protection.
528
-
529
- **Implementation**: Stack-based ownership system. Each API path maintains an independent ownership history stack. Removing a module automatically rolls back to the previous owner. Collision behavior is controlled by the `api.collision` configuration.
530
-
531
- ### Configuration
532
-
533
- ```javascript
534
- const api = await slothlet({
535
- dir: "./api",
536
- api: {
537
- collision: {
538
- initial: "merge", // During initial API build
539
- api: "replace" // During api.slothlet.api.add()
540
- }
541
- }
542
- });
543
- ```
544
-
545
- ### moduleId Tracking
546
-
547
- Each `api.slothlet.api.add()` call accepts an optional `moduleId`. This is the key for ownership tracking:
548
-
549
- ```javascript
550
- // Module A registers plugins namespace
551
- await api.slothlet.api.add("plugins.moduleA", "./modules/moduleA", {}, {
552
- moduleId: "moduleA"
553
- });
554
-
555
- // Module B registers in the same parent namespace
556
- await api.slothlet.api.add("plugins.moduleB", "./modules/moduleB", {}, {
557
- moduleId: "moduleB"
558
- });
559
-
560
- // Hot-reload Module A - ownership system allows this because moduleA owns these paths
561
- await api.slothlet.api.add("plugins.moduleA", "./modules/moduleA-v2", {}, {
562
- moduleId: "moduleA",
563
- forceOverwrite: true
564
- });
565
-
566
- // Cross-module overwrite - blocked if collision mode is "error"
567
- await api.slothlet.api.add("plugins.moduleB", "./modules/other", {}, {
568
- moduleId: "moduleA", // moduleA does not own moduleB's paths
569
- forceOverwrite: true // Throws OWNERSHIP_CONFLICT in "error" mode
570
- });
571
- ```
572
-
573
- ### Ownership Stack
574
-
575
- Each API path has a history stack. When a module is removed, the previous owner is automatically restored:
576
-
577
- ```javascript
578
- // Stack for "plugins.tools": [module-a, module-b] (module-b is current owner)
579
- await api.slothlet.api.remove("module-b");
580
- // Stack restored to: [module-a] (module-a is active again)
581
- ```
582
-
583
- ### Collision Modes
584
-
585
- | Mode | Behavior |
586
- | ---- | -------- |
587
- | `"merge"` (default) | Preserve existing properties, add new ones |
588
- | `"merge-replace"` | Add new properties, overwrite existing |
589
- | `"replace"` | Completely replace the existing value |
590
- | `"skip"` | Keep existing value, silently ignore new |
591
- | `"warn"` | Keep existing value, log a warning |
592
- | `"error"` | Throw `OWNERSHIP_CONFLICT` error |
593
-
594
- ### forceOverwrite
595
-
596
- `forceOverwrite: true` requires an explicit `moduleId` and performs a complete replacement regardless of collision mode. Use for cases where a module must fully replace its own prior registration:
597
-
598
- ```javascript
599
- await api.slothlet.api.add("config", "./new-config", {}, {
600
- moduleId: "config-v2",
601
- forceOverwrite: true
602
- });
603
- ```
604
-
605
- **Source Code**: `src/lib/handlers/ownership.mjs`
606
-
607
- ---
608
-
609
- ## Rule 13: AddApi Path Deduplication Flattening
610
-
611
- > **New in v3**
612
-
613
- **Category**: AddApi
614
- **Status**: ✅ Implemented (`api_tests/smart_flatten/api_smart_flatten_folder_config`)
615
- **User Guide**: [F08](API-RULES/API-FLATTENING.md#f08)
616
- **Technical**: [C34](API-RULES/API-RULES-CONDITIONS.md#c34)
617
-
618
- **Purpose**: When `api.slothlet.api.add("config", folder)` is called and the folder contains a subfolder whose name matches the last segment of the mount path (e.g. `config/config.mjs`), prevent double-nesting `api.config.config.*` by hoisting the subfolder's exports up to `api.config.*`.
619
-
620
- **Condition**: After `buildAPI` returns `newApi`, if `newApi` contains a key equal to `lastPart` (last segment of `normalizedPath`) AND the matching value's `filePath` has its parent directory equal to `resolvedFolderPath/lastPart` (direct child check), hoist that key's own exports to the same level as the other keys in `newApi` and remove the duplicate key.
621
-
622
- **Verified Example**:
623
-
624
- ```javascript
625
- // Folder structure: api_smart_flatten_folder_config/
626
- // main.mjs ← exports getRootInfo, setRootConfig
627
- // config/
628
- // config.mjs ← exports getNestedConfig, setNestedConfig
629
-
630
- await api.slothlet.api.add("config", "./api_smart_flatten_folder_config", {});
631
-
632
- // Without Rule 13 (double-nested):
633
- api.config.config.getNestedConfig(); // ❌
634
-
635
- // With Rule 13 (hoisted):
636
- api.config.getNestedConfig(); // ✅ subfolder exports promoted
637
- api.config.setNestedConfig(); // ✅
638
- api.config.main.getRootInfo(); // ✅ other files unaffected
639
- ```
640
-
641
- **Guard - `isDirectChild`**: Rule 13 only fires when the matching key's `filePath` is **directly** inside `resolvedFolderPath/lastPart`. This prevents false positives when a deeper nested folder coincidentally shares the mount-path name:
642
-
643
- ```javascript
644
- // Should NOT hoist (services/services/services.mjs):
645
- // api.add("services", folder) → newApi has key "services"
646
- // but filePath = .../services/services/services.mjs
647
- // dirname = .../services/services ≠ resolvedFolderPath/services
648
- // → Rule 13 does NOT fire
649
- // → api.services.services.getNestedService remains properly nested ✅
650
- ```
651
-
652
- **Implementation**: `src/lib/handlers/api-manager.mjs` - immediately after `buildAPI` call, before `setValueAtPath`
653
-
654
- ---
655
-
656
- ## Verification Status
657
-
658
- | Rule | Title | Status | Test Source |
659
- | ---- | ---------------------------------------------- | ------------ | ----------- |
660
- | 1 | Filename Matches Container Flattening | ✅ Verified | `api_tests/api_test` |
661
- | 2 | Named-Only Export Collection | ✅ Verified | `api_tests/api_test` |
662
- | 3 | Empty Module Handling | ✅ Verified | debug testing |
663
- | 4 | Named Export with Function Name Preservation | ✅ Verified | `api_tests/api_test`, `api_tests/api_tv_test` |
664
- | 5 | Multiple Module Default Export Handling | ✅ Verified | `api_tests/api_tv_test` |
665
- | 6 | Multiple Module Mixed Exports | ✅ Verified | `api_tests/api_test_mixed` |
666
- | 7 | Single Module Named Export Flattening | ✅ Verified | `api_tests/api_test` |
667
- | 8 | Single Module Default Export Promotion | ✅ Verified | Multiple test files |
668
- | 9 | Function Name Preference Over Sanitization | ✅ Verified | autoIP, parseJSON, getHTTPStatus, XMLParser |
669
- | 10 | Generic Filename Parent-Level Promotion | ✅ Verified | `api_tests/api_test/nest4/singlefile.mjs` |
670
- | 11 | AddApi Special File Pattern | ✅ Verified | `api_tests/api_smart_flatten_addapi` |
671
- | 12 | Module Ownership and Selective API Overwriting | ✅ Verified | `src/lib/handlers/ownership.mjs` |
672
- | 13 | AddApi Path Deduplication Flattening | ✅ Verified | `api_tests/smart_flatten/api_smart_flatten_folder_config` |
673
-
674
- ---
675
-
676
- ## Cross-Reference Index
677
-
678
- ### By Flattening Pattern (F##)
679
-
680
- | Flattening Pattern | API Rules | Technical Conditions |
681
- | ------------------ | --------- | -------------------- |
682
- | [F01](API-RULES/API-FLATTENING.md#f01) | Rule 1 | [C05, C09b, C11](API-RULES/API-RULES-CONDITIONS.md#c05) |
683
- | [F02](API-RULES/API-FLATTENING.md#f02) | Rule 8 (Pattern A) | [C12, C21a](API-RULES/API-RULES-CONDITIONS.md#c12) |
684
- | [F03](API-RULES/API-FLATTENING.md#f03) | Rule 7 | [C04, C09a, C18, C21c, C30](API-RULES/API-RULES-CONDITIONS.md#c04) |
685
- | [F04](API-RULES/API-FLATTENING.md#f04) | Rule 4, Rule 8 (Pattern B) | [C08c, C24](API-RULES/API-RULES-CONDITIONS.md#c08c) |
686
- | [F05](API-RULES/API-FLATTENING.md#f05) | Rule 4, Rule 8 (Pattern C) | [C08c, C11](API-RULES/API-RULES-CONDITIONS.md#c08c) |
687
- | [F06](API-RULES/API-FLATTENING.md#f06) | Rule 11 | [C33](API-RULES/API-RULES-CONDITIONS.md#c33) |
688
- | [F07](API-RULES/API-FLATTENING.md#f07) | Rule 12 | [C19-C22](API-RULES/API-RULES-CONDITIONS.md#c19) |
689
- | [F08](API-RULES/API-FLATTENING.md#f08) | Rule 13 | [C34](API-RULES/API-RULES-CONDITIONS.md#c34) |
690
-
691
- ### By Technical Condition (C##)
692
-
693
- | Condition | API Rules | Flattening Patterns |
694
- | --------- | --------- | ------------------- |
695
- | [C01-C07](API-RULES/API-RULES-CONDITIONS.md#c01) | Rules 1, 6, 7, 8 | F01, F03 |
696
- | [C08-C09d](API-RULES/API-RULES-CONDITIONS.md#c08) | Rules 4, 6, 7 | F04, F05 |
697
- | [C10-C21d](API-RULES/API-RULES-CONDITIONS.md#c10) | Rules 1, 2, 3, 5, 7, 8, 9, 10 | F01, F02, F03 |
698
- | [C22-C26](API-RULES/API-RULES-CONDITIONS.md#c22) | Rules 4, 6 | F04, F05 |
699
- | [C27-C32](API-RULES/API-RULES-CONDITIONS.md#c27) | Rules 5, 6, 7 | Multi-default scenarios |
700
- | [C33](API-RULES/API-RULES-CONDITIONS.md#c33) | Rule 11 | F06 |
701
- | [C34](API-RULES/API-RULES-CONDITIONS.md#c34) | Rule 13 | F08 |
702
-
703
- ### By Processing Context
704
-
705
- | Context | Rules | Primary Conditions |
706
- | ------- | ----- | ------------------ |
707
- | **Single-File Directories** | 1, 7, 8, 10 | C11, C12, C04, C17 |
708
- | **Multi-File Directories** | 1, 2, 5, 7, 9 | C13, C15, C21a-d, C16, C19 |
709
- | **Multi-Default Scenarios** | 5, 6, 7 | C02, C03, C27-C32 |
710
- | **AddApi Operations** | 11, 12, 13 | C33, C34, C19-C22 |
711
- | **Root-Level Processing** | 4, 8, 10 | C08c, C22, C17 |
712
- | **Subfolder Processing** | 4, 6, 8 | C08d, C20, C24 |