@cldmv/slothlet 2.11.0 → 3.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.
- package/AGENT-USAGE.md +355 -325
- package/README.md +554 -238
- package/dist/lib/builders/api-assignment.mjs +605 -0
- package/dist/lib/builders/api_builder.mjs +1073 -0
- package/dist/lib/builders/builder.mjs +94 -0
- package/dist/lib/builders/modes-processor.mjs +1816 -0
- package/dist/lib/errors.mjs +227 -0
- package/dist/lib/factories/component-base.mjs +96 -0
- package/dist/lib/factories/context.mjs +38 -0
- package/dist/lib/handlers/api-cache-manager.mjs +216 -0
- package/dist/lib/handlers/api-manager.mjs +2364 -0
- package/dist/lib/handlers/context-async.mjs +184 -0
- package/dist/lib/handlers/context-live.mjs +184 -0
- package/dist/lib/handlers/hook-manager.mjs +789 -0
- package/dist/lib/handlers/lifecycle-token.mjs +44 -0
- package/dist/lib/handlers/lifecycle.mjs +131 -0
- package/dist/lib/handlers/materialize-manager.mjs +64 -0
- package/dist/lib/handlers/metadata.mjs +500 -0
- package/dist/lib/handlers/ownership.mjs +338 -0
- package/dist/lib/handlers/unified-wrapper.mjs +3031 -0
- package/dist/lib/helpers/class-instance-wrapper.mjs +125 -0
- package/dist/lib/helpers/config.mjs +343 -0
- package/dist/lib/helpers/eventemitter-context.mjs +365 -0
- package/dist/lib/helpers/hint-detector.mjs +63 -0
- package/dist/lib/helpers/modes-utils.mjs +53 -0
- package/dist/lib/helpers/resolve-from-caller.mjs +123 -117
- package/dist/lib/helpers/sanitize.mjs +247 -168
- package/dist/lib/helpers/utilities.mjs +46 -81
- package/dist/lib/i18n/languages/de-de.json +377 -0
- package/dist/lib/i18n/languages/en-gb.json +377 -0
- package/dist/lib/i18n/languages/en-us.json +377 -0
- package/dist/lib/i18n/languages/es-mx.json +377 -0
- package/dist/lib/i18n/languages/fr-fr.json +377 -0
- package/dist/lib/i18n/languages/hi-in.json +377 -0
- package/dist/lib/i18n/languages/ja-jp.json +377 -0
- package/dist/lib/i18n/languages/ko-kr.json +377 -0
- package/dist/lib/i18n/languages/pt-br.json +377 -0
- package/dist/lib/i18n/languages/ru-ru.json +377 -0
- package/dist/lib/i18n/languages/zh-cn.json +377 -0
- package/dist/lib/i18n/translations.mjs +140 -0
- package/dist/lib/modes/eager.mjs +75 -0
- package/dist/lib/modes/lazy.mjs +97 -0
- package/dist/lib/processors/flatten.mjs +453 -0
- package/dist/lib/processors/loader.mjs +355 -0
- package/dist/lib/processors/type-generator.mjs +291 -0
- package/dist/lib/processors/typescript.mjs +188 -0
- package/dist/lib/runtime/runtime-asynclocalstorage.mjs +80 -522
- package/dist/lib/runtime/runtime-livebindings.mjs +45 -390
- package/dist/lib/runtime/runtime.mjs +39 -159
- package/dist/slothlet.mjs +525 -744
- package/docs/API-RULES.md +338 -486
- package/index.cjs +4 -4
- package/index.mjs +82 -45
- package/package.json +143 -30
- package/types/dist/lib/builders/api-assignment.d.mts +97 -0
- package/types/dist/lib/builders/api-assignment.d.mts.map +1 -0
- package/types/dist/lib/builders/api_builder.d.mts +96 -0
- package/types/dist/lib/builders/api_builder.d.mts.map +1 -0
- package/types/dist/lib/builders/builder.d.mts +60 -0
- package/types/dist/lib/builders/builder.d.mts.map +1 -0
- package/types/dist/lib/builders/modes-processor.d.mts +32 -0
- package/types/dist/lib/builders/modes-processor.d.mts.map +1 -0
- package/types/dist/lib/errors.d.mts +118 -0
- package/types/dist/lib/errors.d.mts.map +1 -0
- package/types/dist/lib/factories/component-base.d.mts +182 -0
- package/types/dist/lib/factories/component-base.d.mts.map +1 -0
- package/types/dist/lib/factories/context.d.mts +26 -0
- package/types/dist/lib/factories/context.d.mts.map +1 -0
- package/types/dist/lib/handlers/api-cache-manager.d.mts +208 -0
- package/types/dist/lib/handlers/api-cache-manager.d.mts.map +1 -0
- package/types/dist/lib/handlers/api-manager.d.mts +392 -0
- package/types/dist/lib/handlers/api-manager.d.mts.map +1 -0
- package/types/dist/lib/handlers/context-async.d.mts +66 -0
- package/types/dist/lib/handlers/context-async.d.mts.map +1 -0
- package/types/dist/lib/handlers/context-live.d.mts +65 -0
- package/types/dist/lib/handlers/context-live.d.mts.map +1 -0
- package/types/dist/lib/handlers/hook-manager.d.mts +199 -0
- package/types/dist/lib/handlers/hook-manager.d.mts.map +1 -0
- package/types/dist/lib/handlers/lifecycle-token.d.mts +49 -0
- package/types/dist/lib/handlers/lifecycle-token.d.mts.map +1 -0
- package/types/dist/lib/handlers/lifecycle.d.mts +90 -0
- package/types/dist/lib/handlers/lifecycle.d.mts.map +1 -0
- package/types/dist/lib/handlers/materialize-manager.d.mts +75 -0
- package/types/dist/lib/handlers/materialize-manager.d.mts.map +1 -0
- package/types/dist/lib/handlers/metadata.d.mts +215 -0
- package/types/dist/lib/handlers/metadata.d.mts.map +1 -0
- package/types/dist/lib/handlers/ownership.d.mts +170 -0
- package/types/dist/lib/handlers/ownership.d.mts.map +1 -0
- package/types/dist/lib/handlers/unified-wrapper.d.mts +250 -0
- package/types/dist/lib/handlers/unified-wrapper.d.mts.map +1 -0
- package/types/dist/lib/helpers/class-instance-wrapper.d.mts +54 -0
- package/types/dist/lib/helpers/class-instance-wrapper.d.mts.map +1 -0
- package/types/dist/lib/helpers/config.d.mts +96 -0
- package/types/dist/lib/helpers/config.d.mts.map +1 -0
- package/types/dist/lib/helpers/eventemitter-context.d.mts +31 -0
- package/types/dist/lib/helpers/eventemitter-context.d.mts.map +1 -0
- package/types/dist/lib/helpers/hint-detector.d.mts +20 -0
- package/types/dist/lib/helpers/hint-detector.d.mts.map +1 -0
- package/types/dist/lib/helpers/modes-utils.d.mts +35 -0
- package/types/dist/lib/helpers/modes-utils.d.mts.map +1 -0
- package/types/dist/lib/helpers/resolve-from-caller.d.mts +29 -145
- package/types/dist/lib/helpers/resolve-from-caller.d.mts.map +1 -1
- package/types/dist/lib/helpers/sanitize.d.mts +95 -94
- package/types/dist/lib/helpers/sanitize.d.mts.map +1 -1
- package/types/dist/lib/helpers/utilities.d.mts +53 -116
- package/types/dist/lib/helpers/utilities.d.mts.map +1 -1
- package/types/dist/lib/i18n/translations.d.mts +39 -0
- package/types/dist/lib/i18n/translations.d.mts.map +1 -0
- package/types/dist/lib/modes/eager.d.mts +36 -0
- package/types/dist/lib/modes/eager.d.mts.map +1 -0
- package/types/dist/lib/modes/lazy.d.mts +49 -0
- package/types/dist/lib/modes/lazy.d.mts.map +1 -0
- package/types/dist/lib/processors/flatten.d.mts +114 -0
- package/types/dist/lib/processors/flatten.d.mts.map +1 -0
- package/types/dist/lib/processors/loader.d.mts +47 -0
- package/types/dist/lib/processors/loader.d.mts.map +1 -0
- package/types/dist/lib/processors/type-generator.d.mts +19 -0
- package/types/dist/lib/processors/type-generator.d.mts.map +1 -0
- package/types/dist/lib/processors/typescript.d.mts +55 -0
- package/types/dist/lib/processors/typescript.d.mts.map +1 -0
- package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts +47 -42
- package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts.map +1 -1
- package/types/dist/lib/runtime/runtime-livebindings.d.mts +34 -65
- package/types/dist/lib/runtime/runtime-livebindings.d.mts.map +1 -1
- package/types/dist/lib/runtime/runtime.d.mts +39 -9
- package/types/dist/lib/runtime/runtime.d.mts.map +1 -1
- package/types/dist/slothlet.d.mts +184 -111
- package/types/dist/slothlet.d.mts.map +1 -1
- package/types/index.d.mts +1 -3
- package/dist/lib/engine/README.md +0 -21
- package/dist/lib/engine/slothlet_child.mjs +0 -59
- package/dist/lib/engine/slothlet_engine.mjs +0 -372
- package/dist/lib/engine/slothlet_esm.mjs +0 -230
- package/dist/lib/engine/slothlet_helpers.mjs +0 -455
- package/dist/lib/engine/slothlet_worker.mjs +0 -149
- package/dist/lib/helpers/als-eventemitter.mjs +0 -256
- package/dist/lib/helpers/api_builder/add_api.mjs +0 -553
- package/dist/lib/helpers/api_builder/analysis.mjs +0 -532
- package/dist/lib/helpers/api_builder/construction.mjs +0 -495
- package/dist/lib/helpers/api_builder/decisions.mjs +0 -748
- package/dist/lib/helpers/api_builder/metadata.mjs +0 -248
- package/dist/lib/helpers/api_builder.mjs +0 -41
- package/dist/lib/helpers/auto-wrap.mjs +0 -62
- package/dist/lib/helpers/hooks.mjs +0 -389
- package/dist/lib/helpers/instance-manager.mjs +0 -111
- package/dist/lib/helpers/metadata-api.mjs +0 -201
- package/dist/lib/helpers/multidefault.mjs +0 -216
- package/dist/lib/modes/slothlet_eager.mjs +0 -154
- package/dist/lib/modes/slothlet_lazy.mjs +0 -594
- package/docs/API-RULES-CONDITIONS.md +0 -712
- package/types/dist/lib/engine/slothlet_child.d.mts +0 -2
- package/types/dist/lib/engine/slothlet_child.d.mts.map +0 -1
- package/types/dist/lib/engine/slothlet_engine.d.mts +0 -31
- package/types/dist/lib/engine/slothlet_engine.d.mts.map +0 -1
- package/types/dist/lib/engine/slothlet_esm.d.mts +0 -19
- package/types/dist/lib/engine/slothlet_esm.d.mts.map +0 -1
- package/types/dist/lib/engine/slothlet_helpers.d.mts +0 -25
- package/types/dist/lib/engine/slothlet_helpers.d.mts.map +0 -1
- package/types/dist/lib/engine/slothlet_worker.d.mts +0 -2
- package/types/dist/lib/engine/slothlet_worker.d.mts.map +0 -1
- package/types/dist/lib/helpers/als-eventemitter.d.mts +0 -56
- package/types/dist/lib/helpers/als-eventemitter.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/add_api.d.mts +0 -102
- package/types/dist/lib/helpers/api_builder/add_api.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/analysis.d.mts +0 -189
- package/types/dist/lib/helpers/api_builder/analysis.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/construction.d.mts +0 -107
- package/types/dist/lib/helpers/api_builder/construction.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/decisions.d.mts +0 -213
- package/types/dist/lib/helpers/api_builder/decisions.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/metadata.d.mts +0 -99
- package/types/dist/lib/helpers/api_builder/metadata.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder.d.mts +0 -6
- package/types/dist/lib/helpers/api_builder.d.mts.map +0 -1
- package/types/dist/lib/helpers/auto-wrap.d.mts +0 -49
- package/types/dist/lib/helpers/auto-wrap.d.mts.map +0 -1
- package/types/dist/lib/helpers/hooks.d.mts +0 -342
- package/types/dist/lib/helpers/hooks.d.mts.map +0 -1
- package/types/dist/lib/helpers/instance-manager.d.mts +0 -41
- package/types/dist/lib/helpers/instance-manager.d.mts.map +0 -1
- package/types/dist/lib/helpers/metadata-api.d.mts +0 -132
- package/types/dist/lib/helpers/metadata-api.d.mts.map +0 -1
- package/types/dist/lib/helpers/multidefault.d.mts +0 -90
- package/types/dist/lib/helpers/multidefault.d.mts.map +0 -1
- package/types/dist/lib/modes/slothlet_eager.d.mts +0 -65
- package/types/dist/lib/modes/slothlet_eager.d.mts.map +0 -1
- package/types/dist/lib/modes/slothlet_lazy.d.mts +0 -31
- package/types/dist/lib/modes/slothlet_lazy.d.mts.map +0 -1
- package/types/index.d.mts.map +0 -1
|
@@ -1,553 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2026 CLDMV/Shinrai
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
import fs from "node:fs/promises";
|
|
22
|
-
import path from "node:path";
|
|
23
|
-
import { resolvePathFromCaller } from "@cldmv/slothlet/helpers/resolve-from-caller";
|
|
24
|
-
import { cleanMetadata, tagLoadedFunctions } from "./metadata.mjs";
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
export async function addApiFromFolder({ apiPath, folderPath, instance, metadata = {}, options = {} }) {
|
|
30
|
-
const { forceOverwrite = false, moduleId } = options;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (forceOverwrite && !moduleId) {
|
|
34
|
-
throw new Error(`[slothlet] Rule 12: forceOverwrite requires moduleId parameter for ownership tracking`);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (forceOverwrite && !instance.config.enableModuleOwnership) {
|
|
38
|
-
throw new Error(`[slothlet] Rule 12: forceOverwrite requires enableModuleOwnership: true in slothlet configuration`);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (!instance.loaded) {
|
|
42
|
-
throw new Error("[slothlet] Cannot add API: API not loaded. Call create() or load() first.");
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (typeof apiPath !== "string") {
|
|
47
|
-
throw new TypeError("[slothlet] addApi: 'apiPath' must be a string.");
|
|
48
|
-
}
|
|
49
|
-
const normalizedApiPath = apiPath.trim();
|
|
50
|
-
if (normalizedApiPath === "") {
|
|
51
|
-
throw new TypeError("[slothlet] addApi: 'apiPath' must be a non-empty, non-whitespace string.");
|
|
52
|
-
}
|
|
53
|
-
const pathParts = normalizedApiPath.split(".");
|
|
54
|
-
if (pathParts.some((part) => part === "")) {
|
|
55
|
-
throw new Error(`[slothlet] addApi: 'apiPath' must not contain empty segments. Received: "${normalizedApiPath}"`);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (typeof folderPath !== "string") {
|
|
60
|
-
throw new TypeError("[slothlet] addApi: 'folderPath' must be a string.");
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
let resolvedFolderPath = folderPath;
|
|
67
|
-
const isAbsolute = path.isAbsolute(folderPath);
|
|
68
|
-
|
|
69
|
-
if (instance.config.debug) {
|
|
70
|
-
console.log(`[DEBUG] addApi: folderPath="${folderPath}"`);
|
|
71
|
-
console.log(`[DEBUG] addApi: isAbsolute=${isAbsolute}`);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (!isAbsolute) {
|
|
75
|
-
resolvedFolderPath = resolvePathFromCaller(folderPath);
|
|
76
|
-
if (instance.config.debug) {
|
|
77
|
-
console.log(`[DEBUG] addApi: Resolved relative path to: ${resolvedFolderPath}`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
let stats;
|
|
83
|
-
try {
|
|
84
|
-
stats = await fs.stat(resolvedFolderPath);
|
|
85
|
-
} catch (error) {
|
|
86
|
-
throw new Error(`[slothlet] addApi: Cannot access folder: ${resolvedFolderPath} - ${error.message}`);
|
|
87
|
-
}
|
|
88
|
-
if (!stats.isDirectory()) {
|
|
89
|
-
throw new Error(`[slothlet] addApi: Path is not a directory: ${resolvedFolderPath}`);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (instance.config.debug) {
|
|
93
|
-
console.log(`[DEBUG] addApi: Loading modules from ${resolvedFolderPath} to path: ${normalizedApiPath}`);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
let earlyCurrentTarget = instance.api;
|
|
102
|
-
let earlyCurrentBoundTarget = instance.boundapi;
|
|
103
|
-
const earlyPathParts = normalizedApiPath.split(".");
|
|
104
|
-
|
|
105
|
-
for (let i = 0; i < earlyPathParts.length - 1; i++) {
|
|
106
|
-
const part = earlyPathParts[i];
|
|
107
|
-
const key = instance._toapiPathKey(part);
|
|
108
|
-
if (earlyCurrentTarget[key]) {
|
|
109
|
-
earlyCurrentTarget = earlyCurrentTarget[key];
|
|
110
|
-
} else {
|
|
111
|
-
earlyCurrentTarget = null;
|
|
112
|
-
break;
|
|
113
|
-
}
|
|
114
|
-
if (earlyCurrentBoundTarget[key]) {
|
|
115
|
-
earlyCurrentBoundTarget = earlyCurrentBoundTarget[key];
|
|
116
|
-
} else {
|
|
117
|
-
earlyCurrentBoundTarget = null;
|
|
118
|
-
break;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const earlyFinalKey = instance._toapiPathKey(earlyPathParts[earlyPathParts.length - 1]);
|
|
123
|
-
let superEarlyExistingTargetContent = null;
|
|
124
|
-
let superEarlyExistingBoundContent = null;
|
|
125
|
-
|
|
126
|
-
if (earlyCurrentTarget && earlyCurrentTarget[earlyFinalKey]) {
|
|
127
|
-
if (typeof earlyCurrentTarget[earlyFinalKey] === "function" && earlyCurrentTarget[earlyFinalKey].__slothletPath) {
|
|
128
|
-
if (instance.config.debug) {
|
|
129
|
-
console.log(`[DEBUG] addApi: SUPER EARLY - Target is lazy proxy - materializing to capture existing content`);
|
|
130
|
-
}
|
|
131
|
-
const _ = earlyCurrentTarget[earlyFinalKey].__trigger;
|
|
132
|
-
await earlyCurrentTarget[earlyFinalKey]();
|
|
133
|
-
}
|
|
134
|
-
if (typeof earlyCurrentTarget[earlyFinalKey] === "object") {
|
|
135
|
-
superEarlyExistingTargetContent = { ...earlyCurrentTarget[earlyFinalKey] };
|
|
136
|
-
if (instance.config.debug) {
|
|
137
|
-
console.log(`[DEBUG] addApi: SUPER EARLY - Captured existing target content:`, Object.keys(superEarlyExistingTargetContent));
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (earlyCurrentBoundTarget && earlyCurrentBoundTarget[earlyFinalKey]) {
|
|
143
|
-
if (instance.config.debug) {
|
|
144
|
-
console.log(
|
|
145
|
-
`[DEBUG] addApi: SUPER EARLY - currentBoundTarget[${earlyFinalKey}] exists, type:`,
|
|
146
|
-
typeof earlyCurrentBoundTarget[earlyFinalKey]
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
if (typeof earlyCurrentBoundTarget[earlyFinalKey] === "function" && earlyCurrentBoundTarget[earlyFinalKey].__slothletPath) {
|
|
150
|
-
if (instance.config.debug) {
|
|
151
|
-
console.log(`[DEBUG] addApi: SUPER EARLY - Bound target is lazy proxy - materializing to capture existing bound content`);
|
|
152
|
-
}
|
|
153
|
-
const _ = earlyCurrentBoundTarget[earlyFinalKey].__trigger;
|
|
154
|
-
await earlyCurrentBoundTarget[earlyFinalKey]();
|
|
155
|
-
}
|
|
156
|
-
if (typeof earlyCurrentBoundTarget[earlyFinalKey] === "object") {
|
|
157
|
-
superEarlyExistingBoundContent = { ...earlyCurrentBoundTarget[earlyFinalKey] };
|
|
158
|
-
if (instance.config.debug) {
|
|
159
|
-
console.log(`[DEBUG] addApi: SUPER EARLY - Captured existing bound content:`, Object.keys(superEarlyExistingBoundContent));
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
let newModules;
|
|
166
|
-
if (instance.config.lazy) {
|
|
167
|
-
|
|
168
|
-
newModules = await instance.modes.lazy.create.call(instance, resolvedFolderPath, instance.config.apiDepth || Infinity, 0);
|
|
169
|
-
} else {
|
|
170
|
-
|
|
171
|
-
newModules = await instance.modes.eager.create.call(instance, resolvedFolderPath, instance.config.apiDepth || Infinity, 0);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (instance.config.debug) {
|
|
175
|
-
console.log(`[DEBUG] addApi: Loaded modules structure:`, Object.keys(newModules || {}));
|
|
176
|
-
console.log(`[DEBUG] addApi: Full newModules:`, newModules);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
if (newModules && typeof newModules === "object" && newModules.addapi) {
|
|
182
|
-
if (instance.config.debug) {
|
|
183
|
-
console.log(`[DEBUG] addApi: Found addapi.mjs - applying Rule 6 flattening`);
|
|
184
|
-
console.log(`[DEBUG] addApi: Original structure:`, Object.keys(newModules));
|
|
185
|
-
console.log(`[DEBUG] addApi: Addapi contents:`, Object.keys(newModules.addapi));
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
const addapiContent = newModules.addapi;
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
delete newModules.addapi;
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
if (addapiContent && typeof addapiContent === "object") {
|
|
196
|
-
|
|
197
|
-
Object.assign(newModules, addapiContent);
|
|
198
|
-
|
|
199
|
-
if (instance.config.debug) {
|
|
200
|
-
console.log(`[DEBUG] addApi: After addapi flattening:`, Object.keys(newModules));
|
|
201
|
-
}
|
|
202
|
-
} else if (typeof addapiContent === "function") {
|
|
203
|
-
|
|
204
|
-
Object.assign(newModules, addapiContent);
|
|
205
|
-
|
|
206
|
-
if (instance.config.debug) {
|
|
207
|
-
console.log(`[DEBUG] addApi: Flattened addapi function with properties:`, Object.keys(newModules));
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
const pathSegments = normalizedApiPath.split(".");
|
|
216
|
-
const lastSegment = pathSegments[pathSegments.length - 1];
|
|
217
|
-
let rootLevelFileContent = null;
|
|
218
|
-
|
|
219
|
-
if (newModules && typeof newModules === "object" && newModules[lastSegment]) {
|
|
220
|
-
if (instance.config.debug) {
|
|
221
|
-
console.log(`[DEBUG] addApi: Found root-level file matching API path segment "${lastSegment}" - applying Rule 7 flattening`);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
let fileContent = newModules[lastSegment];
|
|
226
|
-
if (typeof fileContent === "function" && fileContent.name && fileContent.name.startsWith("lazyFolder_")) {
|
|
227
|
-
|
|
228
|
-
if (fileContent.__slothletPath) {
|
|
229
|
-
const _ = fileContent.__trigger;
|
|
230
|
-
await fileContent();
|
|
231
|
-
|
|
232
|
-
fileContent = newModules[lastSegment];
|
|
233
|
-
if (instance.config.debug) {
|
|
234
|
-
console.log(`[DEBUG] addApi: Materialized lazy proxy for root-level file:`, Object.keys(fileContent || {}));
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
if (instance.config.debug) {
|
|
240
|
-
console.log(`[DEBUG] addApi: Root-level file content:`, Object.keys(fileContent || {}));
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
rootLevelFileContent = fileContent && typeof fileContent === "object" ? { ...fileContent } : fileContent;
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
delete newModules[lastSegment];
|
|
249
|
-
|
|
250
|
-
if (instance.config.debug) {
|
|
251
|
-
console.log(`[DEBUG] addApi: After removing root-level file, remaining structure:`, Object.keys(newModules));
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
if (newModules && metadata && typeof metadata === "object" && Object.keys(metadata).length > 0) {
|
|
259
|
-
|
|
260
|
-
const fullMetadata = {
|
|
261
|
-
...metadata,
|
|
262
|
-
sourceFolder: resolvedFolderPath
|
|
263
|
-
};
|
|
264
|
-
|
|
265
|
-
if (instance.config.debug) {
|
|
266
|
-
console.log(`[DEBUG] addApi: Tagging functions with metadata:`, Object.keys(fullMetadata));
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
tagLoadedFunctions(newModules, fullMetadata, resolvedFolderPath);
|
|
270
|
-
} else if (newModules) {
|
|
271
|
-
|
|
272
|
-
if (instance.config.debug) {
|
|
273
|
-
console.log(`[DEBUG] addApi: Cleaning metadata from functions (no metadata provided)`);
|
|
274
|
-
}
|
|
275
|
-
cleanMetadata(newModules);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (instance.config.debug) {
|
|
279
|
-
if (newModules && typeof newModules === "object") {
|
|
280
|
-
console.log(`[DEBUG] addApi: Loaded modules:`, Object.keys(newModules));
|
|
281
|
-
} else {
|
|
282
|
-
console.log(
|
|
283
|
-
`[DEBUG] addApi: Loaded modules (non-object):`,
|
|
284
|
-
typeof newModules === "function" ? `[Function: ${newModules.name || "anonymous"}]` : newModules
|
|
285
|
-
);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
let currentTarget = instance.api;
|
|
291
|
-
let currentBoundTarget = instance.boundapi;
|
|
292
|
-
|
|
293
|
-
for (let i = 0; i < pathParts.length - 1; i++) {
|
|
294
|
-
const part = pathParts[i];
|
|
295
|
-
const key = instance._toapiPathKey(part);
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
if (Object.prototype.hasOwnProperty.call(currentTarget, key)) {
|
|
301
|
-
const existing = currentTarget[key];
|
|
302
|
-
if (existing === null || (typeof existing !== "object" && typeof existing !== "function")) {
|
|
303
|
-
throw new Error(
|
|
304
|
-
`[slothlet] Cannot extend API path "${normalizedApiPath}" through segment "${part}": ` +
|
|
305
|
-
`existing value is type "${typeof existing}", cannot add properties.`
|
|
306
|
-
);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
} else {
|
|
311
|
-
currentTarget[key] = {};
|
|
312
|
-
}
|
|
313
|
-
if (Object.prototype.hasOwnProperty.call(currentBoundTarget, key)) {
|
|
314
|
-
const existingBound = currentBoundTarget[key];
|
|
315
|
-
if (existingBound === null || (typeof existingBound !== "object" && typeof existingBound !== "function")) {
|
|
316
|
-
throw new Error(
|
|
317
|
-
`[slothlet] Cannot extend bound API path "${normalizedApiPath}" through segment "${part}": ` +
|
|
318
|
-
`existing value is type "${typeof existingBound}", cannot add properties.`
|
|
319
|
-
);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
} else {
|
|
323
|
-
currentBoundTarget[key] = {};
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
currentTarget = currentTarget[key];
|
|
328
|
-
currentBoundTarget = currentBoundTarget[key];
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
const finalKey = instance._toapiPathKey(pathParts[pathParts.length - 1]);
|
|
333
|
-
|
|
334
|
-
if (instance.config.debug) {
|
|
335
|
-
console.log(`[DEBUG] addApi: Final assignment - newModules type:`, typeof newModules, "keys:", Object.keys(newModules || {}));
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
if (typeof newModules === "function") {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
if (Object.prototype.hasOwnProperty.call(currentTarget, finalKey)) {
|
|
347
|
-
const existing = currentTarget[finalKey];
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
if (instance.config.enableModuleOwnership && existing) {
|
|
351
|
-
const normalizedPath = normalizedApiPath + (normalizedApiPath ? "." : "") + finalKey;
|
|
352
|
-
const canOverwrite = instance._validateModuleOwnership(normalizedPath, moduleId, forceOverwrite);
|
|
353
|
-
|
|
354
|
-
if (forceOverwrite && !canOverwrite) {
|
|
355
|
-
const existingOwner = instance._getApiOwnership(normalizedPath);
|
|
356
|
-
throw new Error(
|
|
357
|
-
`[slothlet] Rule 12: Cannot overwrite API "${normalizedPath}" - owned by module "${existingOwner}", ` +
|
|
358
|
-
`attempted by module "${moduleId}". Modules can only overwrite APIs they own.`
|
|
359
|
-
);
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
if (!forceOverwrite && instance.config.allowApiOverwrite === false) {
|
|
365
|
-
console.warn(
|
|
366
|
-
`[slothlet] Skipping addApi: API path "${normalizedApiPath}" final key "${finalKey}" ` +
|
|
367
|
-
`already exists (type: "${typeof existing}"). Set allowApiOverwrite: true to allow overwrites.`
|
|
368
|
-
);
|
|
369
|
-
return;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
if (existing !== null && typeof existing !== "function") {
|
|
374
|
-
console.warn(
|
|
375
|
-
`[slothlet] Overwriting existing non-function value at API path "${normalizedApiPath}" ` +
|
|
376
|
-
`final key "${finalKey}" with a function. Previous type: "${typeof existing}".`
|
|
377
|
-
);
|
|
378
|
-
} else if (typeof existing === "function") {
|
|
379
|
-
|
|
380
|
-
console.warn(
|
|
381
|
-
`[slothlet] Overwriting existing function at API path "${normalizedApiPath}" ` + `final key "${finalKey}" with a new function.`
|
|
382
|
-
);
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
currentTarget[finalKey] = newModules;
|
|
386
|
-
currentBoundTarget[finalKey] = newModules;
|
|
387
|
-
} else if (typeof newModules === "object" && newModules !== null) {
|
|
388
|
-
|
|
389
|
-
if (Object.prototype.hasOwnProperty.call(currentTarget, finalKey)) {
|
|
390
|
-
const existing = currentTarget[finalKey];
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
if (instance.config.enableModuleOwnership && existing) {
|
|
394
|
-
const normalizedPath = normalizedApiPath + (normalizedApiPath ? "." : "") + finalKey;
|
|
395
|
-
const canOverwrite = instance._validateModuleOwnership(normalizedPath, moduleId, forceOverwrite);
|
|
396
|
-
|
|
397
|
-
if (forceOverwrite && !canOverwrite) {
|
|
398
|
-
const existingOwner = instance._getApiOwnership(normalizedPath);
|
|
399
|
-
throw new Error(
|
|
400
|
-
`[slothlet] Rule 12: Cannot overwrite API "${normalizedPath}" - owned by module "${existingOwner}", ` +
|
|
401
|
-
`attempted by module "${moduleId}". Modules can only overwrite APIs they own.`
|
|
402
|
-
);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
if (!forceOverwrite && instance.config.allowApiOverwrite === false && existing !== undefined && existing !== null) {
|
|
408
|
-
|
|
409
|
-
const hasContent = typeof existing === "object" ? Object.keys(existing).length > 0 : true;
|
|
410
|
-
if (hasContent) {
|
|
411
|
-
console.warn(
|
|
412
|
-
`[slothlet] Skipping addApi merge: API path "${normalizedApiPath}" final key "${finalKey}" ` +
|
|
413
|
-
`already exists with content (type: "${typeof existing}"). Set allowApiOverwrite: true to allow merging.`
|
|
414
|
-
);
|
|
415
|
-
return;
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
if (existing !== null && typeof existing !== "object" && typeof existing !== "function") {
|
|
420
|
-
throw new Error(
|
|
421
|
-
`[slothlet] Cannot merge API at "${normalizedApiPath}": ` +
|
|
422
|
-
`existing value at final key "${finalKey}" is type "${typeof existing}", cannot merge into primitives.`
|
|
423
|
-
);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
if (Object.prototype.hasOwnProperty.call(currentBoundTarget, finalKey)) {
|
|
427
|
-
const existingBound = currentBoundTarget[finalKey];
|
|
428
|
-
if (existingBound !== null && typeof existingBound !== "object" && typeof existingBound !== "function") {
|
|
429
|
-
throw new Error(
|
|
430
|
-
`[slothlet] Cannot merge bound API at "${normalizedApiPath}": ` +
|
|
431
|
-
`existing value at final key "${finalKey}" is type "${typeof existingBound}", cannot merge into primitives.`
|
|
432
|
-
);
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
const targetValue = currentTarget[finalKey];
|
|
440
|
-
if (typeof targetValue === "function" && targetValue.__slothletPath) {
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
const _ = targetValue.__trigger;
|
|
444
|
-
await targetValue();
|
|
445
|
-
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
const boundTargetValue = currentBoundTarget[finalKey];
|
|
449
|
-
if (typeof boundTargetValue === "function" && boundTargetValue.__slothletPath) {
|
|
450
|
-
|
|
451
|
-
const _ = boundTargetValue.__trigger;
|
|
452
|
-
await boundTargetValue();
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
if (!currentTarget[finalKey]) {
|
|
457
|
-
currentTarget[finalKey] = {};
|
|
458
|
-
}
|
|
459
|
-
if (!currentBoundTarget[finalKey]) {
|
|
460
|
-
currentBoundTarget[finalKey] = {};
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
if (superEarlyExistingTargetContent) {
|
|
471
|
-
if (instance.config.debug) {
|
|
472
|
-
console.log(`[DEBUG] addApi: Restoring existing content - keys:`, Object.keys(superEarlyExistingTargetContent));
|
|
473
|
-
}
|
|
474
|
-
Object.assign(currentTarget[finalKey], superEarlyExistingTargetContent);
|
|
475
|
-
}
|
|
476
|
-
if (superEarlyExistingBoundContent) {
|
|
477
|
-
if (instance.config.debug) {
|
|
478
|
-
console.log(`[DEBUG] addApi: Restoring existing BOUND content - keys:`, Object.keys(superEarlyExistingBoundContent));
|
|
479
|
-
}
|
|
480
|
-
Object.assign(currentBoundTarget[finalKey], superEarlyExistingBoundContent);
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
if (instance.config.debug) {
|
|
485
|
-
console.log(`[DEBUG] addApi: Before merging new modules - current keys:`, Object.keys(currentTarget[finalKey] || {}));
|
|
486
|
-
console.log(`[DEBUG] addApi: New modules to merge - keys:`, Object.keys(newModules));
|
|
487
|
-
}
|
|
488
|
-
Object.assign(currentTarget[finalKey], newModules);
|
|
489
|
-
Object.assign(currentBoundTarget[finalKey], newModules);
|
|
490
|
-
if (instance.config.debug) {
|
|
491
|
-
console.log(`[DEBUG] addApi: After merging new modules - keys:`, Object.keys(currentTarget[finalKey] || {}));
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
if (rootLevelFileContent !== null) {
|
|
496
|
-
if (instance.config.debug) {
|
|
497
|
-
console.log(`[DEBUG] addApi: Merging root-level file content into API path "${normalizedApiPath}"`);
|
|
498
|
-
console.log(`[DEBUG] addApi: Root-level file functions:`, Object.keys(rootLevelFileContent));
|
|
499
|
-
console.log(`[DEBUG] addApi: Target before root-level merge:`, Object.keys(currentTarget[finalKey]));
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
if (rootLevelFileContent && typeof rootLevelFileContent === "object") {
|
|
504
|
-
Object.assign(currentTarget[finalKey], rootLevelFileContent);
|
|
505
|
-
Object.assign(currentBoundTarget[finalKey], rootLevelFileContent);
|
|
506
|
-
} else if (typeof rootLevelFileContent === "function") {
|
|
507
|
-
|
|
508
|
-
Object.assign(currentTarget[finalKey], rootLevelFileContent);
|
|
509
|
-
Object.assign(currentBoundTarget[finalKey], rootLevelFileContent);
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
if (instance.config.debug) {
|
|
513
|
-
console.log(`[DEBUG] addApi: After merging root-level file, final API structure:`, Object.keys(currentTarget[finalKey]));
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
} else if (newModules === null || newModules === undefined) {
|
|
517
|
-
|
|
518
|
-
const receivedType = newModules === null ? "null" : "undefined";
|
|
519
|
-
console.warn(
|
|
520
|
-
`[slothlet] addApi: No modules loaded from folder at API path "${normalizedApiPath}". ` +
|
|
521
|
-
`Loaded modules resulted in ${receivedType}. Check that the folder contains valid module files.`
|
|
522
|
-
);
|
|
523
|
-
} else {
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
currentTarget[finalKey] = newModules;
|
|
527
|
-
currentBoundTarget[finalKey] = newModules;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
if (instance.config.debug) {
|
|
532
|
-
console.log(`[DEBUG] addApi: Before updateBindings - currentTarget[${finalKey}]:`, Object.keys(currentTarget[finalKey] || {}));
|
|
533
|
-
console.log(
|
|
534
|
-
`[DEBUG] addApi: Before updateBindings - currentBoundTarget[${finalKey}]:`,
|
|
535
|
-
Object.keys(currentBoundTarget[finalKey] || {})
|
|
536
|
-
);
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
if (instance.config.enableModuleOwnership && moduleId) {
|
|
541
|
-
const fullApiPath = normalizedApiPath + (normalizedApiPath ? "." : "") + finalKey;
|
|
542
|
-
instance._registerApiOwnership(fullApiPath, moduleId);
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
instance.updateBindings(instance.context, instance.reference, instance.boundapi);
|
|
546
|
-
if (instance.config.debug) {
|
|
547
|
-
console.log(`[DEBUG] addApi: After updateBindings - api[${finalKey}]:`, Object.keys(instance.api[finalKey] || {}));
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
if (instance.config.debug) {
|
|
551
|
-
console.log(`[DEBUG] addApi: Successfully added modules at ${normalizedApiPath}`);
|
|
552
|
-
}
|
|
553
|
-
}
|