@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
|
@@ -14,1158 +14,4 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
import { ComponentBase } from "@cldmv/slothlet/factories/component-base";
|
|
21
|
-
import { TYPE_STATES } from "@cldmv/slothlet/handlers/unified-wrapper";
|
|
22
|
-
import { getLanguage, initI18n, setLanguage, t, translate } from "@cldmv/slothlet/i18n";
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
function _resolvePathOrModuleId(slothlet, pathOrModuleId) {
|
|
28
|
-
const history = slothlet.handlers?.apiManager?.state?.addHistory;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (history) {
|
|
33
|
-
let match = null;
|
|
34
|
-
for (let i = history.length - 1; i >= 0; i--) {
|
|
35
|
-
const entry = history[i];
|
|
36
|
-
if (entry?.moduleID === pathOrModuleId) {
|
|
37
|
-
match = entry;
|
|
38
|
-
break;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
if (match) return match.apiPath;
|
|
42
|
-
}
|
|
43
|
-
return pathOrModuleId;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
export class ApiBuilder extends ComponentBase {
|
|
48
|
-
static slothletProperty = "apiBuilder";
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
constructor(slothlet) {
|
|
52
|
-
super(slothlet);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
async buildFinalAPI(userApi) {
|
|
57
|
-
this.slothlet.debug("api", {
|
|
58
|
-
key: "DEBUG_MODE_BUILD_FINAL_API_CALLED",
|
|
59
|
-
diagnostics: this.____config.diagnostics,
|
|
60
|
-
userApiKeys: Object.keys(userApi)
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (this.slothlet._ownBuiltins) {
|
|
80
|
-
for (const [key, ref] of Object.entries(this.slothlet._ownBuiltins)) {
|
|
81
|
-
if (ref && Object.prototype.hasOwnProperty.call(userApi, key) && userApi[key] === ref) {
|
|
82
|
-
try {
|
|
83
|
-
delete userApi[key];
|
|
84
|
-
} catch (_) {
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
this.slothlet.userHooks = {
|
|
96
|
-
shutdown: typeof userApi.shutdown === "function" ? userApi.shutdown : null,
|
|
97
|
-
destroy: typeof userApi.destroy === "function" ? userApi.destroy : null
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if (userApi.slothlet) {
|
|
103
|
-
new this.SlothletWarning("WARNING_RESERVED_PROPERTY_CONFLICT", { properties: "slothlet" });
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const slothletNamespace = await this.createSlothletNamespace(userApi);
|
|
108
|
-
|
|
109
|
-
this.slothlet.debug("api", {
|
|
110
|
-
key: "DEBUG_MODE_SLOTHLET_NAMESPACE_CREATED",
|
|
111
|
-
namespaceKeys: Object.keys(slothletNamespace),
|
|
112
|
-
hasDiag: !!slothletNamespace.diag
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const shutdownFn = this.createShutdownFunction();
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
this.attachBuiltins(userApi, {
|
|
120
|
-
slothlet: slothletNamespace,
|
|
121
|
-
shutdown: shutdownFn,
|
|
122
|
-
destroy: null
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
this.slothlet.debug("api", {
|
|
126
|
-
key: "DEBUG_MODE_BUILT_INS_ATTACHED",
|
|
127
|
-
userApiKeys: Object.keys(userApi),
|
|
128
|
-
hasSlothlet: !!userApi.slothlet,
|
|
129
|
-
hasDiag: !!userApi.slothlet?.diag
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const destroyWithApi = this.createDestroyFunction(userApi);
|
|
134
|
-
Object.defineProperty(userApi, "destroy", {
|
|
135
|
-
value: destroyWithApi,
|
|
136
|
-
enumerable: true,
|
|
137
|
-
writable: false,
|
|
138
|
-
configurable: true
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
this.slothlet._ownBuiltins = {
|
|
144
|
-
shutdown: shutdownFn,
|
|
145
|
-
slothlet: slothletNamespace,
|
|
146
|
-
destroy: destroyWithApi
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
return userApi;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
async createSlothletNamespace(userApi) {
|
|
154
|
-
const slothlet = this.slothlet;
|
|
155
|
-
const config = this.____config;
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
let version = "unknown";
|
|
159
|
-
try {
|
|
160
|
-
const pkgPath = new URL("../../../package.json", import.meta.url);
|
|
161
|
-
const { readFile } = await import("node:fs/promises");
|
|
162
|
-
const pkgContent = await readFile(pkgPath, "utf-8");
|
|
163
|
-
const pkg = JSON.parse(pkgContent);
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
version = pkg.version || "unknown";
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
} catch {
|
|
171
|
-
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const namespace = {
|
|
175
|
-
|
|
176
|
-
i18n: {
|
|
177
|
-
setLanguage,
|
|
178
|
-
getLanguage,
|
|
179
|
-
translate,
|
|
180
|
-
t,
|
|
181
|
-
initI18n
|
|
182
|
-
},
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
version,
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
instanceID: slothlet.instanceID,
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
types: TYPE_STATES,
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
api: {
|
|
195
|
-
|
|
196
|
-
add: async function slothlet_api_add(apiPath, folderPath, options = {}, versionConfig = null) {
|
|
197
|
-
|
|
198
|
-
if (!config.api?.mutations?.add) {
|
|
199
|
-
throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED", {
|
|
200
|
-
operation: "api.add",
|
|
201
|
-
validationError: true
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
const {
|
|
210
|
-
recordHistory: ____recordHistory,
|
|
211
|
-
collisionMode: ____collisionMode,
|
|
212
|
-
mutateExisting: ____mutateExisting,
|
|
213
|
-
...filteredOptions
|
|
214
|
-
} = options;
|
|
215
|
-
return slothlet.handlers.apiManager.addApiComponent({
|
|
216
|
-
apiPath,
|
|
217
|
-
folderPath,
|
|
218
|
-
options: filteredOptions,
|
|
219
|
-
versionConfig: versionConfig || null
|
|
220
|
-
});
|
|
221
|
-
},
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
remove: async function slothlet_api_remove(pathOrModuleId) {
|
|
225
|
-
|
|
226
|
-
if (!config.api?.mutations?.remove) {
|
|
227
|
-
throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED", {
|
|
228
|
-
operation: "api.remove",
|
|
229
|
-
validationError: true
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
if (typeof pathOrModuleId !== "string") {
|
|
233
|
-
throw new slothlet.SlothletError("INVALID_ARGUMENT", {
|
|
234
|
-
argument: "pathOrModuleId",
|
|
235
|
-
expected: "string",
|
|
236
|
-
received: typeof pathOrModuleId,
|
|
237
|
-
validationError: true
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
return slothlet.handlers.apiManager.removeApiComponent(pathOrModuleId);
|
|
241
|
-
},
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
reload: async function slothlet_api_reload(pathOrModuleId, options) {
|
|
245
|
-
|
|
246
|
-
if (!config.api?.mutations?.reload) {
|
|
247
|
-
throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED", {
|
|
248
|
-
operation: "api.reload",
|
|
249
|
-
validationError: true
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
if (pathOrModuleId == null || pathOrModuleId === "" || pathOrModuleId === ".") {
|
|
255
|
-
return slothlet.handlers.apiManager.reloadApiComponent({ apiPath: ".", options });
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
if (typeof pathOrModuleId !== "string") {
|
|
259
|
-
throw new slothlet.SlothletError("INVALID_ARGUMENT", {
|
|
260
|
-
argument: "pathOrModuleId",
|
|
261
|
-
expected: "string, null, undefined, or '.'",
|
|
262
|
-
received: typeof pathOrModuleId,
|
|
263
|
-
validationError: true
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
const isModuleId = slothlet.handlers.apiManager.state.addHistory.some((entry) => entry.moduleID === pathOrModuleId);
|
|
269
|
-
|
|
270
|
-
if (isModuleId) {
|
|
271
|
-
return slothlet.handlers.apiManager.reloadApiComponent({ moduleID: pathOrModuleId, options });
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
const normalizedPath = slothlet.handlers.apiManager.normalizeApiPath(pathOrModuleId).apiPath;
|
|
276
|
-
const pathParts = normalizedPath.split(".");
|
|
277
|
-
let current = slothlet.api;
|
|
278
|
-
for (const part of pathParts) {
|
|
279
|
-
if (!current || (typeof current !== "object" && typeof current !== "function")) {
|
|
280
|
-
throw new slothlet.SlothletError("INVALID_API_PATH", {
|
|
281
|
-
apiPath: pathOrModuleId,
|
|
282
|
-
validationError: true
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
current = current[part];
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
if (current === undefined) {
|
|
289
|
-
throw new slothlet.SlothletError("INVALID_API_PATH", {
|
|
290
|
-
apiPath: pathOrModuleId,
|
|
291
|
-
validationError: true
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
return slothlet.handlers.apiManager.reloadApiComponent({ apiPath: normalizedPath, options });
|
|
297
|
-
}
|
|
298
|
-
},
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
sanitize: function slothlet_sanitize(str) {
|
|
302
|
-
if (typeof str !== "string") {
|
|
303
|
-
throw new slothlet.SlothletError("INVALID_ARGUMENT", {
|
|
304
|
-
argument: "str",
|
|
305
|
-
expected: "string",
|
|
306
|
-
received: typeof str,
|
|
307
|
-
validationError: true
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
return slothlet.helpers.sanitize.sanitizePropertyName(str, slothlet.config.sanitize || {});
|
|
311
|
-
},
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
context: {
|
|
315
|
-
|
|
316
|
-
get: (key) => {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
if (slothlet.contextManager.constructor.name === "LiveContextManager") {
|
|
322
|
-
const currentID = slothlet.contextManager.currentInstanceID;
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
if (currentID) {
|
|
328
|
-
const activeStore = slothlet.contextManager.instances.get(currentID);
|
|
329
|
-
const isOurInstance =
|
|
330
|
-
currentID === slothlet.instanceID ||
|
|
331
|
-
currentID?.startsWith(slothlet.instanceID + "__run_") ||
|
|
332
|
-
activeStore?.parentInstanceID === slothlet.instanceID;
|
|
333
|
-
|
|
334
|
-
if (isOurInstance && activeStore) {
|
|
335
|
-
return key ? activeStore.context[key] : { ...activeStore.context };
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
const store = slothlet.contextManager.instances.get(slothlet.instanceID);
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
if (!store) {
|
|
345
|
-
const baseContext = slothlet.context || {};
|
|
346
|
-
return key ? baseContext[key] : { ...baseContext };
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
return key ? store.context[key] : { ...store.context };
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
if (slothlet.contextManager.constructor.name === "AsyncContextManager") {
|
|
355
|
-
let currentStore = slothlet.contextManager.tryGetContext();
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
if (!currentStore) {
|
|
360
|
-
const baseStore = slothlet.contextManager.instances.get(slothlet.instanceID);
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
const baseContext = baseStore?.context || {};
|
|
364
|
-
return key ? baseContext[key] : { ...baseContext };
|
|
365
|
-
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
const isOurInstance =
|
|
370
|
-
currentStore.instanceID === slothlet.instanceID ||
|
|
371
|
-
currentStore.parentInstanceID === slothlet.instanceID ||
|
|
372
|
-
currentStore.instanceID.startsWith(slothlet.instanceID + "__run_");
|
|
373
|
-
|
|
374
|
-
if (isOurInstance) {
|
|
375
|
-
|
|
376
|
-
return key ? currentStore.context[key] : { ...currentStore.context };
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
const baseStore = slothlet.contextManager.instances.get(slothlet.instanceID);
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
const baseContext = baseStore?.context || {};
|
|
384
|
-
return key ? baseContext[key] : { ...baseContext };
|
|
385
|
-
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
const baseContext = slothlet.context || {};
|
|
393
|
-
return key ? baseContext[key] : { ...baseContext };
|
|
394
|
-
|
|
395
|
-
},
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
diagnostics: () => {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
if (!slothlet.config?.diagnostics) return undefined;
|
|
404
|
-
const managerType = slothlet.contextManager.constructor.name;
|
|
405
|
-
const result = {
|
|
406
|
-
instanceID: slothlet.instanceID,
|
|
407
|
-
managerType,
|
|
408
|
-
instancesMapSize: slothlet.contextManager.instances.size,
|
|
409
|
-
instancesMapKeys: Array.from(slothlet.contextManager.instances.keys()),
|
|
410
|
-
baseContext: slothlet.context
|
|
411
|
-
};
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
const store = slothlet.contextManager.instances.get(slothlet.instanceID);
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
result.storeFromInstancesMap = store
|
|
419
|
-
? {
|
|
420
|
-
instanceID: store.instanceID,
|
|
421
|
-
context: store.context,
|
|
422
|
-
createdAt: store.createdAt
|
|
423
|
-
}
|
|
424
|
-
: null;
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
if (managerType === "AsyncContextManager") {
|
|
428
|
-
try {
|
|
429
|
-
const currentCtx = slothlet.contextManager.tryGetContext();
|
|
430
|
-
result.currentALSContext = currentCtx
|
|
431
|
-
? {
|
|
432
|
-
instanceID: currentCtx.instanceID,
|
|
433
|
-
context: currentCtx.context,
|
|
434
|
-
hasParent: !!currentCtx.parentContext,
|
|
435
|
-
parentInstanceID: currentCtx.parentInstanceID
|
|
436
|
-
}
|
|
437
|
-
: null;
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
} catch (____error) {
|
|
442
|
-
result.currentALSContext = null;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
if (managerType === "LiveContextManager") {
|
|
449
|
-
result.currentInstanceID = slothlet.contextManager.currentInstanceID;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
return result;
|
|
453
|
-
},
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
run: this.createRunFunction(),
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
scope: this.createScopeFunction()
|
|
460
|
-
},
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
hook: {
|
|
464
|
-
|
|
465
|
-
on: function slothlet_hook_on(typePattern, handler, options = {}) {
|
|
466
|
-
if (!slothlet.handlers?.hookManager) {
|
|
467
|
-
throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED", { validationError: true });
|
|
468
|
-
}
|
|
469
|
-
return slothlet.handlers.hookManager.on(typePattern, handler, options);
|
|
470
|
-
},
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
remove: function slothlet_hook_remove(filter = {}) {
|
|
474
|
-
if (!slothlet.handlers?.hookManager) {
|
|
475
|
-
throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED", { validationError: true });
|
|
476
|
-
}
|
|
477
|
-
return slothlet.handlers.hookManager.remove(filter);
|
|
478
|
-
},
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
clear: function slothlet_hook_clear(filter = {}) {
|
|
482
|
-
return this.remove(filter);
|
|
483
|
-
},
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
off: function slothlet_hook_off(idOrFilter) {
|
|
487
|
-
if (!slothlet.handlers?.hookManager) {
|
|
488
|
-
throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED", { validationError: true });
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
const filter = typeof idOrFilter === "string" ? { id: idOrFilter } : idOrFilter;
|
|
492
|
-
return slothlet.handlers.hookManager.remove(filter);
|
|
493
|
-
},
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
enable: function slothlet_hook_enable(filter = {}) {
|
|
497
|
-
if (!slothlet.handlers?.hookManager) {
|
|
498
|
-
throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED", { validationError: true });
|
|
499
|
-
}
|
|
500
|
-
return slothlet.handlers.hookManager.enable(filter);
|
|
501
|
-
},
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
disable: function slothlet_hook_disable(filter = {}) {
|
|
505
|
-
if (!slothlet.handlers?.hookManager) {
|
|
506
|
-
throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED", { validationError: true });
|
|
507
|
-
}
|
|
508
|
-
return slothlet.handlers.hookManager.disable(filter);
|
|
509
|
-
},
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
list: function slothlet_hook_list(filter = {}) {
|
|
513
|
-
if (!slothlet.handlers?.hookManager) {
|
|
514
|
-
throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED", { validationError: true });
|
|
515
|
-
}
|
|
516
|
-
return slothlet.handlers.hookManager.list(filter);
|
|
517
|
-
}
|
|
518
|
-
},
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
metadata: {
|
|
522
|
-
|
|
523
|
-
setGlobal: function slothlet_metadata_setGlobal(key, value) {
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
if (!slothlet.handlers?.metadata) {
|
|
529
|
-
throw new slothlet.SlothletError("METADATA_NOT_AVAILABLE", {
|
|
530
|
-
handlersKeys: slothlet.handlers ? Object.keys(slothlet.handlers).join(", ") : "undefined",
|
|
531
|
-
validationError: true
|
|
532
|
-
});
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
return slothlet.handlers.metadata.setGlobalMetadata(key, value);
|
|
536
|
-
},
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
set: function slothlet_metadata_set(fn, key, value) {
|
|
540
|
-
if (!slothlet.handlers?.metadata) {
|
|
541
|
-
throw new slothlet.SlothletError("METADATA_NOT_AVAILABLE", {
|
|
542
|
-
handlersKeys: slothlet.handlers
|
|
543
|
-
? Object.keys(slothlet.handlers).join(", ")
|
|
544
|
-
:
|
|
545
|
-
|
|
546
|
-
"undefined",
|
|
547
|
-
validationError: true
|
|
548
|
-
});
|
|
549
|
-
}
|
|
550
|
-
return slothlet.handlers.metadata.setUserMetadata(fn, key, value);
|
|
551
|
-
},
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
remove: function slothlet_metadata_remove(fn, key) {
|
|
555
|
-
return slothlet.handlers.metadata.removeUserMetadata(fn, key);
|
|
556
|
-
},
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
setFor: function slothlet_metadata_setFor(pathOrModuleId, keyOrObj, value) {
|
|
560
|
-
if (!slothlet.handlers?.metadata) {
|
|
561
|
-
throw new slothlet.SlothletError("METADATA_NOT_AVAILABLE", {
|
|
562
|
-
handlersKeys: slothlet.handlers
|
|
563
|
-
? Object.keys(slothlet.handlers).join(", ")
|
|
564
|
-
:
|
|
565
|
-
|
|
566
|
-
"undefined",
|
|
567
|
-
validationError: true
|
|
568
|
-
});
|
|
569
|
-
}
|
|
570
|
-
const resolvedPath = _resolvePathOrModuleId(slothlet, pathOrModuleId);
|
|
571
|
-
return slothlet.handlers.metadata.setPathMetadata(resolvedPath, keyOrObj, value);
|
|
572
|
-
},
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
removeFor: function slothlet_metadata_removeFor(pathOrModuleId, key) {
|
|
576
|
-
if (!slothlet.handlers?.metadata) return;
|
|
577
|
-
const resolvedPath = _resolvePathOrModuleId(slothlet, pathOrModuleId);
|
|
578
|
-
return slothlet.handlers.metadata.removePathMetadata(resolvedPath, key);
|
|
579
|
-
},
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
setForVersion: function slothlet_metadata_setForVersion(logicalPath, versionTag, keyOrObj, value) {
|
|
583
|
-
if (!slothlet.handlers?.metadata) {
|
|
584
|
-
throw new slothlet.SlothletError("METADATA_NOT_AVAILABLE", {
|
|
585
|
-
handlersKeys: slothlet.handlers
|
|
586
|
-
? Object.keys(slothlet.handlers).join(", ")
|
|
587
|
-
: "undefined",
|
|
588
|
-
validationError: true
|
|
589
|
-
});
|
|
590
|
-
}
|
|
591
|
-
const info = slothlet.handlers?.versionManager?.list(logicalPath);
|
|
592
|
-
if (!info || !info.versions?.[versionTag]) {
|
|
593
|
-
throw new slothlet.SlothletError("VERSION_NOT_FOUND", {
|
|
594
|
-
version: versionTag,
|
|
595
|
-
apiPath: logicalPath
|
|
596
|
-
});
|
|
597
|
-
}
|
|
598
|
-
const { moduleID } = info.versions[versionTag];
|
|
599
|
-
const resolvedPath = _resolvePathOrModuleId(slothlet, moduleID);
|
|
600
|
-
return slothlet.handlers.metadata.setPathMetadata(resolvedPath, keyOrObj, value);
|
|
601
|
-
},
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
getForVersion: function slothlet_metadata_getForVersion(logicalPath, versionTag) {
|
|
605
|
-
|
|
606
|
-
if (!slothlet.handlers?.metadata) return {};
|
|
607
|
-
const info = slothlet.handlers?.versionManager?.list(logicalPath);
|
|
608
|
-
if (!info || !info.versions?.[versionTag]) return {};
|
|
609
|
-
const { moduleID } = info.versions[versionTag];
|
|
610
|
-
const resolvedPath = _resolvePathOrModuleId(slothlet, moduleID);
|
|
611
|
-
return slothlet.handlers.metadata.getPathMetadata(resolvedPath);
|
|
612
|
-
}
|
|
613
|
-
},
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
scope: this.createScopeFunction(),
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
run: this.createRunFunction(),
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
reload: async (options = {}) => {
|
|
623
|
-
|
|
624
|
-
if (!config.api?.mutations?.reload) {
|
|
625
|
-
throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED", {
|
|
626
|
-
operation: "reload",
|
|
627
|
-
validationError: true
|
|
628
|
-
});
|
|
629
|
-
}
|
|
630
|
-
return slothlet.reload(options);
|
|
631
|
-
},
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
shutdown: async () => {
|
|
635
|
-
return slothlet.shutdown();
|
|
636
|
-
},
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
owner: {
|
|
640
|
-
|
|
641
|
-
get: (apiPath) => {
|
|
642
|
-
if (slothlet.handlers?.ownership) {
|
|
643
|
-
return slothlet.handlers.ownership.getPathOwnership(apiPath);
|
|
644
|
-
}
|
|
645
|
-
return null;
|
|
646
|
-
}
|
|
647
|
-
},
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
materialize: (() => {
|
|
651
|
-
const mgr = slothlet.handlers?.materialize;
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
if (!mgr) {
|
|
655
|
-
return Object.freeze({
|
|
656
|
-
materialized: false,
|
|
657
|
-
get: () => ({ total: 0, materialized: 0, remaining: 0, percentage: 100 }),
|
|
658
|
-
wait: async () => {}
|
|
659
|
-
});
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
return Object.freeze({
|
|
663
|
-
get materialized() {
|
|
664
|
-
return mgr.materialized;
|
|
665
|
-
},
|
|
666
|
-
get: mgr.get.bind(mgr),
|
|
667
|
-
wait: mgr.wait.bind(mgr)
|
|
668
|
-
});
|
|
669
|
-
})(),
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
lifecycle: (() => {
|
|
673
|
-
const handler = slothlet.handlers?.lifecycle;
|
|
674
|
-
const noop = () => {};
|
|
675
|
-
if (!handler) return { on: noop, off: noop };
|
|
676
|
-
return {
|
|
677
|
-
on: handler.on.bind(handler),
|
|
678
|
-
off: handler.off.bind(handler)
|
|
679
|
-
};
|
|
680
|
-
})(),
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
env: slothlet.envSnapshot,
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
versioning: {
|
|
687
|
-
|
|
688
|
-
list: function slothlet_version_list(logicalPath) {
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
if (!slothlet.handlers?.versionManager) return undefined;
|
|
692
|
-
return slothlet.handlers.versionManager.list(logicalPath);
|
|
693
|
-
},
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
setDefault: function slothlet_version_setDefault(logicalPath, versionTag) {
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
if (!slothlet.handlers?.versionManager) return;
|
|
700
|
-
return slothlet.handlers.versionManager.setDefault(logicalPath, versionTag);
|
|
701
|
-
},
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
unregister: async function slothlet_version_unregister(logicalPath, versionTag) {
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
if (!slothlet.handlers?.versionManager) return false;
|
|
708
|
-
|
|
709
|
-
const info = slothlet.handlers.versionManager.list(logicalPath);
|
|
710
|
-
if (!info || !info.versions?.[versionTag]) return false;
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
const { moduleID: versionedModuleID } = info.versions[versionTag];
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
await slothlet.handlers.apiManager.removeApiComponent(versionedModuleID);
|
|
719
|
-
return true;
|
|
720
|
-
},
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
getVersionMetadata: function slothlet_version_getVersionMetadata(logicalPath, versionTag) {
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
if (!slothlet.handlers?.versionManager) return undefined;
|
|
727
|
-
return slothlet.handlers.versionManager.getVersionMetadataByPath(logicalPath, versionTag);
|
|
728
|
-
},
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
setVersionMetadata: function slothlet_version_setVersionMetadata(logicalPath, versionTag, patch) {
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
if (!slothlet.handlers?.versionManager) return;
|
|
735
|
-
return slothlet.handlers.versionManager.setVersionMetadataByPath(logicalPath, versionTag, patch);
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
};
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
if (!config.hook?.enabled && config.diagnostics !== true) {
|
|
743
|
-
delete namespace.hooks;
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
if (config.diagnostics === true) {
|
|
748
|
-
namespace.diag = {
|
|
749
|
-
|
|
750
|
-
describe: (showAll = false) => {
|
|
751
|
-
if (showAll) {
|
|
752
|
-
|
|
753
|
-
return { ...userApi };
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
return Reflect.ownKeys(userApi);
|
|
757
|
-
},
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
reference: slothlet.reference || null,
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
context: slothlet.context || {},
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
inspect: () => {
|
|
767
|
-
return slothlet.getDiagnostics();
|
|
768
|
-
},
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
getAPI: () => {
|
|
772
|
-
return slothlet.getAPI();
|
|
773
|
-
},
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
getOwnership: () => {
|
|
777
|
-
return slothlet.getOwnership();
|
|
778
|
-
},
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
owner: {
|
|
782
|
-
|
|
783
|
-
get: (apiPath) => {
|
|
784
|
-
if (slothlet.handlers?.ownership) {
|
|
785
|
-
return slothlet.handlers.ownership.getPathOwnership(apiPath);
|
|
786
|
-
}
|
|
787
|
-
return null;
|
|
788
|
-
}
|
|
789
|
-
},
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
caches: {
|
|
793
|
-
|
|
794
|
-
get: () => {
|
|
795
|
-
if (slothlet.handlers?.apiCacheManager) {
|
|
796
|
-
return slothlet.handlers.apiCacheManager.getCacheDiagnostics();
|
|
797
|
-
}
|
|
798
|
-
return { totalCaches: 0, caches: [] };
|
|
799
|
-
},
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
getAllModuleIDs: () => {
|
|
803
|
-
if (slothlet.handlers?.apiCacheManager) {
|
|
804
|
-
return slothlet.handlers.apiCacheManager.getAllModuleIDs();
|
|
805
|
-
}
|
|
806
|
-
return [];
|
|
807
|
-
},
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
has: (moduleID) => {
|
|
811
|
-
if (slothlet.handlers?.apiCacheManager) {
|
|
812
|
-
return slothlet.handlers.apiCacheManager.has(moduleID);
|
|
813
|
-
}
|
|
814
|
-
return false;
|
|
815
|
-
}
|
|
816
|
-
},
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
SlothletWarning: slothlet.SlothletWarning,
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
hook: slothlet.handlers?.hookManager
|
|
825
|
-
? {
|
|
826
|
-
|
|
827
|
-
get enabled() {
|
|
828
|
-
return slothlet.handlers.hookManager.enabled;
|
|
829
|
-
},
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
compilePattern: (pattern) => {
|
|
833
|
-
return slothlet.handlers.hookManager.getCompilePatternForDiagnostics()(pattern);
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
: undefined
|
|
837
|
-
|
|
838
|
-
};
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
return namespace;
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
createShutdownFunction() {
|
|
846
|
-
const slothlet = this.slothlet;
|
|
847
|
-
const shutdownFunction = {
|
|
848
|
-
shutdown: async () => {
|
|
849
|
-
|
|
850
|
-
if (slothlet.userHooks?.shutdown && typeof slothlet.userHooks.shutdown === "function") {
|
|
851
|
-
await slothlet.userHooks.shutdown();
|
|
852
|
-
}
|
|
853
|
-
return slothlet.shutdown();
|
|
854
|
-
}
|
|
855
|
-
}.shutdown;
|
|
856
|
-
return shutdownFunction;
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
createRunFunction() {
|
|
861
|
-
const slothlet = this.slothlet;
|
|
862
|
-
|
|
863
|
-
const scopeFunc = this.createScopeFunction();
|
|
864
|
-
|
|
865
|
-
const runFunction = {
|
|
866
|
-
run: async (contextData, callback, ...args) => {
|
|
867
|
-
|
|
868
|
-
if (slothlet.config.scope === false) {
|
|
869
|
-
throw new slothlet.SlothletError("SCOPE_DISABLED", {}, null, { validationError: true });
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
if (!contextData || typeof contextData !== "object") {
|
|
874
|
-
throw new slothlet.SlothletError("SCOPE_INVALID_CONTEXT", { received: typeof contextData }, null, { validationError: true });
|
|
875
|
-
}
|
|
876
|
-
if (typeof callback !== "function") {
|
|
877
|
-
throw new slothlet.SlothletError("SCOPE_INVALID_CALLBACK", { received: typeof callback }, null, { validationError: true });
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
return scopeFunc({
|
|
883
|
-
context: contextData,
|
|
884
|
-
fn: callback,
|
|
885
|
-
args: args,
|
|
886
|
-
merge: slothlet.config.scope?.merge || "shallow",
|
|
887
|
-
isolation: slothlet.config.scope?.isolation || "partial"
|
|
888
|
-
});
|
|
889
|
-
}
|
|
890
|
-
}.run;
|
|
891
|
-
return runFunction;
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
createScopeFunction() {
|
|
896
|
-
const slothlet = this.slothlet;
|
|
897
|
-
const scopeFunction = {
|
|
898
|
-
scope: async (options) => {
|
|
899
|
-
|
|
900
|
-
if (slothlet.config.scope === false) {
|
|
901
|
-
throw new slothlet.SlothletError("SCOPE_DISABLED", {}, null, { validationError: true });
|
|
902
|
-
}
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
if (!options || typeof options !== "object") {
|
|
906
|
-
throw new slothlet.SlothletError("SCOPE_INVALID_OPTIONS", { received: typeof options }, null, { validationError: true });
|
|
907
|
-
}
|
|
908
|
-
if (!options.fn || typeof options.fn !== "function") {
|
|
909
|
-
throw new slothlet.SlothletError("SCOPE_INVALID_FN", { received: typeof options?.fn }, null, { validationError: true });
|
|
910
|
-
}
|
|
911
|
-
if (!options.context || typeof options.context !== "object") {
|
|
912
|
-
throw new slothlet.SlothletError("SCOPE_INVALID_CONTEXT_OBJECT", { received: typeof options?.context }, null, {
|
|
913
|
-
validationError: true
|
|
914
|
-
});
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
const { context: contextData, fn, args = [], merge = "shallow", isolation } = options;
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
if (merge !== "shallow" && merge !== "deep") {
|
|
921
|
-
throw new slothlet.SlothletError("SCOPE_INVALID_MERGE_STRATEGY", { merge }, null, { validationError: true });
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
const isolationMode = isolation || slothlet.config.scope?.isolation || "partial";
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
if (isolationMode !== "partial" && isolationMode !== "full") {
|
|
929
|
-
throw new slothlet.SlothletError("SCOPE_INVALID_ISOLATION_MODE", { isolationMode }, null, { validationError: true });
|
|
930
|
-
}
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
const contextManager = slothlet.contextManager;
|
|
934
|
-
if (!contextManager) {
|
|
935
|
-
throw new slothlet.SlothletError("NO_CONTEXT_MANAGER", { validationError: true });
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
const { utilities } = slothlet.helpers;
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
if (contextManager.constructor.name === "LiveContextManager") {
|
|
942
|
-
|
|
943
|
-
let currentStore = null;
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
const currentID = contextManager.currentInstanceID;
|
|
947
|
-
if (currentID) {
|
|
948
|
-
const activeStore = contextManager.instances.get(currentID);
|
|
949
|
-
const isOurContext =
|
|
950
|
-
currentID === slothlet.instanceID ||
|
|
951
|
-
activeStore?.parentInstanceID === slothlet.instanceID ||
|
|
952
|
-
currentID.startsWith(slothlet.instanceID + "__run_");
|
|
953
|
-
|
|
954
|
-
if (isOurContext) {
|
|
955
|
-
currentStore = activeStore;
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
if (!currentStore) {
|
|
961
|
-
currentStore = contextManager.instances.get(slothlet.instanceID);
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
if (!currentStore) {
|
|
965
|
-
throw new slothlet.SlothletError("CONTEXT_NOT_FOUND", {
|
|
966
|
-
instanceID: slothlet.instanceID,
|
|
967
|
-
availableInstances: [...contextManager.instances.keys()].join(", ") || "none",
|
|
968
|
-
validationError: true
|
|
969
|
-
});
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
let mergedContext;
|
|
975
|
-
if (merge === "deep") {
|
|
976
|
-
mergedContext = utilities.deepMerge(currentStore.context, contextData);
|
|
977
|
-
|
|
978
|
-
mergedContext = structuredClone(mergedContext);
|
|
979
|
-
} else {
|
|
980
|
-
|
|
981
|
-
const clonedParent = structuredClone(currentStore.context);
|
|
982
|
-
mergedContext = { ...clonedParent, ...contextData };
|
|
983
|
-
}
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
const childInstanceID = `${slothlet.instanceID}__run_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
987
|
-
|
|
988
|
-
const childStore = {
|
|
989
|
-
instanceID: childInstanceID,
|
|
990
|
-
context: mergedContext,
|
|
991
|
-
self: isolationMode === "full" ? utilities.deepClone(currentStore.self) : currentStore.self,
|
|
992
|
-
config: currentStore.config,
|
|
993
|
-
createdAt: currentStore.createdAt,
|
|
994
|
-
parentInstanceID: slothlet.instanceID
|
|
995
|
-
};
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
contextManager.instances.set(childInstanceID, childStore);
|
|
999
|
-
const previousInstanceID = contextManager.currentInstanceID;
|
|
1000
|
-
|
|
1001
|
-
try {
|
|
1002
|
-
|
|
1003
|
-
contextManager.currentInstanceID = childInstanceID;
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
return await fn(...args);
|
|
1007
|
-
} finally {
|
|
1008
|
-
|
|
1009
|
-
contextManager.currentInstanceID = previousInstanceID;
|
|
1010
|
-
contextManager.instances.delete(childInstanceID);
|
|
1011
|
-
}
|
|
1012
|
-
}
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
if (contextManager.constructor.name === "AsyncContextManager") {
|
|
1016
|
-
|
|
1017
|
-
let currentStore = null;
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
const activeStore = contextManager.tryGetContext();
|
|
1021
|
-
if (activeStore) {
|
|
1022
|
-
const isOurContext =
|
|
1023
|
-
activeStore.instanceID === slothlet.instanceID ||
|
|
1024
|
-
activeStore.parentInstanceID === slothlet.instanceID ||
|
|
1025
|
-
activeStore.instanceID.startsWith(slothlet.instanceID + "__run_");
|
|
1026
|
-
|
|
1027
|
-
if (isOurContext) {
|
|
1028
|
-
currentStore = activeStore;
|
|
1029
|
-
}
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
if (!currentStore) {
|
|
1034
|
-
const baseStore = contextManager.instances.get(slothlet.instanceID);
|
|
1035
|
-
if (!baseStore) {
|
|
1036
|
-
throw new slothlet.SlothletError("CONTEXT_NOT_FOUND", {
|
|
1037
|
-
instanceID: slothlet.instanceID,
|
|
1038
|
-
availableInstances: [...contextManager.instances.keys()].join(", ") || "none",
|
|
1039
|
-
validationError: true
|
|
1040
|
-
});
|
|
1041
|
-
}
|
|
1042
|
-
currentStore = baseStore;
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
let mergedContext;
|
|
1048
|
-
if (merge === "deep") {
|
|
1049
|
-
mergedContext = utilities.deepMerge(currentStore.context, contextData);
|
|
1050
|
-
|
|
1051
|
-
mergedContext = structuredClone(mergedContext);
|
|
1052
|
-
} else {
|
|
1053
|
-
|
|
1054
|
-
const clonedParent = structuredClone(currentStore.context);
|
|
1055
|
-
mergedContext = { ...clonedParent, ...contextData };
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
const childInstanceID = `${slothlet.instanceID}__run_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
1060
|
-
|
|
1061
|
-
const childStore = {
|
|
1062
|
-
instanceID: childInstanceID,
|
|
1063
|
-
context: mergedContext,
|
|
1064
|
-
self: isolationMode === "full" ? utilities.deepClone(currentStore.self) : currentStore.self,
|
|
1065
|
-
config: currentStore.config,
|
|
1066
|
-
createdAt: currentStore.createdAt,
|
|
1067
|
-
parentInstanceID: slothlet.instanceID
|
|
1068
|
-
};
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
contextManager.instances.set(childInstanceID, childStore);
|
|
1072
|
-
|
|
1073
|
-
try {
|
|
1074
|
-
|
|
1075
|
-
return await contextManager.als.run(childStore, async () => {
|
|
1076
|
-
return await fn(...args);
|
|
1077
|
-
});
|
|
1078
|
-
} finally {
|
|
1079
|
-
|
|
1080
|
-
contextManager.instances.delete(childInstanceID);
|
|
1081
|
-
}
|
|
1082
|
-
}
|
|
1083
|
-
|
|
1084
|
-
throw new slothlet.SlothletError("UNSUPPORTED_CONTEXT_MANAGER", {
|
|
1085
|
-
manager: contextManager.constructor.name,
|
|
1086
|
-
validationError: true
|
|
1087
|
-
});
|
|
1088
|
-
}
|
|
1089
|
-
}.scope;
|
|
1090
|
-
return scopeFunction;
|
|
1091
|
-
}
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
createDestroyFunction(api) {
|
|
1095
|
-
const slothlet = this.slothlet;
|
|
1096
|
-
const destroyFunction = {
|
|
1097
|
-
destroy: async () => {
|
|
1098
|
-
|
|
1099
|
-
if (slothlet.userHooks?.destroy && typeof slothlet.userHooks.destroy === "function") {
|
|
1100
|
-
await slothlet.userHooks.destroy();
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
if (api && typeof api.shutdown === "function") {
|
|
1105
|
-
await api.shutdown();
|
|
1106
|
-
} else {
|
|
1107
|
-
|
|
1108
|
-
await slothlet.shutdown();
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
slothlet.isDestroyed = true;
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
const objectsToClear = [api, slothlet.api].filter((obj) => obj && typeof obj === "object");
|
|
1118
|
-
|
|
1119
|
-
for (const obj of objectsToClear) {
|
|
1120
|
-
const keys = Object.keys(obj);
|
|
1121
|
-
for (const key of keys) {
|
|
1122
|
-
try {
|
|
1123
|
-
delete obj[key];
|
|
1124
|
-
} catch (_) {
|
|
1125
|
-
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
slothlet.api = null;
|
|
1132
|
-
}
|
|
1133
|
-
}.destroy;
|
|
1134
|
-
return destroyFunction;
|
|
1135
|
-
}
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
attachBuiltins(userApi, builtins) {
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
Object.defineProperty(userApi, "slothlet", {
|
|
1142
|
-
value: builtins.slothlet,
|
|
1143
|
-
enumerable: true,
|
|
1144
|
-
writable: false,
|
|
1145
|
-
configurable: true
|
|
1146
|
-
});
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
Object.defineProperty(userApi, "shutdown", {
|
|
1150
|
-
value: builtins.shutdown,
|
|
1151
|
-
enumerable: true,
|
|
1152
|
-
writable: false,
|
|
1153
|
-
configurable: true
|
|
1154
|
-
});
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
if (builtins.destroy !== null) {
|
|
1162
|
-
Object.defineProperty(userApi, "destroy", {
|
|
1163
|
-
value: builtins.destroy,
|
|
1164
|
-
enumerable: true,
|
|
1165
|
-
writable: false,
|
|
1166
|
-
configurable: true
|
|
1167
|
-
});
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
17
|
+
import{ComponentBase}from"@cldmv/slothlet/factories/component-base";import{TYPE_STATES}from"@cldmv/slothlet/handlers/unified-wrapper";import{getLanguage,initI18n,setLanguage,t,translate}from"@cldmv/slothlet/i18n";function _resolvePathOrModuleId(slothlet,pathOrModuleId){const history=slothlet.handlers?.apiManager?.state?.addHistory;if(history){let match=null;for(let i=history.length-1;i>=0;i--){const entry=history[i];if(entry?.moduleID===pathOrModuleId){match=entry;break}}if(match)return match.apiPath}return pathOrModuleId}class ApiBuilder extends ComponentBase{static slothletProperty="apiBuilder";constructor(slothlet){super(slothlet)}async buildFinalAPI(userApi){this.slothlet.debug("api",{key:"DEBUG_MODE_BUILD_FINAL_API_CALLED",diagnostics:this.____config.diagnostics,userApiKeys:Object.keys(userApi)});if(this.slothlet._ownBuiltins){for(const[key,ref]of Object.entries(this.slothlet._ownBuiltins)){if(ref&&Object.prototype.hasOwnProperty.call(userApi,key)&&userApi[key]===ref){try{delete userApi[key]}catch(_){}}}}this.slothlet.userHooks={shutdown:typeof userApi.shutdown==="function"?userApi.shutdown:null,destroy:typeof userApi.destroy==="function"?userApi.destroy:null};if(userApi.slothlet){new this.SlothletWarning("WARNING_RESERVED_PROPERTY_CONFLICT",{properties:"slothlet"})}const slothletNamespace=await this.createSlothletNamespace(userApi);this.slothlet.debug("api",{key:"DEBUG_MODE_SLOTHLET_NAMESPACE_CREATED",namespaceKeys:Object.keys(slothletNamespace),hasDiag:!!slothletNamespace.diag});const shutdownFn=this.createShutdownFunction();this.attachBuiltins(userApi,{slothlet:slothletNamespace,shutdown:shutdownFn,destroy:null});this.slothlet.debug("api",{key:"DEBUG_MODE_BUILT_INS_ATTACHED",userApiKeys:Object.keys(userApi),hasSlothlet:!!userApi.slothlet,hasDiag:!!userApi.slothlet?.diag});const destroyWithApi=this.createDestroyFunction(userApi);Object.defineProperty(userApi,"destroy",{value:destroyWithApi,enumerable:true,writable:false,configurable:true});this.slothlet._ownBuiltins={shutdown:shutdownFn,slothlet:slothletNamespace,destroy:destroyWithApi};return userApi}async createSlothletNamespace(userApi){const slothlet=this.slothlet;const config=this.____config;let version="unknown";try{const pkgPath=new URL("../../../package.json",import.meta.url);const{readFile}=await import("node:fs/promises");const pkgContent=await readFile(pkgPath,"utf-8");const pkg=JSON.parse(pkgContent);version=pkg.version||"unknown"}catch{}const namespace={i18n:{setLanguage,getLanguage,translate,t,initI18n},version,instanceID:slothlet.instanceID,types:TYPE_STATES,api:{add:async function slothlet_api_add(apiPath,folderPath,options={},versionConfig=null){if(!config.api?.mutations?.add){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.add",validationError:true})}const{recordHistory:____recordHistory,collisionMode:____collisionMode,mutateExisting:____mutateExisting,...filteredOptions}=options;return slothlet.handlers.apiManager.addApiComponent({apiPath,folderPath,options:filteredOptions,versionConfig:versionConfig||null})},remove:async function slothlet_api_remove(pathOrModuleId){if(!config.api?.mutations?.remove){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.remove",validationError:true})}if(typeof pathOrModuleId!=="string"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"pathOrModuleId",expected:"string",received:typeof pathOrModuleId,validationError:true})}return slothlet.handlers.apiManager.removeApiComponent(pathOrModuleId)},reload:async function slothlet_api_reload(pathOrModuleId,options){if(!config.api?.mutations?.reload){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.reload",validationError:true})}if(pathOrModuleId==null||pathOrModuleId===""||pathOrModuleId==="."){return slothlet.handlers.apiManager.reloadApiComponent({apiPath:".",options})}if(typeof pathOrModuleId!=="string"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"pathOrModuleId",expected:"string, null, undefined, or '.'",received:typeof pathOrModuleId,validationError:true})}const isModuleId=slothlet.handlers.apiManager.state.addHistory.some(entry=>entry.moduleID===pathOrModuleId);if(isModuleId){return slothlet.handlers.apiManager.reloadApiComponent({moduleID:pathOrModuleId,options})}const normalizedPath=slothlet.handlers.apiManager.normalizeApiPath(pathOrModuleId).apiPath;const pathParts=normalizedPath.split(".");let current=slothlet.api;for(const part of pathParts){if(!current||typeof current!=="object"&&typeof current!=="function"){throw new slothlet.SlothletError("INVALID_API_PATH",{apiPath:pathOrModuleId,validationError:true})}current=current[part]}if(current===void 0){throw new slothlet.SlothletError("INVALID_API_PATH",{apiPath:pathOrModuleId,validationError:true})}return slothlet.handlers.apiManager.reloadApiComponent({apiPath:normalizedPath,options})}},sanitize:function slothlet_sanitize(str){if(typeof str!=="string"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"str",expected:"string",received:typeof str,validationError:true})}return slothlet.helpers.sanitize.sanitizePropertyName(str,slothlet.config.sanitize||{})},context:{get:key=>{if(slothlet.contextManager.constructor.name==="LiveContextManager"){const currentID=slothlet.contextManager.currentInstanceID;if(currentID){const activeStore=slothlet.contextManager.instances.get(currentID);const isOurInstance=currentID===slothlet.instanceID||currentID?.startsWith(slothlet.instanceID+"__run_")||activeStore?.parentInstanceID===slothlet.instanceID;if(isOurInstance&&activeStore){return key?activeStore.context[key]:{...activeStore.context}}}const store=slothlet.contextManager.instances.get(slothlet.instanceID);if(!store){const baseContext2=slothlet.context||{};return key?baseContext2[key]:{...baseContext2}}return key?store.context[key]:{...store.context}}if(slothlet.contextManager.constructor.name==="AsyncContextManager"){let currentStore=slothlet.contextManager.tryGetContext();if(!currentStore){const baseStore2=slothlet.contextManager.instances.get(slothlet.instanceID);const baseContext3=baseStore2?.context||{};return key?baseContext3[key]:{...baseContext3}}const isOurInstance=currentStore.instanceID===slothlet.instanceID||currentStore.parentInstanceID===slothlet.instanceID||currentStore.instanceID.startsWith(slothlet.instanceID+"__run_");if(isOurInstance){return key?currentStore.context[key]:{...currentStore.context}}const baseStore=slothlet.contextManager.instances.get(slothlet.instanceID);const baseContext2=baseStore?.context||{};return key?baseContext2[key]:{...baseContext2}}const baseContext=slothlet.context||{};return key?baseContext[key]:{...baseContext}},diagnostics:()=>{if(!slothlet.config?.diagnostics)return void 0;const managerType=slothlet.contextManager.constructor.name;const result={instanceID:slothlet.instanceID,managerType,instancesMapSize:slothlet.contextManager.instances.size,instancesMapKeys:Array.from(slothlet.contextManager.instances.keys()),baseContext:slothlet.context};const store=slothlet.contextManager.instances.get(slothlet.instanceID);result.storeFromInstancesMap=store?{instanceID:store.instanceID,context:store.context,createdAt:store.createdAt}:null;if(managerType==="AsyncContextManager"){try{const currentCtx=slothlet.contextManager.tryGetContext();result.currentALSContext=currentCtx?{instanceID:currentCtx.instanceID,context:currentCtx.context,hasParent:!!currentCtx.parentContext,parentInstanceID:currentCtx.parentInstanceID}:null}catch(____error){result.currentALSContext=null}}if(managerType==="LiveContextManager"){result.currentInstanceID=slothlet.contextManager.currentInstanceID}return result},run:this.createRunFunction(),scope:this.createScopeFunction()},hook:{on:function slothlet_hook_on(typePattern,handler,options={}){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.on(typePattern,handler,options)},remove:function slothlet_hook_remove(filter={}){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.remove(filter)},clear:function slothlet_hook_clear(filter={}){return this.remove(filter)},off:function slothlet_hook_off(idOrFilter){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}const filter=typeof idOrFilter==="string"?{id:idOrFilter}:idOrFilter;return slothlet.handlers.hookManager.remove(filter)},enable:function slothlet_hook_enable(filter={}){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.enable(filter)},disable:function slothlet_hook_disable(filter={}){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.disable(filter)},list:function slothlet_hook_list(filter={}){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.list(filter)}},metadata:{setGlobal:function slothlet_metadata_setGlobal(key,value){if(!slothlet.handlers?.metadata){throw new slothlet.SlothletError("METADATA_NOT_AVAILABLE",{handlersKeys:slothlet.handlers?Object.keys(slothlet.handlers).join(", "):"undefined",validationError:true})}return slothlet.handlers.metadata.setGlobalMetadata(key,value)},set:function slothlet_metadata_set(fn,key,value){if(!slothlet.handlers?.metadata){throw new slothlet.SlothletError("METADATA_NOT_AVAILABLE",{handlersKeys:slothlet.handlers?Object.keys(slothlet.handlers).join(", "):"undefined",validationError:true})}return slothlet.handlers.metadata.setUserMetadata(fn,key,value)},remove:function slothlet_metadata_remove(fn,key){return slothlet.handlers.metadata.removeUserMetadata(fn,key)},setFor:function slothlet_metadata_setFor(pathOrModuleId,keyOrObj,value){if(!slothlet.handlers?.metadata){throw new slothlet.SlothletError("METADATA_NOT_AVAILABLE",{handlersKeys:slothlet.handlers?Object.keys(slothlet.handlers).join(", "):"undefined",validationError:true})}const resolvedPath=_resolvePathOrModuleId(slothlet,pathOrModuleId);return slothlet.handlers.metadata.setPathMetadata(resolvedPath,keyOrObj,value)},removeFor:function slothlet_metadata_removeFor(pathOrModuleId,key){if(!slothlet.handlers?.metadata)return;const resolvedPath=_resolvePathOrModuleId(slothlet,pathOrModuleId);return slothlet.handlers.metadata.removePathMetadata(resolvedPath,key)},setForVersion:function slothlet_metadata_setForVersion(logicalPath,versionTag,keyOrObj,value){if(!slothlet.handlers?.metadata){throw new slothlet.SlothletError("METADATA_NOT_AVAILABLE",{handlersKeys:slothlet.handlers?Object.keys(slothlet.handlers).join(", "):"undefined",validationError:true})}const info=slothlet.handlers?.versionManager?.list(logicalPath);if(!info||!info.versions?.[versionTag]){throw new slothlet.SlothletError("VERSION_NOT_FOUND",{version:versionTag,apiPath:logicalPath})}const{moduleID}=info.versions[versionTag];const resolvedPath=_resolvePathOrModuleId(slothlet,moduleID);return slothlet.handlers.metadata.setPathMetadata(resolvedPath,keyOrObj,value)},getForVersion:function slothlet_metadata_getForVersion(logicalPath,versionTag){if(!slothlet.handlers?.metadata)return{};const info=slothlet.handlers?.versionManager?.list(logicalPath);if(!info||!info.versions?.[versionTag])return{};const{moduleID}=info.versions[versionTag];const resolvedPath=_resolvePathOrModuleId(slothlet,moduleID);return slothlet.handlers.metadata.getPathMetadata(resolvedPath)}},scope:this.createScopeFunction(),run:this.createRunFunction(),reload:async(options={})=>{if(!config.api?.mutations?.reload){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"reload",validationError:true})}return slothlet.reload(options)},shutdown:async()=>{return slothlet.shutdown()},owner:{get:apiPath=>{if(slothlet.handlers?.ownership){return slothlet.handlers.ownership.getPathOwnership(apiPath)}return null}},materialize:(()=>{const mgr=slothlet.handlers?.materialize;if(!mgr){return Object.freeze({materialized:false,get:()=>({total:0,materialized:0,remaining:0,percentage:100}),wait:async()=>{}})}return Object.freeze({get materialized(){return mgr.materialized},get:mgr.get.bind(mgr),wait:mgr.wait.bind(mgr)})})(),lifecycle:(()=>{const handler=slothlet.handlers?.lifecycle;const noop=()=>{};if(!handler)return{on:noop,off:noop};return{on:handler.on.bind(handler),off:handler.off.bind(handler)}})(),env:slothlet.envSnapshot,versioning:{list:function slothlet_version_list(logicalPath){if(!slothlet.handlers?.versionManager)return void 0;return slothlet.handlers.versionManager.list(logicalPath)},setDefault:function slothlet_version_setDefault(logicalPath,versionTag){if(!slothlet.handlers?.versionManager)return;return slothlet.handlers.versionManager.setDefault(logicalPath,versionTag)},unregister:async function slothlet_version_unregister(logicalPath,versionTag){if(!slothlet.handlers?.versionManager)return false;const info=slothlet.handlers.versionManager.list(logicalPath);if(!info||!info.versions?.[versionTag])return false;const{moduleID:versionedModuleID}=info.versions[versionTag];await slothlet.handlers.apiManager.removeApiComponent(versionedModuleID);return true},getVersionMetadata:function slothlet_version_getVersionMetadata(logicalPath,versionTag){if(!slothlet.handlers?.versionManager)return void 0;return slothlet.handlers.versionManager.getVersionMetadataByPath(logicalPath,versionTag)},setVersionMetadata:function slothlet_version_setVersionMetadata(logicalPath,versionTag,patch){if(!slothlet.handlers?.versionManager)return;return slothlet.handlers.versionManager.setVersionMetadataByPath(logicalPath,versionTag,patch)}},permissions:{addRule:function slothlet_permissions_addRule(rule){if(!config.api?.mutations?.permissions){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.slothlet.permissions.addRule",validationError:true})}const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.addRule){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}const ruleId=permissionManager.addRule(rule,null);if(slothlet.handlers?.apiManager?.state?.operationHistory){slothlet.handlers.apiManager.state.operationHistory.push({type:"addPermissionRule",rule,ownerModuleID:null,ruleId,timestamp:Date.now()})}return ruleId},removeRule:function slothlet_permissions_removeRule(ruleId){if(!config.api?.mutations?.permissions){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.slothlet.permissions.removeRule",validationError:true})}const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.removeRule){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}const ctx=slothlet.contextManager?.tryGetContext?.();const currentWrapper=ctx?.currentWrapper;const callerModuleID=currentWrapper?.____slothletInternal?.moduleID??null;const result=slothlet.handlers.permissionManager.removeRule(ruleId,callerModuleID);if(result&&slothlet.handlers?.apiManager?.state?.operationHistory){slothlet.handlers.apiManager.state.operationHistory.push({type:"removePermissionRule",ruleId,callerModuleID,timestamp:Date.now()})}return result},self:{access:function slothlet_permissions_self_access(target){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.checkAccess){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}const currentWrapper=slothlet.contextManager?.tryGetContext?.()?.currentWrapper;const callerPath=currentWrapper?.____slothletInternal?.apiPath??"";const callerFilePath=currentWrapper?.____slothletInternal?.filePath??null;return slothlet.handlers.permissionManager.checkAccess(callerPath,target,callerFilePath,null)},rules:function slothlet_permissions_self_rules(){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.getRulesForCaller){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}const currentWrapper=slothlet.contextManager?.tryGetContext?.()?.currentWrapper;const callerPath=currentWrapper?.____slothletInternal?.apiPath??"";return slothlet.handlers.permissionManager.getRulesForCaller(callerPath)}},global:{checkAccess:function slothlet_permissions_global_checkAccess(caller,target){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.checkAccess){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}return slothlet.handlers.permissionManager.checkAccess(caller,target)},rulesForPath:function slothlet_permissions_global_rulesForPath(path){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.getRulesForPath){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}return slothlet.handlers.permissionManager.getRulesForPath(path)},rulesByModule:function slothlet_permissions_global_rulesByModule(moduleID){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.getRulesByModule){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}return slothlet.handlers.permissionManager.getRulesByModule(moduleID)}},control:{enable:function slothlet_permissions_control_enable(){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.enable){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}const ctx=slothlet.contextManager?.tryGetContext?.();const callerWrapper=ctx?.currentWrapper;if(callerWrapper){const callerPath=callerWrapper.____slothletInternal?.apiPath??"";const callerFilePath=callerWrapper.____slothletInternal?.filePath??null;if(!permissionManager.checkAccess(callerPath,"slothlet.permissions.control.enable",callerFilePath,null)){throw new slothlet.SlothletError("PERMISSION_DENIED",{caller:callerPath,target:"slothlet.permissions.control.enable"})}}slothlet.handlers.permissionManager.enable()},disable:function slothlet_permissions_control_disable(){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.disable){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}const ctx=slothlet.contextManager?.tryGetContext?.();const callerWrapper=ctx?.currentWrapper;if(callerWrapper){const callerPath=callerWrapper.____slothletInternal?.apiPath??"";const callerFilePath=callerWrapper.____slothletInternal?.filePath??null;if(!permissionManager.checkAccess(callerPath,"slothlet.permissions.control.disable",callerFilePath,null)){throw new slothlet.SlothletError("PERMISSION_DENIED",{caller:callerPath,target:"slothlet.permissions.control.disable"})}}slothlet.handlers.permissionManager.disable()}}}};if(!config.hook?.enabled&&config.diagnostics!==true){delete namespace.hooks}if(config.diagnostics===true){namespace.diag={describe:(showAll=false)=>{if(showAll){return{...userApi}}return Reflect.ownKeys(userApi)},reference:slothlet.reference||null,context:slothlet.context||{},inspect:()=>{return slothlet.getDiagnostics()},getAPI:()=>{return slothlet.getAPI()},getOwnership:()=>{return slothlet.getOwnership()},owner:{get:apiPath=>{if(slothlet.handlers?.ownership){return slothlet.handlers.ownership.getPathOwnership(apiPath)}return null}},caches:{get:()=>{if(slothlet.handlers?.apiCacheManager){return slothlet.handlers.apiCacheManager.getCacheDiagnostics()}return{totalCaches:0,caches:[]}},getAllModuleIDs:()=>{if(slothlet.handlers?.apiCacheManager){return slothlet.handlers.apiCacheManager.getAllModuleIDs()}return[]},has:moduleID=>{if(slothlet.handlers?.apiCacheManager){return slothlet.handlers.apiCacheManager.has(moduleID)}return false}},SlothletWarning:slothlet.SlothletWarning,hook:slothlet.handlers?.hookManager?{get enabled(){return slothlet.handlers.hookManager.enabled},compilePattern:pattern=>{return slothlet.handlers.hookManager.getCompilePatternForDiagnostics()(pattern)}}:void 0}}return namespace}createShutdownFunction(){const slothlet=this.slothlet;const shutdownFunction={shutdown:async()=>{if(slothlet.userHooks?.shutdown&&typeof slothlet.userHooks.shutdown==="function"){await slothlet.userHooks.shutdown()}return slothlet.shutdown()}}.shutdown;return shutdownFunction}createRunFunction(){const slothlet=this.slothlet;const scopeFunc=this.createScopeFunction();const runFunction={run:async(contextData,callback,...args)=>{if(slothlet.config.scope===false){throw new slothlet.SlothletError("SCOPE_DISABLED",{},null,{validationError:true})}if(!contextData||typeof contextData!=="object"){throw new slothlet.SlothletError("SCOPE_INVALID_CONTEXT",{received:typeof contextData},null,{validationError:true})}if(typeof callback!=="function"){throw new slothlet.SlothletError("SCOPE_INVALID_CALLBACK",{received:typeof callback},null,{validationError:true})}return scopeFunc({context:contextData,fn:callback,args,merge:slothlet.config.scope?.merge||"shallow",isolation:slothlet.config.scope?.isolation||"partial"})}}.run;return runFunction}createScopeFunction(){const slothlet=this.slothlet;const scopeFunction={scope:async options=>{if(slothlet.config.scope===false){throw new slothlet.SlothletError("SCOPE_DISABLED",{},null,{validationError:true})}if(!options||typeof options!=="object"){throw new slothlet.SlothletError("SCOPE_INVALID_OPTIONS",{received:typeof options},null,{validationError:true})}if(!options.fn||typeof options.fn!=="function"){throw new slothlet.SlothletError("SCOPE_INVALID_FN",{received:typeof options?.fn},null,{validationError:true})}if(!options.context||typeof options.context!=="object"){throw new slothlet.SlothletError("SCOPE_INVALID_CONTEXT_OBJECT",{received:typeof options?.context},null,{validationError:true})}const{context:contextData,fn,args=[],merge="shallow",isolation}=options;if(merge!=="shallow"&&merge!=="deep"){throw new slothlet.SlothletError("SCOPE_INVALID_MERGE_STRATEGY",{merge},null,{validationError:true})}const isolationMode=isolation||slothlet.config.scope?.isolation||"partial";if(isolationMode!=="partial"&&isolationMode!=="full"){throw new slothlet.SlothletError("SCOPE_INVALID_ISOLATION_MODE",{isolationMode},null,{validationError:true})}const contextManager=slothlet.contextManager;if(!contextManager){throw new slothlet.SlothletError("NO_CONTEXT_MANAGER",{validationError:true})}const{utilities}=slothlet.helpers;if(contextManager.constructor.name==="LiveContextManager"){let currentStore=null;const currentID=contextManager.currentInstanceID;if(currentID){const activeStore=contextManager.instances.get(currentID);const isOurContext=currentID===slothlet.instanceID||activeStore?.parentInstanceID===slothlet.instanceID||currentID.startsWith(slothlet.instanceID+"__run_");if(isOurContext){currentStore=activeStore}}if(!currentStore){currentStore=contextManager.instances.get(slothlet.instanceID)}if(!currentStore){throw new slothlet.SlothletError("CONTEXT_NOT_FOUND",{instanceID:slothlet.instanceID,availableInstances:[...contextManager.instances.keys()].join(", ")||"none",validationError:true})}let mergedContext;if(merge==="deep"){mergedContext=utilities.deepMerge(currentStore.context,contextData);mergedContext=structuredClone(mergedContext)}else{const clonedParent=structuredClone(currentStore.context);mergedContext={...clonedParent,...contextData}}const childInstanceID=`${slothlet.instanceID}__run_${Date.now()}_${Math.random().toString(36).slice(2,9)}`;const childStore={instanceID:childInstanceID,context:mergedContext,self:isolationMode==="full"?utilities.deepClone(currentStore.self):currentStore.self,config:currentStore.config,createdAt:currentStore.createdAt,parentInstanceID:slothlet.instanceID};contextManager.instances.set(childInstanceID,childStore);const previousInstanceID=contextManager.currentInstanceID;try{contextManager.currentInstanceID=childInstanceID;return await fn(...args)}finally{contextManager.currentInstanceID=previousInstanceID;contextManager.instances.delete(childInstanceID)}}if(contextManager.constructor.name==="AsyncContextManager"){let currentStore=null;const activeStore=contextManager.tryGetContext();if(activeStore){const isOurContext=activeStore.instanceID===slothlet.instanceID||activeStore.parentInstanceID===slothlet.instanceID||activeStore.instanceID.startsWith(slothlet.instanceID+"__run_");if(isOurContext){currentStore=activeStore}}if(!currentStore){const baseStore=contextManager.instances.get(slothlet.instanceID);if(!baseStore){throw new slothlet.SlothletError("CONTEXT_NOT_FOUND",{instanceID:slothlet.instanceID,availableInstances:[...contextManager.instances.keys()].join(", ")||"none",validationError:true})}currentStore=baseStore}let mergedContext;if(merge==="deep"){mergedContext=utilities.deepMerge(currentStore.context,contextData);mergedContext=structuredClone(mergedContext)}else{const clonedParent=structuredClone(currentStore.context);mergedContext={...clonedParent,...contextData}}const childInstanceID=`${slothlet.instanceID}__run_${Date.now()}_${Math.random().toString(36).slice(2,9)}`;const childStore={instanceID:childInstanceID,context:mergedContext,self:isolationMode==="full"?utilities.deepClone(currentStore.self):currentStore.self,config:currentStore.config,createdAt:currentStore.createdAt,parentInstanceID:slothlet.instanceID};contextManager.instances.set(childInstanceID,childStore);try{return await contextManager.als.run(childStore,async()=>{return await fn(...args)})}finally{contextManager.instances.delete(childInstanceID)}}throw new slothlet.SlothletError("UNSUPPORTED_CONTEXT_MANAGER",{manager:contextManager.constructor.name,validationError:true})}}.scope;return scopeFunction}createDestroyFunction(api){const slothlet=this.slothlet;const destroyFunction={destroy:async()=>{if(slothlet.userHooks?.destroy&&typeof slothlet.userHooks.destroy==="function"){await slothlet.userHooks.destroy()}if(api&&typeof api.shutdown==="function"){await api.shutdown()}else{await slothlet.shutdown()}slothlet.isDestroyed=true;const objectsToClear=[api,slothlet.api].filter(obj=>obj&&typeof obj==="object");for(const obj of objectsToClear){const keys=Object.keys(obj);for(const key of keys){try{delete obj[key]}catch(_){}}}slothlet.api=null}}.destroy;return destroyFunction}attachBuiltins(userApi,builtins){Object.defineProperty(userApi,"slothlet",{value:builtins.slothlet,enumerable:true,writable:false,configurable:true});Object.defineProperty(userApi,"shutdown",{value:builtins.shutdown,enumerable:true,writable:false,configurable:true});if(builtins.destroy!==null){Object.defineProperty(userApi,"destroy",{value:builtins.destroy,enumerable:true,writable:false,configurable:true})}}}export{ApiBuilder};
|