@cldmv/slothlet 2.9.0 → 2.10.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/README.md +68 -0
- package/dist/lib/engine/slothlet_child.mjs +1 -1
- package/dist/lib/engine/slothlet_engine.mjs +1 -1
- package/dist/lib/engine/slothlet_esm.mjs +1 -1
- package/dist/lib/engine/slothlet_helpers.mjs +1 -1
- package/dist/lib/engine/slothlet_worker.mjs +1 -1
- package/dist/lib/helpers/als-eventemitter.mjs +1 -1
- package/dist/lib/helpers/api_builder/add_api.mjs +58 -3
- package/dist/lib/helpers/api_builder/analysis.mjs +13 -3
- package/dist/lib/helpers/api_builder/construction.mjs +1 -1
- package/dist/lib/helpers/api_builder/decisions.mjs +1 -1
- package/dist/lib/helpers/api_builder/metadata.mjs +248 -0
- package/dist/lib/helpers/api_builder.mjs +1 -1
- package/dist/lib/helpers/auto-wrap.mjs +1 -1
- package/dist/lib/helpers/hooks.mjs +1 -1
- package/dist/lib/helpers/instance-manager.mjs +1 -1
- package/dist/lib/helpers/metadata-api.mjs +201 -0
- package/dist/lib/helpers/multidefault.mjs +12 -3
- package/dist/lib/helpers/resolve-from-caller.mjs +1 -1
- package/dist/lib/helpers/sanitize.mjs +1 -1
- package/dist/lib/helpers/utilities.mjs +1 -1
- package/dist/lib/modes/slothlet_eager.mjs +1 -1
- package/dist/lib/modes/slothlet_lazy.mjs +10 -1
- package/dist/lib/runtime/runtime-asynclocalstorage.mjs +5 -1
- package/dist/lib/runtime/runtime-livebindings.mjs +5 -1
- package/dist/lib/runtime/runtime.mjs +12 -1
- package/dist/slothlet.mjs +19 -3
- package/package.json +1 -1
- package/types/dist/lib/helpers/api_builder/add_api.d.mts +17 -1
- package/types/dist/lib/helpers/api_builder/add_api.d.mts.map +1 -1
- package/types/dist/lib/helpers/api_builder/analysis.d.mts.map +1 -1
- package/types/dist/lib/helpers/api_builder/metadata.d.mts +99 -0
- package/types/dist/lib/helpers/api_builder/metadata.d.mts.map +1 -0
- package/types/dist/lib/helpers/metadata-api.d.mts +132 -0
- package/types/dist/lib/helpers/metadata-api.d.mts.map +1 -0
- package/types/dist/lib/helpers/multidefault.d.mts.map +1 -1
- package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts +2 -0
- package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts.map +1 -1
- package/types/dist/lib/runtime/runtime-livebindings.d.mts +2 -0
- package/types/dist/lib/runtime/runtime-livebindings.d.mts.map +1 -1
- package/types/dist/lib/runtime/runtime.d.mts +1 -0
- package/types/dist/lib/runtime/runtime.d.mts.map +1 -1
- package/types/dist/slothlet.d.mts.map +1 -1
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2026 CLDMV/Shinrai
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
import { getStack, toFsPath } from "@cldmv/slothlet/helpers/resolve-from-caller";
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
let runtimeModule = null;
|
|
25
|
+
let runtimeImportPromise = null;
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
async function ensureRuntime() {
|
|
29
|
+
if (runtimeModule) {
|
|
30
|
+
return runtimeModule;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!runtimeImportPromise) {
|
|
34
|
+
runtimeImportPromise = import("@cldmv/slothlet/runtime")
|
|
35
|
+
.then((module) => {
|
|
36
|
+
runtimeModule = module;
|
|
37
|
+
return module;
|
|
38
|
+
})
|
|
39
|
+
.catch((err) => {
|
|
40
|
+
console.error("[slothlet] Failed to import runtime for metadata API:", err.message);
|
|
41
|
+
runtimeModule = {};
|
|
42
|
+
return {};
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return runtimeImportPromise;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
function getApiRoot() {
|
|
51
|
+
|
|
52
|
+
return runtimeModule?.self || null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
function findFunctionByStack(apiRoot, targetFile, targetLine, visited = new WeakSet()) {
|
|
57
|
+
if (!apiRoot || visited.has(apiRoot)) return null;
|
|
58
|
+
visited.add(apiRoot);
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
if (typeof apiRoot === "function" && apiRoot.__sourceFile && apiRoot.__sourceLine) {
|
|
62
|
+
if (apiRoot.__sourceFile === targetFile && apiRoot.__sourceLine === targetLine) {
|
|
63
|
+
return apiRoot;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
if (typeof apiRoot === "object" || typeof apiRoot === "function") {
|
|
69
|
+
const keys = Object.keys(apiRoot);
|
|
70
|
+
for (const key of keys) {
|
|
71
|
+
|
|
72
|
+
if (key.startsWith("_") || ["hooks", "shutdown", "addApi", "describe", "run"].includes(key)) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const result = findFunctionByStack(apiRoot[key], targetFile, targetLine, visited);
|
|
77
|
+
if (result) return result;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
function findFunctionByPath(apiRoot, path) {
|
|
86
|
+
if (!path || typeof path !== "string") return null;
|
|
87
|
+
|
|
88
|
+
const parts = path.split(".");
|
|
89
|
+
let current = apiRoot;
|
|
90
|
+
|
|
91
|
+
for (const part of parts) {
|
|
92
|
+
if (!current || (typeof current !== "object" && typeof current !== "function")) {
|
|
93
|
+
if (process.env.SLOTHLET_DEBUG) {
|
|
94
|
+
console.log("[findFunctionByPath] Failed: current is", typeof current);
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
current = current[part];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const result = typeof current === "function" ? current : null;
|
|
102
|
+
if (process.env.SLOTHLET_DEBUG) {
|
|
103
|
+
console.log("[findFunctionByPath] Result:", result ? "function found" : "null");
|
|
104
|
+
}
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
function parseCallSite(cs) {
|
|
110
|
+
if (!cs) return null;
|
|
111
|
+
|
|
112
|
+
const fileName = cs.getFileName?.();
|
|
113
|
+
if (!fileName) return null;
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
const filePath = toFsPath(fileName);
|
|
117
|
+
if (!filePath) return null;
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
if (filePath.startsWith?.("node:internal")) return null;
|
|
121
|
+
|
|
122
|
+
const lineNum = cs.getLineNumber?.();
|
|
123
|
+
if (typeof lineNum !== "number") return null;
|
|
124
|
+
|
|
125
|
+
return { file: filePath, line: lineNum };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
export const metadataAPI = {
|
|
130
|
+
|
|
131
|
+
async caller() {
|
|
132
|
+
|
|
133
|
+
await ensureRuntime();
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
const apiRoot = getApiRoot();
|
|
137
|
+
if (!apiRoot || typeof apiRoot !== "object") return null;
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
const stack = getStack(metadataAPI.caller);
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
if (stack.length < 1) return null;
|
|
146
|
+
|
|
147
|
+
const parsed = parseCallSite(stack[0]);
|
|
148
|
+
if (!parsed) return null;
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
const func = findFunctionByStack(apiRoot, parsed.file, parsed.line);
|
|
152
|
+
if (!func) return null;
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
return func.__metadata || null;
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
async self() {
|
|
160
|
+
|
|
161
|
+
await ensureRuntime();
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
const apiRoot = getApiRoot();
|
|
165
|
+
if (!apiRoot || typeof apiRoot !== "object") return null;
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
const stack = getStack(metadataAPI.self);
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
if (stack.length < 1) return null;
|
|
172
|
+
|
|
173
|
+
const parsed = parseCallSite(stack[0]);
|
|
174
|
+
if (!parsed) return null;
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
const func = findFunctionByStack(apiRoot, parsed.file, parsed.line);
|
|
178
|
+
if (!func) return null;
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
return func.__metadata || null;
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
async get(path, apiRoot) {
|
|
186
|
+
|
|
187
|
+
await ensureRuntime();
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
const root = apiRoot || getApiRoot();
|
|
191
|
+
if (!root || (typeof root !== "object" && typeof root !== "function")) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const func = findFunctionByPath(root, path);
|
|
196
|
+
if (!func) return null;
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
return func.__metadata || null;
|
|
200
|
+
}
|
|
201
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Copyright
|
|
2
|
+
Copyright 2026 CLDMV/Shinrai
|
|
3
3
|
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
you may not use this file except in compliance with the License.
|
|
@@ -39,10 +39,19 @@ async function multidefault_analyzeModules(moduleFiles, baseDir, options = {}) {
|
|
|
39
39
|
const moduleFilePath = path.resolve(baseDir, file.name);
|
|
40
40
|
|
|
41
41
|
|
|
42
|
+
|
|
42
43
|
let importUrl = `file://${moduleFilePath.replace(/\\/g, "/")}`;
|
|
44
|
+
const separator = importUrl.includes("?") ? "&" : "?";
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
importUrl = `${importUrl}${separator}_t=${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
48
|
+
|
|
49
|
+
|
|
43
50
|
if (instance && instance.instanceId) {
|
|
44
|
-
const
|
|
45
|
-
|
|
51
|
+
const runtimeType = instance.config?.runtime || "async";
|
|
52
|
+
if (runtimeType === "live") {
|
|
53
|
+
importUrl = `${importUrl}&slothlet_instance=${instance.instanceId}`;
|
|
54
|
+
}
|
|
46
55
|
}
|
|
47
56
|
|
|
48
57
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Copyright
|
|
2
|
+
Copyright 2026 CLDMV/Shinrai
|
|
3
3
|
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
you may not use this file except in compliance with the License.
|
|
@@ -345,6 +345,11 @@ function createFolderProxy({ subDirPath, key, parent, instance, depth, maxDepth,
|
|
|
345
345
|
return pathParts.length > 0 ? pathParts.join(".") : undefined;
|
|
346
346
|
}
|
|
347
347
|
|
|
348
|
+
if (prop === "__metadata" || prop === "__sourceFolder") {
|
|
349
|
+
|
|
350
|
+
return Reflect.get(_t, prop);
|
|
351
|
+
}
|
|
352
|
+
|
|
348
353
|
if (materialized) {
|
|
349
354
|
if (materialized && (typeof materialized === "object" || typeof materialized === "function")) return materialized[prop];
|
|
350
355
|
return undefined;
|
|
@@ -485,6 +490,10 @@ function createFolderProxy({ subDirPath, key, parent, instance, depth, maxDepth,
|
|
|
485
490
|
if (prop === "__materialized") {
|
|
486
491
|
return { configurable: true, enumerable: false, writable: true, value: materialized };
|
|
487
492
|
}
|
|
493
|
+
|
|
494
|
+
if (prop === "__metadata" || prop === "__sourceFolder") {
|
|
495
|
+
return Reflect.getOwnPropertyDescriptor(lazy_lazyTarget, prop);
|
|
496
|
+
}
|
|
488
497
|
if (prop === "prototype") {
|
|
489
498
|
|
|
490
499
|
return Object.getOwnPropertyDescriptor(lazy_lazyTarget, "prototype");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Copyright
|
|
2
|
+
Copyright 2026 CLDMV/Shinrai
|
|
3
3
|
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
you may not use this file except in compliance with the License.
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
22
22
|
import util from "node:util";
|
|
23
23
|
import { enableAlsForEventEmitters } from "@cldmv/slothlet/helpers/als-eventemitter";
|
|
24
|
+
import { metadataAPI } from "@cldmv/slothlet/helpers/metadata-api";
|
|
24
25
|
|
|
25
26
|
const als = new AsyncLocalStorage();
|
|
26
27
|
|
|
@@ -565,3 +566,6 @@ export const context = runtime_createLiveBinding("context");
|
|
|
565
566
|
export const reference = runtime_createLiveBinding("reference");
|
|
566
567
|
|
|
567
568
|
|
|
569
|
+
export { metadataAPI };
|
|
570
|
+
|
|
571
|
+
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Copyright
|
|
2
|
+
Copyright 2026 CLDMV/Shinrai
|
|
3
3
|
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
you may not use this file except in compliance with the License.
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
setActiveInstance,
|
|
26
26
|
getCurrentActiveInstanceId
|
|
27
27
|
} from "@cldmv/slothlet/helpers/instance-manager";
|
|
28
|
+
import { metadataAPI } from "@cldmv/slothlet/helpers/metadata-api";
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
export const requestALS = new AsyncLocalStorage();
|
|
@@ -433,3 +434,6 @@ export const contextManager = {
|
|
|
433
434
|
set: setContext,
|
|
434
435
|
runWithCtx
|
|
435
436
|
};
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
export { metadataAPI };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Copyright
|
|
2
|
+
Copyright 2026 CLDMV/Shinrai
|
|
3
3
|
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
you may not use this file except in compliance with the License.
|
|
@@ -225,3 +225,14 @@ export const instanceId = (() => {
|
|
|
225
225
|
})();
|
|
226
226
|
|
|
227
227
|
export const sharedALS = getCurrentRuntime().sharedALS;
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
export const metadataAPI = new Proxy(
|
|
231
|
+
{},
|
|
232
|
+
{
|
|
233
|
+
get(_, prop) {
|
|
234
|
+
const runtime = getCurrentRuntime();
|
|
235
|
+
return runtime.metadataAPI[prop];
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
);
|
package/dist/slothlet.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Copyright
|
|
2
|
+
Copyright 2026 CLDMV/Shinrai
|
|
3
3
|
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
you may not use this file except in compliance with the License.
|
|
@@ -75,6 +75,11 @@ let DEBUG = process.argv.includes("--slothletdebug")
|
|
|
75
75
|
: false;
|
|
76
76
|
|
|
77
77
|
|
|
78
|
+
if (DEBUG && !process.env.SLOTHLET_DEBUG) {
|
|
79
|
+
process.env.SLOTHLET_DEBUG = "1";
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
78
83
|
export const self = {};
|
|
79
84
|
|
|
80
85
|
|
|
@@ -636,6 +641,17 @@ const slothletObject = {
|
|
|
636
641
|
}
|
|
637
642
|
|
|
638
643
|
|
|
644
|
+
const instanceIdDesc = Object.getOwnPropertyDescriptor(boundApi, "instanceId");
|
|
645
|
+
if (!instanceIdDesc || instanceIdDesc.configurable) {
|
|
646
|
+
Object.defineProperty(boundApi, "instanceId", {
|
|
647
|
+
value: this.instanceId,
|
|
648
|
+
writable: false,
|
|
649
|
+
configurable: true,
|
|
650
|
+
enumerable: false
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
|
|
639
655
|
const scopeDesc = Object.getOwnPropertyDescriptor(boundApi, "scope");
|
|
640
656
|
if (!scopeDesc || scopeDesc.configurable) {
|
|
641
657
|
Object.defineProperty(boundApi, "scope", {
|
|
@@ -678,8 +694,8 @@ const slothletObject = {
|
|
|
678
694
|
},
|
|
679
695
|
|
|
680
696
|
|
|
681
|
-
async addApi(apiPath, folderPath) {
|
|
682
|
-
return addApiFromFolder({ apiPath, folderPath, instance: this });
|
|
697
|
+
async addApi(apiPath, folderPath, metadata = {}) {
|
|
698
|
+
return addApiFromFolder({ apiPath, folderPath, instance: this, metadata });
|
|
683
699
|
},
|
|
684
700
|
|
|
685
701
|
|
package/package.json
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* @param {string} options.apiPath - Dot-notation path where modules will be added
|
|
8
8
|
* @param {string} options.folderPath - Path to folder containing modules to load
|
|
9
9
|
* @param {object} options.instance - Slothlet instance with api, boundapi, config, modes, etc.
|
|
10
|
+
* @param {object} [options.metadata={}] - Metadata to attach to all loaded functions
|
|
10
11
|
* @returns {Promise<void>}
|
|
11
12
|
* @throws {Error} If API not loaded, invalid parameters, folder does not exist, or merge conflicts
|
|
12
13
|
* @package
|
|
@@ -51,10 +52,25 @@
|
|
|
51
52
|
* folderPath: "./services/stripe",
|
|
52
53
|
* instance: slothletInstance
|
|
53
54
|
* });
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* // Add modules with metadata
|
|
58
|
+
* await addApiFromFolder({
|
|
59
|
+
* apiPath: "plugins",
|
|
60
|
+
* folderPath: "./untrusted-plugins",
|
|
61
|
+
* instance: slothletInstance,
|
|
62
|
+
* metadata: {
|
|
63
|
+
* trusted: false,
|
|
64
|
+
* permissions: ["read"],
|
|
65
|
+
* version: "1.0.0",
|
|
66
|
+
* author: "external"
|
|
67
|
+
* }
|
|
68
|
+
* });
|
|
54
69
|
*/
|
|
55
|
-
export function addApiFromFolder({ apiPath, folderPath, instance }: {
|
|
70
|
+
export function addApiFromFolder({ apiPath, folderPath, instance, metadata }: {
|
|
56
71
|
apiPath: string;
|
|
57
72
|
folderPath: string;
|
|
58
73
|
instance: object;
|
|
74
|
+
metadata?: object;
|
|
59
75
|
}): Promise<void>;
|
|
60
76
|
//# sourceMappingURL=add_api.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add_api.d.mts","sourceRoot":"","sources":["../../../../../dist/lib/helpers/api_builder/add_api.mjs"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"add_api.d.mts","sourceRoot":"","sources":["../../../../../dist/lib/helpers/api_builder/add_api.mjs"],"names":[],"mappings":"AAkDA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoEG;AACH,8EA/DG;IAAwB,OAAO,EAAvB,MAAM;IACU,UAAU,EAA1B,MAAM;IACU,QAAQ,EAAxB,MAAM;IACW,QAAQ,GAAzB,MAAM;CACd,GAAU,OAAO,CAAC,IAAI,CAAC,CAoUzB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analysis.d.mts","sourceRoot":"","sources":["../../../../../dist/lib/helpers/api_builder/analysis.mjs"],"names":[],"mappings":"AA0CA;;;;;;;;GAQG;AACH,0CAHW,GAAC,GACC,OAAO,CAcnB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,0CAvBW,MAAM,YAEd;IAA0B,KAAK,GAAvB,OAAO;IACU,QAAQ,GAAzB,MAAM;CACd,GAAU,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAC9B,iBAAiB,EAAE,UAAU,GAAC,QAAQ,GAAC,IAAI,CAAC;IAC5C,oBAAoB,EAAE,OAAO,CAAC;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAC,
|
|
1
|
+
{"version":3,"file":"analysis.d.mts","sourceRoot":"","sources":["../../../../../dist/lib/helpers/api_builder/analysis.mjs"],"names":[],"mappings":"AA0CA;;;;;;;;GAQG;AACH,0CAHW,GAAC,GACC,OAAO,CAcnB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,0CAvBW,MAAM,YAEd;IAA0B,KAAK,GAAvB,OAAO;IACU,QAAQ,GAAzB,MAAM;CACd,GAAU,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAC9B,iBAAiB,EAAE,UAAU,GAAC,QAAQ,GAAC,IAAI,CAAC;IAC5C,oBAAoB,EAAE,OAAO,CAAC;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAC,CA4GJ;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,oDAZW,MAAM,YAEd;IAAyB,QAAQ,GAAzB,MAAM;IACY,KAAK,GAAvB,OAAO;CACf,GAAU,MAAM,CA4NlB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wDA1BW,MAAM,YAEd;IAAwB,QAAQ,EAAxB,MAAM;IACW,YAAY,GAA7B,MAAM;IACW,QAAQ,GAAzB,MAAM;IACY,KAAK,GAAvB,OAAO;CACf,GAAU,OAAO,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE,MAAM,CAAC,CAAC;IACxC,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE,MAAM,CAAC,CAAC;IACpC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,kBAAkB,EAAE,aAAa,GAAC,YAAY,GAAC,OAAO,CAAC;IACvD,eAAe,EAAE,MAAM,CAAA;CACxB,CAAC,CAkEJ;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,2DA1BW,MAAM,YAEd;IAAwB,QAAQ,EAAxB,MAAM;IACW,YAAY,GAA7B,MAAM;IACW,QAAQ,GAAzB,MAAM;IACY,KAAK,GAAvB,OAAO;CACf,GAAU,OAAO,CAAC;IAChB,kBAAkB,EAAE,aAAa,GAAC,YAAY,GAAC,OAAO,CAAC;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,gBAAgB,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,OAAO,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,GAAG,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IACnH,cAAc,EAAE,KAAK,CAAC;QAAC,QAAQ,EAAE,OAAO,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IAC3E,oBAAoB,EAAE,MAAM,CAAC;IAC7B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,yBAAyB,EAAE;QAAC,aAAa,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAC,CAAA;CACxE,CAAC,CAmHJ"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @Project: @cldmv/slothlet
|
|
3
|
+
* @Filename: /src/lib/helpers/api_builder/metadata.mjs
|
|
4
|
+
* @Date: 2025-12-31 00:00:00 -08:00
|
|
5
|
+
* @Author: Nate Hyson <CLDMV>
|
|
6
|
+
* @Email: <Shinrai@users.noreply.github.com>
|
|
7
|
+
* -----
|
|
8
|
+
* @Last modified by: Nate Hyson <CLDMV> (Shinrai@users.noreply.github.com)
|
|
9
|
+
* @Last modified time: 2025-12-31 22:30:16 -08:00 (1767249016)
|
|
10
|
+
* -----
|
|
11
|
+
* @Copyright: Copyright (c) 2013-2025 Catalyzed Motivation Inc. All rights reserved.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* @fileoverview Metadata management utilities for API functions.
|
|
15
|
+
* @module @cldmv/slothlet/lib/helpers/api_builder/metadata
|
|
16
|
+
* @memberof module:@cldmv/slothlet.lib.helpers.api_builder
|
|
17
|
+
* @internal
|
|
18
|
+
* @private
|
|
19
|
+
*
|
|
20
|
+
* @description
|
|
21
|
+
* Provides utilities for tagging functions with immutable metadata, cleaning stale metadata
|
|
22
|
+
* from cached modules, and creating immutable metadata objects with deep freezing.
|
|
23
|
+
*
|
|
24
|
+
* Key Features:
|
|
25
|
+
* - Immutable metadata with Proxy-based enforcement
|
|
26
|
+
* - Deep freezing of nested objects and arrays
|
|
27
|
+
* - Recursive traversal for tagging/cleaning object trees
|
|
28
|
+
* - CommonJS cache-aware metadata cleanup
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* Creates an immutable-but-extensible metadata proxy object.
|
|
32
|
+
*
|
|
33
|
+
* @function createImmutableMetadata
|
|
34
|
+
* @param {object} initial - Initial metadata properties
|
|
35
|
+
* @returns {object} Object with immutable existing properties but allows adding new ones
|
|
36
|
+
*
|
|
37
|
+
* @description
|
|
38
|
+
* Creates an object that enforces immutability of existing properties while allowing
|
|
39
|
+
* new properties to be added. This prevents tampering with security-critical metadata
|
|
40
|
+
* while allowing runtime extension of metadata for additional context.
|
|
41
|
+
*
|
|
42
|
+
* Security features:
|
|
43
|
+
* - Existing properties cannot be modified (non-writable, non-configurable after first set)
|
|
44
|
+
* - Properties cannot be deleted
|
|
45
|
+
* - New properties can be added, which then become immutable
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* const meta = createImmutableMetadata({ trusted: true, version: "1.0" });
|
|
49
|
+
* meta.author = "Alice"; // OK - new property
|
|
50
|
+
* meta.author = "Bob"; // FAIL - cannot modify after setting
|
|
51
|
+
* meta.trusted = false; // FAIL - cannot modify existing property
|
|
52
|
+
* delete meta.version; // FAIL - cannot delete properties
|
|
53
|
+
*/
|
|
54
|
+
export function createImmutableMetadata(initial?: object): object;
|
|
55
|
+
/**
|
|
56
|
+
* Removes metadata from all functions in an object tree.
|
|
57
|
+
*
|
|
58
|
+
* @function cleanMetadata
|
|
59
|
+
* @param {object|Function} obj - Object or function to clean
|
|
60
|
+
* @param {WeakSet} [visited] - Visited objects tracker to prevent infinite recursion
|
|
61
|
+
* @returns {void}
|
|
62
|
+
*
|
|
63
|
+
* @description
|
|
64
|
+
* Traverses an object/function tree and removes __metadata and __sourceFolder properties.
|
|
65
|
+
* This is needed when reloading CommonJS modules that cache function object references.
|
|
66
|
+
*/
|
|
67
|
+
export function cleanMetadata(obj: object | Function, visited?: WeakSet<any>): void;
|
|
68
|
+
/**
|
|
69
|
+
* Recursively tags all functions in an object tree with metadata.
|
|
70
|
+
*
|
|
71
|
+
* @function tagLoadedFunctions
|
|
72
|
+
* @param {object|Function} obj - Object or function to tag
|
|
73
|
+
* @param {object} metadata - Metadata object to attach
|
|
74
|
+
* @param {string} baseDir - Base directory path for relative file tracking
|
|
75
|
+
* @param {WeakSet} [visited] - Visited objects tracker to prevent infinite recursion
|
|
76
|
+
* @returns {void}
|
|
77
|
+
*
|
|
78
|
+
* @description
|
|
79
|
+
* Traverses an object/function tree and attaches immutable metadata to all functions.
|
|
80
|
+
* Also tracks source file information (__sourceFile, __sourceLine) for stack trace
|
|
81
|
+
* matching. Only tags functions that don't already have metadata (non-overwriting).
|
|
82
|
+
*
|
|
83
|
+
* Attached properties:
|
|
84
|
+
* - __metadata: Immutable metadata proxy with all user-provided metadata
|
|
85
|
+
* - __sourceFolder: Absolute path to the folder the module was loaded from
|
|
86
|
+
* - __sourceFile: Absolute file path (for stack trace matching)
|
|
87
|
+
* - __sourceLine: Line number where function is defined (for stack trace matching)
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* const modules = { math: { add: (a, b) => a + b } };
|
|
91
|
+
* tagLoadedFunctions(modules, {
|
|
92
|
+
* trusted: true,
|
|
93
|
+
* version: "1.0.0",
|
|
94
|
+
* author: "Alice"
|
|
95
|
+
* }, "/path/to/plugins");
|
|
96
|
+
* // Now modules.math.add.__metadata.trusted === true
|
|
97
|
+
*/
|
|
98
|
+
export function tagLoadedFunctions(obj: object | Function, metadata: object, baseDir: string, visited?: WeakSet<any>): void;
|
|
99
|
+
//# sourceMappingURL=metadata.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.d.mts","sourceRoot":"","sources":["../../../../../dist/lib/helpers/api_builder/metadata.mjs"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,kDApBW,MAAM,GACJ,MAAM,CAmJlB;AAED;;;;;;;;;;;GAWG;AACH,mCARW,MAAM,WAAS,2BAEb,IAAI,CAyChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wCA1BW,MAAM,WAAS,YACf,MAAM,WACN,MAAM,2BAEJ,IAAI,CA+EhB"}
|