@cldmv/slothlet 2.7.1 → 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 -1475
- 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 +197 -547
- package/docs/API-RULES-CONDITIONS.md +508 -0
- package/{API-RULES.md → docs/API-RULES.md} +127 -72
- package/index.cjs +2 -1
- package/index.mjs +2 -1
- 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 +23 -13
- package/types/dist/slothlet.d.mts.map +1 -1
- package/types/index.d.mts +0 -1
- package/API-RULES-CONDITIONS.md +0 -367
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2025 CLDMV/Shinrai
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
export function safeDefine(obj, key, value, enumerable = false, config = null) {
|
|
23
|
+
const desc = Object.getOwnPropertyDescriptor(obj, key);
|
|
24
|
+
if (!desc) {
|
|
25
|
+
Object.defineProperty(obj, key, {
|
|
26
|
+
value,
|
|
27
|
+
writable: true,
|
|
28
|
+
configurable: true,
|
|
29
|
+
enumerable
|
|
30
|
+
});
|
|
31
|
+
} else if (desc.configurable) {
|
|
32
|
+
Object.defineProperty(obj, key, {
|
|
33
|
+
value,
|
|
34
|
+
writable: true,
|
|
35
|
+
configurable: true,
|
|
36
|
+
enumerable
|
|
37
|
+
});
|
|
38
|
+
} else if (config && config.debug) {
|
|
39
|
+
console.warn(`Could not redefine boundApi.${key}: not configurable`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
export function deepMerge(target, source) {
|
|
45
|
+
if (!source || typeof source !== "object" || Array.isArray(source)) {
|
|
46
|
+
return source;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
for (const key in source) {
|
|
50
|
+
if (!Object.prototype.hasOwnProperty.call(source, key)) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
if (key === "__proto__" || key === "prototype" || key === "constructor") {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const sourceValue = source[key];
|
|
60
|
+
const targetValue = target[key];
|
|
61
|
+
|
|
62
|
+
if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
|
|
63
|
+
target[key] = deepMerge(
|
|
64
|
+
targetValue && typeof targetValue === "object" && !Array.isArray(targetValue) ? targetValue : {},
|
|
65
|
+
sourceValue
|
|
66
|
+
);
|
|
67
|
+
} else {
|
|
68
|
+
target[key] = sourceValue;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return target;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
export function mutateLiveBindingFunction(target, source) {
|
|
77
|
+
if (typeof source === "function") {
|
|
78
|
+
target._impl = (...args) => source(...args);
|
|
79
|
+
|
|
80
|
+
for (const key of Object.keys(target)) {
|
|
81
|
+
if (key !== "_impl" && key !== "__ctx") delete target[key];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
for (const key of Object.getOwnPropertyNames(source)) {
|
|
85
|
+
if (key !== "length" && key !== "name" && key !== "prototype" && key !== "_impl" && key !== "__ctx") {
|
|
86
|
+
try {
|
|
87
|
+
target[key] = source[key];
|
|
88
|
+
} catch {
|
|
89
|
+
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
} else if (typeof source === "object" && source !== null) {
|
|
94
|
+
|
|
95
|
+
for (const key of Object.keys(target)) {
|
|
96
|
+
if (key !== "_impl" && key !== "__ctx") delete target[key];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
for (const [key, value] of Object.entries(source)) {
|
|
100
|
+
if (key !== "__ctx") {
|
|
101
|
+
target[key] = value;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const managementMethods = ["shutdown", "addApi", "describe"];
|
|
106
|
+
for (const method of managementMethods) {
|
|
107
|
+
const desc = Object.getOwnPropertyDescriptor(source, method);
|
|
108
|
+
if (desc) {
|
|
109
|
+
try {
|
|
110
|
+
Object.defineProperty(target, method, desc);
|
|
111
|
+
} catch {
|
|
112
|
+
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (typeof source._impl === "function") {
|
|
118
|
+
target._impl = source._impl;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -28,6 +28,9 @@ const als = new AsyncLocalStorage();
|
|
|
28
28
|
export const sharedALS = new AsyncLocalStorage();
|
|
29
29
|
|
|
30
30
|
|
|
31
|
+
export const requestALS = new AsyncLocalStorage();
|
|
32
|
+
|
|
33
|
+
|
|
31
34
|
enableAlsForEventEmitters(als);
|
|
32
35
|
|
|
33
36
|
|
|
@@ -42,17 +45,21 @@ export const runWithCtx = (ctx, fn, thisArg, args) => {
|
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
|
|
48
|
+
const requestContext = requestALS.getStore();
|
|
49
|
+
const mergedCtx = requestContext ? { ...ctx, context: { ...ctx.context, ...requestContext } } : ctx;
|
|
50
|
+
|
|
51
|
+
|
|
45
52
|
const path = fn.__slothletPath;
|
|
46
53
|
|
|
47
54
|
|
|
48
55
|
const runtime_runInALS = () => {
|
|
49
56
|
try {
|
|
50
57
|
|
|
51
|
-
const beforeResult =
|
|
58
|
+
const beforeResult = mergedCtx.hookManager.executeBeforeHooks(path, args);
|
|
52
59
|
|
|
53
60
|
|
|
54
61
|
if (beforeResult.cancelled) {
|
|
55
|
-
|
|
62
|
+
mergedCtx.hookManager.executeAlwaysHooks(path, beforeResult.value, []);
|
|
56
63
|
return beforeResult.value;
|
|
57
64
|
}
|
|
58
65
|
|
|
@@ -67,20 +74,20 @@ export const runWithCtx = (ctx, fn, thisArg, args) => {
|
|
|
67
74
|
return result.then(
|
|
68
75
|
(resolvedResult) => {
|
|
69
76
|
|
|
70
|
-
const finalResult =
|
|
71
|
-
|
|
77
|
+
const finalResult = mergedCtx.hookManager.executeAfterHooks(path, resolvedResult);
|
|
78
|
+
mergedCtx.hookManager.executeAlwaysHooks(path, finalResult, []);
|
|
72
79
|
return finalResult;
|
|
73
80
|
},
|
|
74
81
|
(error) => {
|
|
75
82
|
|
|
76
|
-
if (!
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
if (!mergedCtx.hookManager.reportedErrors.has(error)) {
|
|
84
|
+
mergedCtx.hookManager.reportedErrors.add(error);
|
|
85
|
+
mergedCtx.hookManager.executeErrorHooks(path, error, { type: "function" });
|
|
79
86
|
}
|
|
80
87
|
|
|
81
|
-
|
|
88
|
+
mergedCtx.hookManager.executeAlwaysHooks(path, undefined, [error]);
|
|
82
89
|
|
|
83
|
-
if (!
|
|
90
|
+
if (!mergedCtx.hookManager.suppressErrors) {
|
|
84
91
|
throw error;
|
|
85
92
|
}
|
|
86
93
|
return undefined;
|
|
@@ -89,26 +96,26 @@ export const runWithCtx = (ctx, fn, thisArg, args) => {
|
|
|
89
96
|
}
|
|
90
97
|
|
|
91
98
|
|
|
92
|
-
const finalResult =
|
|
93
|
-
|
|
99
|
+
const finalResult = mergedCtx.hookManager.executeAfterHooks(path, result);
|
|
100
|
+
mergedCtx.hookManager.executeAlwaysHooks(path, finalResult, []);
|
|
94
101
|
return finalResult;
|
|
95
102
|
} catch (error) {
|
|
96
103
|
|
|
97
|
-
if (!
|
|
98
|
-
|
|
99
|
-
|
|
104
|
+
if (!mergedCtx.hookManager.reportedErrors.has(error)) {
|
|
105
|
+
mergedCtx.hookManager.reportedErrors.add(error);
|
|
106
|
+
mergedCtx.hookManager.executeErrorHooks(path, error, { type: "function" });
|
|
100
107
|
}
|
|
101
108
|
|
|
102
|
-
|
|
109
|
+
mergedCtx.hookManager.executeAlwaysHooks(path, undefined, [error]);
|
|
103
110
|
|
|
104
|
-
if (!
|
|
111
|
+
if (!mergedCtx.hookManager.suppressErrors) {
|
|
105
112
|
throw error;
|
|
106
113
|
}
|
|
107
114
|
return undefined;
|
|
108
115
|
}
|
|
109
116
|
};
|
|
110
117
|
|
|
111
|
-
return als.run(
|
|
118
|
+
return als.run(mergedCtx, runtime_runInALS);
|
|
112
119
|
};
|
|
113
120
|
|
|
114
121
|
|
|
@@ -477,6 +484,26 @@ function runtime_createLiveBinding(contextKey) {
|
|
|
477
484
|
|
|
478
485
|
|
|
479
486
|
|
|
487
|
+
if (contextKey === "context") {
|
|
488
|
+
const ctx = getCtx();
|
|
489
|
+
const baseContext = ctx?.context || {};
|
|
490
|
+
const requestContext = requestALS.getStore() || {};
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
const isDeepMerge = ctx?.config?.scope?.merge === "deep";
|
|
495
|
+
|
|
496
|
+
if (isDeepMerge && Object.keys(requestContext).length > 0) {
|
|
497
|
+
|
|
498
|
+
return requestContext[prop];
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
const merged = { ...baseContext, ...requestContext };
|
|
503
|
+
return merged[prop];
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
|
|
480
507
|
runtime_syncWithContext();
|
|
481
508
|
return target[prop];
|
|
482
509
|
},
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
21
22
|
import {
|
|
22
23
|
detectCurrentInstanceId,
|
|
23
24
|
getInstanceData,
|
|
@@ -26,6 +27,9 @@ import {
|
|
|
26
27
|
} from "@cldmv/slothlet/helpers/instance-manager";
|
|
27
28
|
|
|
28
29
|
|
|
30
|
+
export const requestALS = new AsyncLocalStorage();
|
|
31
|
+
|
|
32
|
+
|
|
29
33
|
function getCurrentInstanceContext() {
|
|
30
34
|
|
|
31
35
|
|
|
@@ -122,10 +126,21 @@ export const context = new Proxy(
|
|
|
122
126
|
{
|
|
123
127
|
get(target, prop) {
|
|
124
128
|
const ctx = getCurrentInstanceContext();
|
|
125
|
-
|
|
126
|
-
|
|
129
|
+
const baseContext = ctx?.context || {};
|
|
130
|
+
const requestContext = requestALS.getStore() || {};
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
const isDeepMerge = ctx?.config?.scope?.merge === "deep";
|
|
135
|
+
|
|
136
|
+
if (isDeepMerge && Object.keys(requestContext).length > 0) {
|
|
137
|
+
|
|
138
|
+
return requestContext[prop];
|
|
127
139
|
}
|
|
128
|
-
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
const merged = { ...baseContext, ...requestContext };
|
|
143
|
+
return merged[prop];
|
|
129
144
|
},
|
|
130
145
|
|
|
131
146
|
set(target, prop, value) {
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
import { detectCurrentInstanceId, getInstanceData } from "
|
|
21
|
+
import { detectCurrentInstanceId, getInstanceData } from "@cldmv/slothlet/helpers/instance-manager";
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
const asyncRuntime = await import("
|
|
25
|
-
const liveBindingsRuntime = await import("
|
|
24
|
+
const asyncRuntime = await import("@cldmv/slothlet/runtime/async");
|
|
25
|
+
const liveBindingsRuntime = await import("@cldmv/slothlet/runtime/live");
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
function detectRuntimeType() {
|