@cldmv/slothlet 2.8.0 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT-USAGE.md +1 -1
- package/README.md +253 -1578
- package/dist/lib/helpers/als-eventemitter.mjs +4 -5
- package/dist/lib/helpers/api_builder/add_api.mjs +237 -0
- package/dist/lib/helpers/api_builder/analysis.mjs +522 -0
- package/dist/lib/helpers/api_builder/construction.mjs +457 -0
- package/dist/lib/helpers/api_builder/decisions.mjs +737 -0
- package/dist/lib/helpers/api_builder.mjs +16 -1567
- package/dist/lib/helpers/utilities.mjs +121 -0
- package/dist/lib/runtime/runtime-asynclocalstorage.mjs +44 -17
- package/dist/lib/runtime/runtime-livebindings.mjs +18 -3
- package/dist/lib/runtime/runtime.mjs +3 -3
- package/dist/slothlet.mjs +146 -746
- package/docs/API-RULES-CONDITIONS.md +508 -0
- package/{API-RULES.md → docs/API-RULES.md} +127 -72
- package/package.json +11 -9
- package/types/dist/lib/helpers/als-eventemitter.d.mts.map +1 -1
- package/types/dist/lib/helpers/api_builder/add_api.d.mts +60 -0
- package/types/dist/lib/helpers/api_builder/add_api.d.mts.map +1 -0
- package/types/dist/lib/helpers/api_builder/analysis.d.mts +189 -0
- package/types/dist/lib/helpers/api_builder/analysis.d.mts.map +1 -0
- package/types/dist/lib/helpers/api_builder/construction.d.mts +107 -0
- package/types/dist/lib/helpers/api_builder/construction.d.mts.map +1 -0
- package/types/dist/lib/helpers/api_builder/decisions.d.mts +213 -0
- package/types/dist/lib/helpers/api_builder/decisions.d.mts.map +1 -0
- package/types/dist/lib/helpers/api_builder.d.mts +5 -448
- package/types/dist/lib/helpers/api_builder.d.mts.map +1 -1
- package/types/dist/lib/helpers/utilities.d.mts +120 -0
- package/types/dist/lib/helpers/utilities.d.mts.map +1 -0
- package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts +7 -0
- package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts.map +1 -1
- package/types/dist/lib/runtime/runtime-livebindings.d.mts +8 -0
- package/types/dist/lib/runtime/runtime-livebindings.d.mts.map +1 -1
- package/types/dist/slothlet.d.mts +0 -11
- package/types/dist/slothlet.d.mts.map +1 -1
- package/types/index.d.mts +0 -1
- package/API-RULES-CONDITIONS.md +0 -367
package/dist/slothlet.mjs
CHANGED
|
@@ -19,20 +19,23 @@
|
|
|
19
19
|
|
|
20
20
|
import fs from "node:fs/promises";
|
|
21
21
|
import path from "node:path";
|
|
22
|
-
import { types as utilTypes } from "node:util";
|
|
23
22
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
24
23
|
|
|
25
24
|
import { resolvePathFromCaller } from "@cldmv/slothlet/helpers/resolve-from-caller";
|
|
26
|
-
import { sanitizePathName } from "@cldmv/slothlet/helpers/sanitize";
|
|
27
25
|
import {
|
|
28
26
|
analyzeModule,
|
|
29
27
|
processModuleFromAnalysis,
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
buildCategoryStructure,
|
|
29
|
+
toapiPathKey,
|
|
30
|
+
shouldIncludeFile,
|
|
31
|
+
safeDefine,
|
|
32
|
+
deepMerge,
|
|
33
|
+
mutateLiveBindingFunction,
|
|
34
|
+
addApiFromFolder
|
|
32
35
|
} from "@cldmv/slothlet/helpers/api_builder";
|
|
33
|
-
import { updateInstanceData, cleanupInstance } from "
|
|
34
|
-
import { disableAlsForEventEmitters, cleanupAllSlothletListeners } from "
|
|
35
|
-
import { HookManager } from "
|
|
36
|
+
import { updateInstanceData, cleanupInstance } from "@cldmv/slothlet/helpers/instance-manager";
|
|
37
|
+
import { disableAlsForEventEmitters, cleanupAllSlothletListeners } from "@cldmv/slothlet/helpers/als-eventemitter";
|
|
38
|
+
import { HookManager } from "@cldmv/slothlet/helpers/hooks";
|
|
36
39
|
|
|
37
40
|
|
|
38
41
|
|
|
@@ -177,31 +180,18 @@ const slothletObject = {
|
|
|
177
180
|
if (!this.modes) {
|
|
178
181
|
this.modes = {};
|
|
179
182
|
const modesDir = path.join(__dirname, "lib", "modes");
|
|
180
|
-
|
|
181
|
-
|
|
183
|
+
|
|
182
184
|
const dirents = await fs.readdir(modesDir, { withFileTypes: true });
|
|
183
185
|
const modeFiles = dirents.filter((d) => d.isFile()).map((d) => path.join(modesDir, d.name));
|
|
184
|
-
|
|
185
|
-
|
|
186
186
|
|
|
187
187
|
for (const file of modeFiles) {
|
|
188
|
-
|
|
189
|
-
|
|
190
188
|
const modePath = file;
|
|
191
189
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
190
|
const modeName = path.parse(file).name.replace(/^slothlet_/, "");
|
|
198
191
|
if (!modeName || modeName.includes(" ")) continue;
|
|
199
192
|
try {
|
|
200
193
|
|
|
201
194
|
const modeUrl = pathToFileURL(modePath).href;
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
195
|
|
|
206
196
|
const imported = await import(modeUrl);
|
|
207
197
|
if (imported && typeof imported === "object") {
|
|
@@ -213,10 +203,6 @@ const slothletObject = {
|
|
|
213
203
|
}
|
|
214
204
|
}
|
|
215
205
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
206
|
this.mode = executionEngine;
|
|
221
207
|
this.api_mode = api_mode;
|
|
222
208
|
let api;
|
|
@@ -224,7 +210,7 @@ const slothletObject = {
|
|
|
224
210
|
if (executionEngine === "singleton") {
|
|
225
211
|
|
|
226
212
|
|
|
227
|
-
const { context = null, reference = null, sanitize = null, hooks = false, engine, mode, ...loadConfig } = options;
|
|
213
|
+
const { context = null, reference = null, sanitize = null, hooks = false, scope, engine, mode, ...loadConfig } = options;
|
|
228
214
|
this.context = context;
|
|
229
215
|
this.reference = reference;
|
|
230
216
|
|
|
@@ -252,6 +238,20 @@ const slothletObject = {
|
|
|
252
238
|
this.hookManager = new HookManager(hooksEnabled, hooksPattern, { suppressErrors: hooksSuppressErrors });
|
|
253
239
|
|
|
254
240
|
|
|
241
|
+
if (scope && typeof scope === "object") {
|
|
242
|
+
const mergeStrategy = scope.merge || "shallow";
|
|
243
|
+
if (mergeStrategy !== "shallow" && mergeStrategy !== "deep") {
|
|
244
|
+
throw new TypeError(`Invalid scope.merge value: "${mergeStrategy}". Must be "shallow" or "deep".`);
|
|
245
|
+
}
|
|
246
|
+
this.config.scope = { merge: mergeStrategy };
|
|
247
|
+
} else if (scope === false) {
|
|
248
|
+
this.config.scope = { enabled: false };
|
|
249
|
+
} else {
|
|
250
|
+
|
|
251
|
+
this.config.scope = { merge: "shallow" };
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
|
|
255
255
|
if (sanitize !== null) {
|
|
256
256
|
this.config.sanitize = sanitize;
|
|
257
257
|
}
|
|
@@ -278,9 +278,6 @@ const slothletObject = {
|
|
|
278
278
|
await this.load(loadConfig, { context, reference });
|
|
279
279
|
|
|
280
280
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
281
|
return this.boundapi;
|
|
285
282
|
} else {
|
|
286
283
|
const { createEngine } = await import("./lib/engine/slothlet_engine.mjs");
|
|
@@ -318,17 +315,10 @@ const slothletObject = {
|
|
|
318
315
|
}
|
|
319
316
|
}
|
|
320
317
|
|
|
321
|
-
|
|
322
|
-
|
|
323
318
|
let apiDir = this.config.dir || "api";
|
|
324
319
|
|
|
325
320
|
if (apiDir && !path.isAbsolute(apiDir)) {
|
|
326
|
-
|
|
327
321
|
apiDir = resolvePathFromCaller(apiDir);
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
322
|
}
|
|
333
323
|
|
|
334
324
|
if (this.loaded) return this.api;
|
|
@@ -381,70 +371,22 @@ const slothletObject = {
|
|
|
381
371
|
}
|
|
382
372
|
}
|
|
383
373
|
|
|
384
|
-
|
|
385
|
-
|
|
386
374
|
const l_ctxRef = { ...{ context: null, reference: null }, ...ctxRef };
|
|
387
375
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
376
|
const _boundapi = this.createBoundApi(l_ctxRef.reference);
|
|
392
377
|
|
|
393
378
|
mutateLiveBindingFunction(this.boundapi, _boundapi);
|
|
394
379
|
|
|
395
380
|
this.updateBindings(this.context, this.reference, this.boundapi);
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
this.loaded = true;
|
|
405
381
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
382
|
+
this.loaded = true;
|
|
440
383
|
|
|
441
384
|
return this.boundapi;
|
|
442
385
|
},
|
|
443
386
|
|
|
444
387
|
|
|
445
388
|
_toapiPathKey(name) {
|
|
446
|
-
return
|
|
447
|
-
|
|
389
|
+
return toapiPathKey(name, this.config.sanitize || {});
|
|
448
390
|
},
|
|
449
391
|
|
|
450
392
|
|
|
@@ -452,288 +394,13 @@ const slothletObject = {
|
|
|
452
394
|
const { currentDepth = 0, maxDepth = Infinity, mode = "eager", subdirHandler } = options;
|
|
453
395
|
|
|
454
396
|
|
|
455
|
-
|
|
397
|
+
return buildCategoryStructure(categoryPath, {
|
|
456
398
|
currentDepth,
|
|
457
399
|
maxDepth,
|
|
458
400
|
mode,
|
|
459
401
|
subdirHandler,
|
|
460
402
|
instance: this
|
|
461
403
|
});
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
if (decisions.type === "single-file") {
|
|
465
|
-
const { singleFile } = decisions;
|
|
466
|
-
const { mod, moduleName } = singleFile;
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
if (decisions.shouldFlatten) {
|
|
470
|
-
switch (decisions.flattenType) {
|
|
471
|
-
case "function-folder-match":
|
|
472
|
-
case "default-function":
|
|
473
|
-
try {
|
|
474
|
-
Object.defineProperty(mod, "name", { value: decisions.preferredName, configurable: true });
|
|
475
|
-
} catch {
|
|
476
|
-
|
|
477
|
-
}
|
|
478
|
-
return mod;
|
|
479
|
-
|
|
480
|
-
case "default-export-flatten":
|
|
481
|
-
|
|
482
|
-
return mod;
|
|
483
|
-
|
|
484
|
-
case "object-auto-flatten":
|
|
485
|
-
|
|
486
|
-
return mod[decisions.preferredName];
|
|
487
|
-
|
|
488
|
-
case "parent-level-flatten": {
|
|
489
|
-
|
|
490
|
-
const exportValue = mod[Object.keys(mod).filter((k) => k !== "default")[0]];
|
|
491
|
-
return { [decisions.preferredName]: exportValue };
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
case "filename-folder-match-flatten":
|
|
495
|
-
|
|
496
|
-
return mod;
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
if (decisions.preferredName && decisions.preferredName !== moduleName) {
|
|
502
|
-
return { [decisions.preferredName]: mod };
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
return { [moduleName]: mod };
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
const categoryModules = {};
|
|
511
|
-
const { categoryName, processedModules, subdirectoryDecisions } = decisions;
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
for (const moduleDecision of processedModules) {
|
|
515
|
-
const { moduleName, mod, type, apiPathKey, shouldFlatten, flattenType, specialHandling, processedExports } = moduleDecision;
|
|
516
|
-
|
|
517
|
-
if (specialHandling === "category-merge") {
|
|
518
|
-
|
|
519
|
-
if (
|
|
520
|
-
Object.prototype.hasOwnProperty.call(mod, categoryName) &&
|
|
521
|
-
typeof mod[categoryName] === "object" &&
|
|
522
|
-
mod[categoryName] !== null
|
|
523
|
-
) {
|
|
524
|
-
Object.assign(categoryModules, mod[categoryName]);
|
|
525
|
-
for (const [key, value] of Object.entries(mod)) {
|
|
526
|
-
if (key !== categoryName) categoryModules[this._toapiPathKey(key)] = value;
|
|
527
|
-
}
|
|
528
|
-
} else {
|
|
529
|
-
Object.assign(categoryModules, mod);
|
|
530
|
-
}
|
|
531
|
-
} else if (type === "function") {
|
|
532
|
-
|
|
533
|
-
if (specialHandling === "multi-default-filename") {
|
|
534
|
-
try {
|
|
535
|
-
Object.defineProperty(mod, "name", { value: moduleName, configurable: true });
|
|
536
|
-
} catch {
|
|
537
|
-
|
|
538
|
-
}
|
|
539
|
-
categoryModules[moduleName] = mod;
|
|
540
|
-
} else if (specialHandling === "prefer-function-name") {
|
|
541
|
-
categoryModules[apiPathKey] = mod;
|
|
542
|
-
} else {
|
|
543
|
-
|
|
544
|
-
categoryModules[apiPathKey] = mod;
|
|
545
|
-
}
|
|
546
|
-
} else if (type === "self-referential") {
|
|
547
|
-
|
|
548
|
-
categoryModules[moduleName] = mod[moduleName] || mod;
|
|
549
|
-
} else if (type === "object") {
|
|
550
|
-
|
|
551
|
-
if (specialHandling === "preferred-export-names") {
|
|
552
|
-
Object.assign(categoryModules, processedExports);
|
|
553
|
-
} else if (shouldFlatten) {
|
|
554
|
-
switch (flattenType) {
|
|
555
|
-
case "single-default-object": {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
let flattened;
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
const defaultExport = mod.default;
|
|
562
|
-
const hasNamedExports = Object.keys(mod).some((k) => k !== "default");
|
|
563
|
-
|
|
564
|
-
if (hasNamedExports && defaultExport && typeof defaultExport === "object") {
|
|
565
|
-
|
|
566
|
-
const isProxy = utilTypes?.isProxy?.(defaultExport) ?? false;
|
|
567
|
-
|
|
568
|
-
if (isProxy) {
|
|
569
|
-
|
|
570
|
-
flattened = defaultExport;
|
|
571
|
-
let assignmentFailed = false;
|
|
572
|
-
|
|
573
|
-
const failedMap = new Map();
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
for (const [key, value] of Object.entries(mod)) {
|
|
577
|
-
if (key !== "default") {
|
|
578
|
-
try {
|
|
579
|
-
flattened[key] = value;
|
|
580
|
-
} catch (e) {
|
|
581
|
-
|
|
582
|
-
assignmentFailed = true;
|
|
583
|
-
failedMap.set(key, value);
|
|
584
|
-
if (this.config?.debug) {
|
|
585
|
-
console.warn(
|
|
586
|
-
`Could not assign '${key}' to proxy object in module '${moduleName}' at '${categoryPath}':`,
|
|
587
|
-
e.message
|
|
588
|
-
);
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
if (assignmentFailed) {
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
const originalProxy = flattened;
|
|
605
|
-
flattened = new Proxy(originalProxy, {
|
|
606
|
-
get(target, prop, receiver) {
|
|
607
|
-
|
|
608
|
-
if (failedMap.has(prop)) return failedMap.get(prop);
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
return Reflect.get(target, prop, receiver);
|
|
612
|
-
},
|
|
613
|
-
has(target, prop) {
|
|
614
|
-
|
|
615
|
-
if (failedMap.has(prop)) return true;
|
|
616
|
-
return Reflect.has(target, prop);
|
|
617
|
-
},
|
|
618
|
-
ownKeys(target) {
|
|
619
|
-
const originalKeys = Reflect.ownKeys(target);
|
|
620
|
-
const failedKeys = Array.from(failedMap.keys());
|
|
621
|
-
return [...new Set([...originalKeys, ...failedKeys])];
|
|
622
|
-
},
|
|
623
|
-
getOwnPropertyDescriptor(target, prop) {
|
|
624
|
-
if (failedMap.has(prop)) {
|
|
625
|
-
return { configurable: true, enumerable: true, value: failedMap.get(prop) };
|
|
626
|
-
}
|
|
627
|
-
return Reflect.getOwnPropertyDescriptor(target, prop);
|
|
628
|
-
}
|
|
629
|
-
});
|
|
630
|
-
}
|
|
631
|
-
} else {
|
|
632
|
-
|
|
633
|
-
flattened = { ...defaultExport };
|
|
634
|
-
for (const [key, value] of Object.entries(mod)) {
|
|
635
|
-
if (key !== "default") {
|
|
636
|
-
flattened[key] = value;
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
} else {
|
|
641
|
-
|
|
642
|
-
flattened = defaultExport;
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
categoryModules[apiPathKey] = flattened;
|
|
646
|
-
break;
|
|
647
|
-
}
|
|
648
|
-
case "multi-default-no-default": {
|
|
649
|
-
|
|
650
|
-
const moduleKeys = Object.keys(mod).filter((k) => k !== "default");
|
|
651
|
-
for (const key of moduleKeys) {
|
|
652
|
-
categoryModules[key] = mod[key];
|
|
653
|
-
}
|
|
654
|
-
break;
|
|
655
|
-
}
|
|
656
|
-
case "single-named-export-match":
|
|
657
|
-
|
|
658
|
-
categoryModules[apiPathKey] = mod[apiPathKey];
|
|
659
|
-
break;
|
|
660
|
-
case "category-name-match-flatten": {
|
|
661
|
-
|
|
662
|
-
const moduleKeys = Object.keys(mod).filter((k) => k !== "default");
|
|
663
|
-
for (const key of moduleKeys) {
|
|
664
|
-
categoryModules[key] = mod[key];
|
|
665
|
-
}
|
|
666
|
-
break;
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
} else {
|
|
670
|
-
|
|
671
|
-
categoryModules[apiPathKey] = mod;
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
for (const subDirDecision of subdirectoryDecisions) {
|
|
678
|
-
if (subDirDecision.shouldRecurse) {
|
|
679
|
-
const { name, path: subDirPath, apiPathKey } = subDirDecision;
|
|
680
|
-
let subModule;
|
|
681
|
-
|
|
682
|
-
if (mode === "lazy" && typeof subdirHandler === "function") {
|
|
683
|
-
subModule = subdirHandler({
|
|
684
|
-
subDirEntry: { name },
|
|
685
|
-
subDirPath,
|
|
686
|
-
key: apiPathKey,
|
|
687
|
-
categoryModules,
|
|
688
|
-
currentDepth,
|
|
689
|
-
maxDepth
|
|
690
|
-
});
|
|
691
|
-
} else {
|
|
692
|
-
subModule = await this._buildCategory(subDirPath, {
|
|
693
|
-
currentDepth: currentDepth + 1,
|
|
694
|
-
maxDepth,
|
|
695
|
-
mode: "eager"
|
|
696
|
-
});
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
if (
|
|
702
|
-
typeof subModule === "function" &&
|
|
703
|
-
subModule.name &&
|
|
704
|
-
subModule.name.toLowerCase() === apiPathKey.toLowerCase() &&
|
|
705
|
-
subModule.name !== apiPathKey
|
|
706
|
-
) {
|
|
707
|
-
|
|
708
|
-
categoryModules[subModule.name] = subModule;
|
|
709
|
-
} else {
|
|
710
|
-
categoryModules[apiPathKey] = subModule;
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
const keys = Object.keys(categoryModules);
|
|
717
|
-
if (keys.length === 1) {
|
|
718
|
-
const singleKey = keys[0];
|
|
719
|
-
if (singleKey === categoryName) {
|
|
720
|
-
const single = categoryModules[singleKey];
|
|
721
|
-
if (typeof single === "function") {
|
|
722
|
-
if (single.name !== categoryName) {
|
|
723
|
-
try {
|
|
724
|
-
Object.defineProperty(single, "name", { value: categoryName, configurable: true });
|
|
725
|
-
} catch {
|
|
726
|
-
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
return single;
|
|
730
|
-
} else if (single && typeof single === "object" && !Array.isArray(single)) {
|
|
731
|
-
return single;
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
return categoryModules;
|
|
737
404
|
},
|
|
738
405
|
|
|
739
406
|
|
|
@@ -763,117 +430,8 @@ const slothletObject = {
|
|
|
763
430
|
},
|
|
764
431
|
|
|
765
432
|
|
|
766
|
-
async _buildCategoryEnhanced(categoryPath, options = {}) {
|
|
767
|
-
const { currentDepth = 0, maxDepth = Infinity, mode = "eager", subdirHandler } = options;
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
const decisions = await getCategoryBuildingDecisions(categoryPath, {
|
|
771
|
-
instance: this,
|
|
772
|
-
currentDepth,
|
|
773
|
-
maxDepth,
|
|
774
|
-
debug: this.config.debug
|
|
775
|
-
});
|
|
776
|
-
|
|
777
|
-
const { processingStrategy, categoryName, processedModules, subDirectories } = decisions;
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
if (processingStrategy === "single-file" && processedModules.length === 1) {
|
|
781
|
-
const { processedModule, flattening } = processedModules[0];
|
|
782
|
-
|
|
783
|
-
if (flattening.shouldFlatten) {
|
|
784
|
-
|
|
785
|
-
if (typeof processedModule === "function") {
|
|
786
|
-
try {
|
|
787
|
-
Object.defineProperty(processedModule, "name", { value: flattening.apiPathKey, configurable: true });
|
|
788
|
-
} catch {
|
|
789
|
-
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
return processedModule;
|
|
793
|
-
}
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
return { [flattening.apiPathKey]: processedModule };
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
const categoryModules = {};
|
|
801
|
-
|
|
802
|
-
for (const { processedModule, flattening } of processedModules) {
|
|
803
|
-
categoryModules[flattening.apiPathKey] = processedModule;
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
for (const { dirEntry: subDirEntry, apiPathKey: key } of subDirectories) {
|
|
808
|
-
const subDirPath = path.join(categoryPath, subDirEntry.name);
|
|
809
|
-
let subModule;
|
|
810
|
-
|
|
811
|
-
if (mode === "lazy" && typeof subdirHandler === "function") {
|
|
812
|
-
subModule = subdirHandler({
|
|
813
|
-
subDirEntry,
|
|
814
|
-
subDirPath,
|
|
815
|
-
key,
|
|
816
|
-
categoryModules,
|
|
817
|
-
currentDepth,
|
|
818
|
-
maxDepth
|
|
819
|
-
});
|
|
820
|
-
} else {
|
|
821
|
-
|
|
822
|
-
subModule = await this._buildCategoryEnhanced(subDirPath, {
|
|
823
|
-
currentDepth: currentDepth + 1,
|
|
824
|
-
maxDepth,
|
|
825
|
-
mode: "eager"
|
|
826
|
-
});
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
if (
|
|
831
|
-
typeof subModule === "function" &&
|
|
832
|
-
subModule.name &&
|
|
833
|
-
subModule.name.toLowerCase() === key.toLowerCase() &&
|
|
834
|
-
subModule.name !== key
|
|
835
|
-
) {
|
|
836
|
-
categoryModules[subModule.name] = subModule;
|
|
837
|
-
} else {
|
|
838
|
-
categoryModules[key] = subModule;
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
const keys = Object.keys(categoryModules);
|
|
844
|
-
if (keys.length === 1) {
|
|
845
|
-
const singleKey = keys[0];
|
|
846
|
-
if (singleKey === categoryName) {
|
|
847
|
-
const single = categoryModules[singleKey];
|
|
848
|
-
if (typeof single === "function") {
|
|
849
|
-
if (single.name !== categoryName) {
|
|
850
|
-
try {
|
|
851
|
-
Object.defineProperty(single, "name", { value: categoryName, configurable: true });
|
|
852
|
-
} catch {
|
|
853
|
-
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
return single;
|
|
857
|
-
} else if (single && typeof single === "object" && !Array.isArray(single)) {
|
|
858
|
-
return single;
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
return categoryModules;
|
|
864
|
-
},
|
|
865
|
-
|
|
866
|
-
|
|
867
433
|
_shouldIncludeFile(entry) {
|
|
868
|
-
|
|
869
|
-
if (!entry.isFile()) return false;
|
|
870
|
-
|
|
871
|
-
if (!(entry.name.endsWith(".mjs") || entry.name.endsWith(".cjs") || entry.name.endsWith(".js"))) return false;
|
|
872
|
-
|
|
873
|
-
if (entry.name.startsWith(".")) return false;
|
|
874
|
-
|
|
875
|
-
if (entry.name.startsWith("__slothlet_")) return false;
|
|
876
|
-
return true;
|
|
434
|
+
return shouldIncludeFile(entry);
|
|
877
435
|
},
|
|
878
436
|
|
|
879
437
|
|
|
@@ -956,11 +514,7 @@ const slothletObject = {
|
|
|
956
514
|
createBoundApi(ref = null) {
|
|
957
515
|
if (!this.api) throw new Error("BindleApi modules not loaded. Call load() first.");
|
|
958
516
|
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
517
|
let boundApi;
|
|
963
|
-
|
|
964
518
|
|
|
965
519
|
boundApi = this.api;
|
|
966
520
|
|
|
@@ -978,24 +532,6 @@ const slothletObject = {
|
|
|
978
532
|
}
|
|
979
533
|
|
|
980
534
|
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
535
|
const instance = this;
|
|
1000
536
|
this.safeDefine(boundApi, "describe", function (showAll = false) {
|
|
1001
537
|
|
|
@@ -1085,6 +621,32 @@ const slothletObject = {
|
|
|
1085
621
|
} else if (this.config && this.config.debug) {
|
|
1086
622
|
console.warn("Could not redefine boundApi.addApi: not configurable");
|
|
1087
623
|
}
|
|
624
|
+
|
|
625
|
+
|
|
626
|
+
const runDesc = Object.getOwnPropertyDescriptor(boundApi, "run");
|
|
627
|
+
if (!runDesc || runDesc.configurable) {
|
|
628
|
+
Object.defineProperty(boundApi, "run", {
|
|
629
|
+
value: this.run.bind(this),
|
|
630
|
+
writable: true,
|
|
631
|
+
configurable: true,
|
|
632
|
+
enumerable: false
|
|
633
|
+
});
|
|
634
|
+
} else if (this.config && this.config.debug) {
|
|
635
|
+
console.warn("Could not redefine boundApi.run: not configurable");
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
const scopeDesc = Object.getOwnPropertyDescriptor(boundApi, "scope");
|
|
640
|
+
if (!scopeDesc || scopeDesc.configurable) {
|
|
641
|
+
Object.defineProperty(boundApi, "scope", {
|
|
642
|
+
value: this.scope.bind(this),
|
|
643
|
+
writable: true,
|
|
644
|
+
configurable: true,
|
|
645
|
+
enumerable: false
|
|
646
|
+
});
|
|
647
|
+
} else if (this.config && this.config.debug) {
|
|
648
|
+
console.warn("Could not redefine boundApi.scope: not configurable");
|
|
649
|
+
}
|
|
1088
650
|
|
|
1089
651
|
|
|
1090
652
|
|
|
@@ -1097,24 +659,7 @@ const slothletObject = {
|
|
|
1097
659
|
|
|
1098
660
|
|
|
1099
661
|
safeDefine(obj, key, value, enumerable = false) {
|
|
1100
|
-
|
|
1101
|
-
if (!desc) {
|
|
1102
|
-
Object.defineProperty(obj, key, {
|
|
1103
|
-
value,
|
|
1104
|
-
writable: true,
|
|
1105
|
-
configurable: true,
|
|
1106
|
-
enumerable
|
|
1107
|
-
});
|
|
1108
|
-
} else if (desc.configurable) {
|
|
1109
|
-
Object.defineProperty(obj, key, {
|
|
1110
|
-
value,
|
|
1111
|
-
writable: true,
|
|
1112
|
-
configurable: true,
|
|
1113
|
-
enumerable
|
|
1114
|
-
});
|
|
1115
|
-
} else if (this.config && this.config.debug) {
|
|
1116
|
-
console.warn(`Could not redefine boundApi.${key}: not configurable`);
|
|
1117
|
-
}
|
|
662
|
+
return safeDefine(obj, key, value, enumerable, this.config);
|
|
1118
663
|
},
|
|
1119
664
|
|
|
1120
665
|
|
|
@@ -1134,219 +679,120 @@ const slothletObject = {
|
|
|
1134
679
|
|
|
1135
680
|
|
|
1136
681
|
async addApi(apiPath, folderPath) {
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
}
|
|
682
|
+
return addApiFromFolder({ apiPath, folderPath, instance: this });
|
|
683
|
+
},
|
|
1140
684
|
|
|
1141
|
-
|
|
1142
|
-
if (typeof apiPath !== "string") {
|
|
1143
|
-
throw new TypeError("[slothlet] addApi: 'apiPath' must be a string.");
|
|
1144
|
-
}
|
|
1145
|
-
const normalizedApiPath = apiPath.trim();
|
|
1146
|
-
if (normalizedApiPath === "") {
|
|
1147
|
-
throw new TypeError("[slothlet] addApi: 'apiPath' must be a non-empty, non-whitespace string.");
|
|
1148
|
-
}
|
|
1149
|
-
const pathParts = normalizedApiPath.split(".");
|
|
1150
|
-
if (pathParts.some((part) => part === "")) {
|
|
1151
|
-
throw new Error(`[slothlet] addApi: 'apiPath' must not contain empty segments. Received: "${normalizedApiPath}"`);
|
|
1152
|
-
}
|
|
685
|
+
|
|
1153
686
|
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
687
|
+
|
|
688
|
+
run(contextData, callback, ...args) {
|
|
689
|
+
if (this.config.scope?.enabled === false) {
|
|
690
|
+
throw new Error("Per-request context (scope) is disabled for this instance.");
|
|
1157
691
|
}
|
|
1158
692
|
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
if (!path.isAbsolute(folderPath)) {
|
|
1162
|
-
resolvedFolderPath = resolvePathFromCaller(folderPath);
|
|
693
|
+
if (typeof callback !== "function") {
|
|
694
|
+
throw new TypeError("Callback must be a function.");
|
|
1163
695
|
}
|
|
1164
696
|
|
|
1165
|
-
|
|
1166
|
-
let
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
}
|
|
1172
|
-
if (!stats.isDirectory()) {
|
|
1173
|
-
throw new Error(`[slothlet] addApi: Path is not a directory: ${resolvedFolderPath}`);
|
|
1174
|
-
}
|
|
697
|
+
const runtimeType = this.config.runtime || "async";
|
|
698
|
+
let requestALS;
|
|
699
|
+
if (runtimeType === "async") {
|
|
700
|
+
return import("@cldmv/slothlet/runtime/async").then((asyncRuntime) => {
|
|
701
|
+
requestALS = asyncRuntime.requestALS;
|
|
702
|
+
const parentContext = requestALS.getStore() || {};
|
|
1175
703
|
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
704
|
+
let mergedContext;
|
|
705
|
+
if (this.config.scope?.merge === "deep") {
|
|
706
|
+
const instanceContext = this.context || {};
|
|
707
|
+
let temp = this._deepMerge({}, instanceContext);
|
|
708
|
+
temp = this._deepMerge(temp, parentContext);
|
|
709
|
+
mergedContext = this._deepMerge(temp, contextData);
|
|
710
|
+
} else {
|
|
711
|
+
mergedContext = { ...parentContext, ...contextData };
|
|
712
|
+
}
|
|
1179
713
|
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
if (this.config.lazy) {
|
|
1183
|
-
|
|
1184
|
-
newModules = await this.modes.lazy.create.call(this, resolvedFolderPath, this.config.apiDepth || Infinity, 0);
|
|
714
|
+
return requestALS.run(mergedContext, () => callback(...args));
|
|
715
|
+
});
|
|
1185
716
|
} else {
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
}
|
|
1199
|
-
}
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
let currentTarget = this.api;
|
|
1203
|
-
let currentBoundTarget = this.boundapi;
|
|
1204
|
-
|
|
1205
|
-
for (let i = 0; i < pathParts.length - 1; i++) {
|
|
1206
|
-
const part = pathParts[i];
|
|
1207
|
-
const key = this._toapiPathKey(part);
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
if (Object.prototype.hasOwnProperty.call(currentTarget, key)) {
|
|
1213
|
-
const existing = currentTarget[key];
|
|
1214
|
-
if (existing === null || (typeof existing !== "object" && typeof existing !== "function")) {
|
|
1215
|
-
throw new Error(
|
|
1216
|
-
`[slothlet] Cannot extend API path "${normalizedApiPath}" through segment "${part}": ` +
|
|
1217
|
-
`existing value is type "${typeof existing}", cannot add properties.`
|
|
1218
|
-
);
|
|
1219
|
-
}
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
} else {
|
|
1223
|
-
currentTarget[key] = {};
|
|
1224
|
-
}
|
|
1225
|
-
if (Object.prototype.hasOwnProperty.call(currentBoundTarget, key)) {
|
|
1226
|
-
const existingBound = currentBoundTarget[key];
|
|
1227
|
-
if (existingBound === null || (typeof existingBound !== "object" && typeof existingBound !== "function")) {
|
|
1228
|
-
throw new Error(
|
|
1229
|
-
`[slothlet] Cannot extend bound API path "${normalizedApiPath}" through segment "${part}": ` +
|
|
1230
|
-
`existing value is type "${typeof existingBound}", cannot add properties.`
|
|
1231
|
-
);
|
|
717
|
+
return import("@cldmv/slothlet/runtime/live").then((liveRuntime) => {
|
|
718
|
+
requestALS = liveRuntime.requestALS;
|
|
719
|
+
const parentContext = requestALS.getStore() || {};
|
|
720
|
+
|
|
721
|
+
let mergedContext;
|
|
722
|
+
if (this.config.scope?.merge === "deep") {
|
|
723
|
+
const instanceContext = this.context || {};
|
|
724
|
+
let temp = this._deepMerge({}, instanceContext);
|
|
725
|
+
temp = this._deepMerge(temp, parentContext);
|
|
726
|
+
mergedContext = this._deepMerge(temp, contextData);
|
|
727
|
+
} else {
|
|
728
|
+
mergedContext = { ...parentContext, ...contextData };
|
|
1232
729
|
}
|
|
1233
|
-
|
|
1234
|
-
} else {
|
|
1235
|
-
currentBoundTarget[key] = {};
|
|
1236
|
-
}
|
|
1237
730
|
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
currentBoundTarget = currentBoundTarget[key];
|
|
731
|
+
return requestALS.run(mergedContext, () => callback(...args));
|
|
732
|
+
});
|
|
1241
733
|
}
|
|
734
|
+
},
|
|
1242
735
|
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
if (Object.prototype.hasOwnProperty.call(currentTarget, finalKey)) {
|
|
1251
|
-
const existing = currentTarget[finalKey];
|
|
736
|
+
|
|
737
|
+
scope({ context, fn, args }) {
|
|
738
|
+
if (this.config.scope?.enabled === false) {
|
|
739
|
+
throw new Error("Per-request context (scope) is disabled for this instance.");
|
|
740
|
+
}
|
|
1252
741
|
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
`[slothlet] Skipping addApi: API path "${normalizedApiPath}" final key "${finalKey}" ` +
|
|
1257
|
-
`already exists (type: "${typeof existing}"). Set allowApiOverwrite: true to allow overwrites.`
|
|
1258
|
-
);
|
|
1259
|
-
return;
|
|
1260
|
-
}
|
|
742
|
+
if (!context || typeof context !== "object") {
|
|
743
|
+
throw new TypeError("context must be an object.");
|
|
744
|
+
}
|
|
1261
745
|
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
`[slothlet] Overwriting existing non-function value at API path "${normalizedApiPath}" ` +
|
|
1266
|
-
`final key "${finalKey}" with a function. Previous type: "${typeof existing}".`
|
|
1267
|
-
);
|
|
1268
|
-
} else if (typeof existing === "function") {
|
|
1269
|
-
|
|
1270
|
-
console.warn(
|
|
1271
|
-
`[slothlet] Overwriting existing function at API path "${normalizedApiPath}" ` + `final key "${finalKey}" with a new function.`
|
|
1272
|
-
);
|
|
1273
|
-
}
|
|
1274
|
-
}
|
|
1275
|
-
currentTarget[finalKey] = newModules;
|
|
1276
|
-
currentBoundTarget[finalKey] = newModules;
|
|
1277
|
-
} else if (typeof newModules === "object" && newModules !== null) {
|
|
1278
|
-
|
|
1279
|
-
if (Object.prototype.hasOwnProperty.call(currentTarget, finalKey)) {
|
|
1280
|
-
const existing = currentTarget[finalKey];
|
|
746
|
+
if (typeof fn !== "function") {
|
|
747
|
+
throw new TypeError("fn must be a function.");
|
|
748
|
+
}
|
|
1281
749
|
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
`[slothlet] Skipping addApi merge: API path "${normalizedApiPath}" final key "${finalKey}" ` +
|
|
1289
|
-
`already exists with content (type: "${typeof existing}"). Set allowApiOverwrite: true to allow merging.`
|
|
1290
|
-
);
|
|
1291
|
-
return;
|
|
1292
|
-
}
|
|
1293
|
-
}
|
|
750
|
+
const runtimeType = this.config.runtime || "async";
|
|
751
|
+
let requestALS;
|
|
752
|
+
if (runtimeType === "async") {
|
|
753
|
+
return import("./lib/runtime/runtime-asynclocalstorage.mjs").then((asyncRuntime) => {
|
|
754
|
+
requestALS = asyncRuntime.requestALS;
|
|
755
|
+
const parentContext = requestALS.getStore() || {};
|
|
1294
756
|
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
);
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
const existingBound = currentBoundTarget[finalKey];
|
|
1304
|
-
if (existingBound !== null && typeof existingBound !== "object" && typeof existingBound !== "function") {
|
|
1305
|
-
throw new Error(
|
|
1306
|
-
`[slothlet] Cannot merge bound API at "${normalizedApiPath}": ` +
|
|
1307
|
-
`existing value at final key "${finalKey}" is type "${typeof existingBound}", cannot merge into primitives.`
|
|
1308
|
-
);
|
|
757
|
+
let mergedContext;
|
|
758
|
+
if (this.config.scope?.merge === "deep") {
|
|
759
|
+
const instanceContext = this.context || {};
|
|
760
|
+
let temp = this._deepMerge({}, instanceContext);
|
|
761
|
+
temp = this._deepMerge(temp, parentContext);
|
|
762
|
+
mergedContext = this._deepMerge(temp, context);
|
|
763
|
+
} else {
|
|
764
|
+
mergedContext = { ...parentContext, ...context };
|
|
1309
765
|
}
|
|
1310
|
-
}
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
if (!currentTarget[finalKey]) {
|
|
1314
|
-
currentTarget[finalKey] = {};
|
|
1315
|
-
}
|
|
1316
|
-
if (!currentBoundTarget[finalKey]) {
|
|
1317
|
-
currentBoundTarget[finalKey] = {};
|
|
1318
|
-
}
|
|
1319
766
|
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
Object.assign(currentTarget[finalKey], newModules);
|
|
1326
|
-
Object.assign(currentBoundTarget[finalKey], newModules);
|
|
1327
|
-
} else if (newModules === null || newModules === undefined) {
|
|
1328
|
-
|
|
1329
|
-
const receivedType = newModules === null ? "null" : "undefined";
|
|
1330
|
-
console.warn(
|
|
1331
|
-
`[slothlet] addApi: No modules loaded from folder at API path "${normalizedApiPath}". ` +
|
|
1332
|
-
`Loaded modules resulted in ${receivedType}. Check that the folder contains valid module files.`
|
|
1333
|
-
);
|
|
767
|
+
const argsArray = args || [];
|
|
768
|
+
return requestALS.run(mergedContext, () => fn(...argsArray));
|
|
769
|
+
});
|
|
1334
770
|
} else {
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
771
|
+
return import("./lib/runtime/runtime-livebindings.mjs").then((liveRuntime) => {
|
|
772
|
+
requestALS = liveRuntime.requestALS;
|
|
773
|
+
const parentContext = requestALS.getStore() || {};
|
|
774
|
+
|
|
775
|
+
let mergedContext;
|
|
776
|
+
if (this.config.scope?.merge === "deep") {
|
|
777
|
+
const instanceContext = this.context || {};
|
|
778
|
+
let temp = this._deepMerge({}, instanceContext);
|
|
779
|
+
temp = this._deepMerge(temp, parentContext);
|
|
780
|
+
mergedContext = this._deepMerge(temp, context);
|
|
781
|
+
} else {
|
|
782
|
+
mergedContext = { ...parentContext, ...context };
|
|
783
|
+
}
|
|
1343
784
|
|
|
1344
|
-
|
|
1345
|
-
|
|
785
|
+
const argsArray = args || [];
|
|
786
|
+
return requestALS.run(mergedContext, () => fn(...argsArray));
|
|
787
|
+
});
|
|
1346
788
|
}
|
|
1347
789
|
},
|
|
1348
790
|
|
|
1349
791
|
|
|
792
|
+
_deepMerge(target, source) {
|
|
793
|
+
return deepMerge(target, source);
|
|
794
|
+
},
|
|
795
|
+
|
|
1350
796
|
async shutdown() {
|
|
1351
797
|
|
|
1352
798
|
|
|
@@ -1423,52 +869,6 @@ const slothletObject = {
|
|
|
1423
869
|
};
|
|
1424
870
|
|
|
1425
871
|
|
|
1426
|
-
export function mutateLiveBindingFunction(target, source) {
|
|
1427
|
-
if (typeof source === "function") {
|
|
1428
|
-
target._impl = (...args) => source(...args);
|
|
1429
|
-
|
|
1430
|
-
for (const key of Object.keys(target)) {
|
|
1431
|
-
if (key !== "_impl" && key !== "__ctx") delete target[key];
|
|
1432
|
-
}
|
|
1433
|
-
|
|
1434
|
-
for (const key of Object.getOwnPropertyNames(source)) {
|
|
1435
|
-
if (key !== "length" && key !== "name" && key !== "prototype" && key !== "_impl" && key !== "__ctx") {
|
|
1436
|
-
try {
|
|
1437
|
-
target[key] = source[key];
|
|
1438
|
-
} catch {
|
|
1439
|
-
|
|
1440
|
-
}
|
|
1441
|
-
}
|
|
1442
|
-
}
|
|
1443
|
-
} else if (typeof source === "object" && source !== null) {
|
|
1444
|
-
|
|
1445
|
-
for (const key of Object.keys(target)) {
|
|
1446
|
-
if (key !== "_impl" && key !== "__ctx") delete target[key];
|
|
1447
|
-
}
|
|
1448
|
-
|
|
1449
|
-
for (const [key, value] of Object.entries(source)) {
|
|
1450
|
-
if (key !== "__ctx") {
|
|
1451
|
-
target[key] = value;
|
|
1452
|
-
}
|
|
1453
|
-
}
|
|
1454
|
-
|
|
1455
|
-
const managementMethods = ["shutdown", "addApi", "describe"];
|
|
1456
|
-
for (const method of managementMethods) {
|
|
1457
|
-
const desc = Object.getOwnPropertyDescriptor(source, method);
|
|
1458
|
-
if (desc) {
|
|
1459
|
-
try {
|
|
1460
|
-
Object.defineProperty(target, method, desc);
|
|
1461
|
-
} catch {
|
|
1462
|
-
|
|
1463
|
-
}
|
|
1464
|
-
}
|
|
1465
|
-
}
|
|
1466
|
-
|
|
1467
|
-
if (typeof source._impl === "function") {
|
|
1468
|
-
target._impl = source._impl;
|
|
1469
|
-
}
|
|
1470
|
-
}
|
|
1471
|
-
}
|
|
1472
872
|
|
|
1473
873
|
export { slothlet };
|
|
1474
874
|
export default slothlet;
|