@cldmv/slothlet 2.10.0 → 3.0.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 +365 -294
- package/README.md +556 -233
- package/dist/lib/builders/api-assignment.mjs +605 -0
- package/dist/lib/builders/api_builder.mjs +1073 -0
- package/dist/lib/builders/builder.mjs +94 -0
- package/dist/lib/builders/modes-processor.mjs +1816 -0
- package/dist/lib/errors.mjs +227 -0
- package/dist/lib/factories/component-base.mjs +96 -0
- package/dist/lib/factories/context.mjs +38 -0
- package/dist/lib/handlers/api-cache-manager.mjs +216 -0
- package/dist/lib/handlers/api-manager.mjs +2364 -0
- package/dist/lib/handlers/context-async.mjs +184 -0
- package/dist/lib/handlers/context-live.mjs +184 -0
- package/dist/lib/handlers/hook-manager.mjs +789 -0
- package/dist/lib/handlers/lifecycle-token.mjs +44 -0
- package/dist/lib/handlers/lifecycle.mjs +131 -0
- package/dist/lib/handlers/materialize-manager.mjs +64 -0
- package/dist/lib/handlers/metadata.mjs +500 -0
- package/dist/lib/handlers/ownership.mjs +338 -0
- package/dist/lib/handlers/unified-wrapper.mjs +3031 -0
- package/dist/lib/helpers/class-instance-wrapper.mjs +125 -0
- package/dist/lib/helpers/config.mjs +343 -0
- package/dist/lib/helpers/eventemitter-context.mjs +365 -0
- package/dist/lib/helpers/hint-detector.mjs +63 -0
- package/dist/lib/helpers/modes-utils.mjs +53 -0
- package/dist/lib/helpers/resolve-from-caller.mjs +125 -85
- package/dist/lib/helpers/sanitize.mjs +247 -168
- package/dist/lib/helpers/utilities.mjs +46 -81
- package/dist/lib/i18n/languages/de-de.json +377 -0
- package/dist/lib/i18n/languages/en-gb.json +377 -0
- package/dist/lib/i18n/languages/en-us.json +377 -0
- package/dist/lib/i18n/languages/es-mx.json +377 -0
- package/dist/lib/i18n/languages/fr-fr.json +377 -0
- package/dist/lib/i18n/languages/hi-in.json +377 -0
- package/dist/lib/i18n/languages/ja-jp.json +377 -0
- package/dist/lib/i18n/languages/ko-kr.json +377 -0
- package/dist/lib/i18n/languages/pt-br.json +377 -0
- package/dist/lib/i18n/languages/ru-ru.json +377 -0
- package/dist/lib/i18n/languages/zh-cn.json +377 -0
- package/dist/lib/i18n/translations.mjs +140 -0
- package/dist/lib/modes/eager.mjs +75 -0
- package/dist/lib/modes/lazy.mjs +97 -0
- package/dist/lib/processors/flatten.mjs +453 -0
- package/dist/lib/processors/loader.mjs +355 -0
- package/dist/lib/processors/type-generator.mjs +291 -0
- package/dist/lib/processors/typescript.mjs +188 -0
- package/dist/lib/runtime/runtime-asynclocalstorage.mjs +80 -522
- package/dist/lib/runtime/runtime-livebindings.mjs +45 -390
- package/dist/lib/runtime/runtime.mjs +39 -159
- package/dist/slothlet.mjs +529 -700
- package/docs/API-RULES.md +497 -617
- package/index.cjs +4 -4
- package/index.mjs +82 -45
- package/package.json +139 -26
- package/types/dist/lib/builders/api-assignment.d.mts +97 -0
- package/types/dist/lib/builders/api-assignment.d.mts.map +1 -0
- package/types/dist/lib/builders/api_builder.d.mts +96 -0
- package/types/dist/lib/builders/api_builder.d.mts.map +1 -0
- package/types/dist/lib/builders/builder.d.mts +60 -0
- package/types/dist/lib/builders/builder.d.mts.map +1 -0
- package/types/dist/lib/builders/modes-processor.d.mts +32 -0
- package/types/dist/lib/builders/modes-processor.d.mts.map +1 -0
- package/types/dist/lib/errors.d.mts +118 -0
- package/types/dist/lib/errors.d.mts.map +1 -0
- package/types/dist/lib/factories/component-base.d.mts +182 -0
- package/types/dist/lib/factories/component-base.d.mts.map +1 -0
- package/types/dist/lib/factories/context.d.mts +26 -0
- package/types/dist/lib/factories/context.d.mts.map +1 -0
- package/types/dist/lib/handlers/api-cache-manager.d.mts +208 -0
- package/types/dist/lib/handlers/api-cache-manager.d.mts.map +1 -0
- package/types/dist/lib/handlers/api-manager.d.mts +392 -0
- package/types/dist/lib/handlers/api-manager.d.mts.map +1 -0
- package/types/dist/lib/handlers/context-async.d.mts +66 -0
- package/types/dist/lib/handlers/context-async.d.mts.map +1 -0
- package/types/dist/lib/handlers/context-live.d.mts +65 -0
- package/types/dist/lib/handlers/context-live.d.mts.map +1 -0
- package/types/dist/lib/handlers/hook-manager.d.mts +199 -0
- package/types/dist/lib/handlers/hook-manager.d.mts.map +1 -0
- package/types/dist/lib/handlers/lifecycle-token.d.mts +49 -0
- package/types/dist/lib/handlers/lifecycle-token.d.mts.map +1 -0
- package/types/dist/lib/handlers/lifecycle.d.mts +90 -0
- package/types/dist/lib/handlers/lifecycle.d.mts.map +1 -0
- package/types/dist/lib/handlers/materialize-manager.d.mts +75 -0
- package/types/dist/lib/handlers/materialize-manager.d.mts.map +1 -0
- package/types/dist/lib/handlers/metadata.d.mts +215 -0
- package/types/dist/lib/handlers/metadata.d.mts.map +1 -0
- package/types/dist/lib/handlers/ownership.d.mts +170 -0
- package/types/dist/lib/handlers/ownership.d.mts.map +1 -0
- package/types/dist/lib/handlers/unified-wrapper.d.mts +250 -0
- package/types/dist/lib/handlers/unified-wrapper.d.mts.map +1 -0
- package/types/dist/lib/helpers/class-instance-wrapper.d.mts +54 -0
- package/types/dist/lib/helpers/class-instance-wrapper.d.mts.map +1 -0
- package/types/dist/lib/helpers/config.d.mts +96 -0
- package/types/dist/lib/helpers/config.d.mts.map +1 -0
- package/types/dist/lib/helpers/eventemitter-context.d.mts +31 -0
- package/types/dist/lib/helpers/eventemitter-context.d.mts.map +1 -0
- package/types/dist/lib/helpers/hint-detector.d.mts +20 -0
- package/types/dist/lib/helpers/hint-detector.d.mts.map +1 -0
- package/types/dist/lib/helpers/modes-utils.d.mts +35 -0
- package/types/dist/lib/helpers/modes-utils.d.mts.map +1 -0
- package/types/dist/lib/helpers/resolve-from-caller.d.mts +29 -145
- package/types/dist/lib/helpers/resolve-from-caller.d.mts.map +1 -1
- package/types/dist/lib/helpers/sanitize.d.mts +95 -94
- package/types/dist/lib/helpers/sanitize.d.mts.map +1 -1
- package/types/dist/lib/helpers/utilities.d.mts +53 -116
- package/types/dist/lib/helpers/utilities.d.mts.map +1 -1
- package/types/dist/lib/i18n/translations.d.mts +39 -0
- package/types/dist/lib/i18n/translations.d.mts.map +1 -0
- package/types/dist/lib/modes/eager.d.mts +36 -0
- package/types/dist/lib/modes/eager.d.mts.map +1 -0
- package/types/dist/lib/modes/lazy.d.mts +49 -0
- package/types/dist/lib/modes/lazy.d.mts.map +1 -0
- package/types/dist/lib/processors/flatten.d.mts +114 -0
- package/types/dist/lib/processors/flatten.d.mts.map +1 -0
- package/types/dist/lib/processors/loader.d.mts +47 -0
- package/types/dist/lib/processors/loader.d.mts.map +1 -0
- package/types/dist/lib/processors/type-generator.d.mts +19 -0
- package/types/dist/lib/processors/type-generator.d.mts.map +1 -0
- package/types/dist/lib/processors/typescript.d.mts +55 -0
- package/types/dist/lib/processors/typescript.d.mts.map +1 -0
- package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts +47 -42
- package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts.map +1 -1
- package/types/dist/lib/runtime/runtime-livebindings.d.mts +34 -65
- package/types/dist/lib/runtime/runtime-livebindings.d.mts.map +1 -1
- package/types/dist/lib/runtime/runtime.d.mts +39 -9
- package/types/dist/lib/runtime/runtime.d.mts.map +1 -1
- package/types/dist/slothlet.d.mts +186 -105
- package/types/dist/slothlet.d.mts.map +1 -1
- package/types/index.d.mts +1 -3
- package/dist/lib/engine/README.md +0 -21
- package/dist/lib/engine/slothlet_child.mjs +0 -59
- package/dist/lib/engine/slothlet_engine.mjs +0 -372
- package/dist/lib/engine/slothlet_esm.mjs +0 -230
- package/dist/lib/engine/slothlet_helpers.mjs +0 -455
- package/dist/lib/engine/slothlet_worker.mjs +0 -149
- package/dist/lib/helpers/als-eventemitter.mjs +0 -256
- package/dist/lib/helpers/api_builder/add_api.mjs +0 -292
- package/dist/lib/helpers/api_builder/analysis.mjs +0 -532
- package/dist/lib/helpers/api_builder/construction.mjs +0 -457
- package/dist/lib/helpers/api_builder/decisions.mjs +0 -737
- package/dist/lib/helpers/api_builder/metadata.mjs +0 -248
- package/dist/lib/helpers/api_builder.mjs +0 -41
- package/dist/lib/helpers/auto-wrap.mjs +0 -62
- package/dist/lib/helpers/hooks.mjs +0 -389
- package/dist/lib/helpers/instance-manager.mjs +0 -111
- package/dist/lib/helpers/metadata-api.mjs +0 -201
- package/dist/lib/helpers/multidefault.mjs +0 -216
- package/dist/lib/modes/slothlet_eager.mjs +0 -126
- package/dist/lib/modes/slothlet_lazy.mjs +0 -513
- package/docs/API-RULES-CONDITIONS.md +0 -508
- package/types/dist/lib/engine/slothlet_child.d.mts +0 -2
- package/types/dist/lib/engine/slothlet_child.d.mts.map +0 -1
- package/types/dist/lib/engine/slothlet_engine.d.mts +0 -31
- package/types/dist/lib/engine/slothlet_engine.d.mts.map +0 -1
- package/types/dist/lib/engine/slothlet_esm.d.mts +0 -19
- package/types/dist/lib/engine/slothlet_esm.d.mts.map +0 -1
- package/types/dist/lib/engine/slothlet_helpers.d.mts +0 -25
- package/types/dist/lib/engine/slothlet_helpers.d.mts.map +0 -1
- package/types/dist/lib/engine/slothlet_worker.d.mts +0 -2
- package/types/dist/lib/engine/slothlet_worker.d.mts.map +0 -1
- package/types/dist/lib/helpers/als-eventemitter.d.mts +0 -56
- package/types/dist/lib/helpers/als-eventemitter.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/add_api.d.mts +0 -76
- package/types/dist/lib/helpers/api_builder/add_api.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/analysis.d.mts +0 -189
- package/types/dist/lib/helpers/api_builder/analysis.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/construction.d.mts +0 -107
- package/types/dist/lib/helpers/api_builder/construction.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/decisions.d.mts +0 -213
- package/types/dist/lib/helpers/api_builder/decisions.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/metadata.d.mts +0 -99
- package/types/dist/lib/helpers/api_builder/metadata.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder.d.mts +0 -6
- package/types/dist/lib/helpers/api_builder.d.mts.map +0 -1
- package/types/dist/lib/helpers/auto-wrap.d.mts +0 -49
- package/types/dist/lib/helpers/auto-wrap.d.mts.map +0 -1
- package/types/dist/lib/helpers/hooks.d.mts +0 -342
- package/types/dist/lib/helpers/hooks.d.mts.map +0 -1
- package/types/dist/lib/helpers/instance-manager.d.mts +0 -41
- package/types/dist/lib/helpers/instance-manager.d.mts.map +0 -1
- package/types/dist/lib/helpers/metadata-api.d.mts +0 -132
- package/types/dist/lib/helpers/metadata-api.d.mts.map +0 -1
- package/types/dist/lib/helpers/multidefault.d.mts +0 -90
- package/types/dist/lib/helpers/multidefault.d.mts.map +0 -1
- package/types/dist/lib/modes/slothlet_eager.d.mts +0 -65
- package/types/dist/lib/modes/slothlet_eager.d.mts.map +0 -1
- package/types/dist/lib/modes/slothlet_lazy.d.mts +0 -31
- package/types/dist/lib/modes/slothlet_lazy.d.mts.map +0 -1
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2026 CLDMV/Shinrai
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
import { AsyncResource, AsyncLocalStorage } from "node:async_hooks";
|
|
22
|
-
import { EventEmitter } from "node:events";
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const defaultALS = new AsyncLocalStorage();
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
let originalMethods = null;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const globalResourceSet = new Set();
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const globalListenerTracker = new WeakMap();
|
|
36
|
-
const allPatchedListeners = new Set();
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
export function enableAlsForEventEmitters(als = defaultALS) {
|
|
40
|
-
|
|
41
|
-
const kPatched = Symbol.for("slothlet.als.patched");
|
|
42
|
-
|
|
43
|
-
if (EventEmitter.prototype[kPatched]) return;
|
|
44
|
-
EventEmitter.prototype[kPatched] = true;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const kMap = Symbol("slothlet.als.listenerMap");
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
function runtime_ensureMap(emitter) {
|
|
51
|
-
if (!emitter[kMap]) emitter[kMap] = new WeakMap();
|
|
52
|
-
return emitter[kMap];
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
function runtime_wrapListener(listener) {
|
|
57
|
-
|
|
58
|
-
const store = als.getStore();
|
|
59
|
-
if (!store) return listener;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const resource = new AsyncResource("slothlet-als-listener");
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
globalResourceSet.add(resource);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const runtime_wrappedListener = function (...args) {
|
|
69
|
-
return resource.runInAsyncScope(
|
|
70
|
-
() => {
|
|
71
|
-
return listener.apply(this, args);
|
|
72
|
-
},
|
|
73
|
-
this,
|
|
74
|
-
...args
|
|
75
|
-
);
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
runtime_wrappedListener._slothletResource = resource;
|
|
80
|
-
|
|
81
|
-
return runtime_wrappedListener;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const proto = EventEmitter.prototype;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const origOn = proto.on;
|
|
88
|
-
const origOnce = proto.once;
|
|
89
|
-
const origAdd = proto.addListener;
|
|
90
|
-
const origPre = proto.prependListener;
|
|
91
|
-
const origPreO = proto.prependOnceListener;
|
|
92
|
-
const origOff = proto.off ?? proto.removeListener;
|
|
93
|
-
const origRem = proto.removeListener;
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
function runtime_installWrapper(addFnName, orig) {
|
|
97
|
-
proto[addFnName] = function (event, listener) {
|
|
98
|
-
const map = runtime_ensureMap(this);
|
|
99
|
-
const wrapped = runtime_wrapListener(listener);
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (!globalListenerTracker.has(this)) {
|
|
104
|
-
globalListenerTracker.set(this, new Set());
|
|
105
|
-
}
|
|
106
|
-
const listenerInfo = {
|
|
107
|
-
emitter: this,
|
|
108
|
-
event,
|
|
109
|
-
originalListener: listener,
|
|
110
|
-
wrappedListener: wrapped,
|
|
111
|
-
addMethod: addFnName
|
|
112
|
-
};
|
|
113
|
-
globalListenerTracker.get(this).add(listenerInfo);
|
|
114
|
-
allPatchedListeners.add(listenerInfo);
|
|
115
|
-
|
|
116
|
-
if (wrapped !== listener) map.set(listener, wrapped);
|
|
117
|
-
return orig.call(this, event, wrapped);
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
runtime_installWrapper("on", origOn);
|
|
123
|
-
runtime_installWrapper("once", origOnce);
|
|
124
|
-
runtime_installWrapper("addListener", origAdd);
|
|
125
|
-
if (origPre) runtime_installWrapper("prependListener", origPre);
|
|
126
|
-
if (origPreO) runtime_installWrapper("prependOnceListener", origPreO);
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
function runtime_createRemoveWrapper(method) {
|
|
130
|
-
|
|
131
|
-
const runtime_removeWrapper = function (event, listener) {
|
|
132
|
-
const map = runtime_ensureMap(this);
|
|
133
|
-
const wrapped = map.get(listener) || listener;
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if (globalListenerTracker.has(this)) {
|
|
137
|
-
const emitterListeners = globalListenerTracker.get(this);
|
|
138
|
-
for (const info of emitterListeners) {
|
|
139
|
-
if (info.originalListener === listener || info.wrappedListener === wrapped) {
|
|
140
|
-
emitterListeners.delete(info);
|
|
141
|
-
allPatchedListeners.delete(info);
|
|
142
|
-
break;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if (wrapped && wrapped._slothletResource) {
|
|
149
|
-
const resource = wrapped._slothletResource;
|
|
150
|
-
globalResourceSet.delete(resource);
|
|
151
|
-
try {
|
|
152
|
-
resource.emitDestroy();
|
|
153
|
-
} catch (_) {
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
map.delete(listener);
|
|
159
|
-
return method.call(this, event, wrapped);
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
return runtime_removeWrapper;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
if (proto.off) proto.off = runtime_createRemoveWrapper(origOff);
|
|
167
|
-
proto.removeListener = runtime_createRemoveWrapper(origRem);
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
const origRemoveAll = proto.removeAllListeners;
|
|
171
|
-
proto.removeAllListeners = function (event) {
|
|
172
|
-
const res = origRemoveAll.call(this, event);
|
|
173
|
-
if (this[kMap]) this[kMap] = new WeakMap();
|
|
174
|
-
return res;
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (!originalMethods) {
|
|
179
|
-
originalMethods = {
|
|
180
|
-
on: origOn,
|
|
181
|
-
once: origOnce,
|
|
182
|
-
addListener: origAdd,
|
|
183
|
-
prependListener: origPre,
|
|
184
|
-
prependOnceListener: origPreO,
|
|
185
|
-
off: origOff,
|
|
186
|
-
removeListener: origRem,
|
|
187
|
-
removeAllListeners: origRemoveAll
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
export function cleanupAllSlothletListeners() {
|
|
195
|
-
let cleanedCount = 0;
|
|
196
|
-
let errorCount = 0;
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
for (const listenerInfo of allPatchedListeners) {
|
|
200
|
-
try {
|
|
201
|
-
const { emitter, event, wrappedListener } = listenerInfo;
|
|
202
|
-
if (emitter && typeof emitter.removeListener === "function") {
|
|
203
|
-
emitter.removeListener(event, wrappedListener);
|
|
204
|
-
cleanedCount++;
|
|
205
|
-
}
|
|
206
|
-
} catch (_) {
|
|
207
|
-
errorCount++;
|
|
208
|
-
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
allPatchedListeners.clear();
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
if (process.env.SLOTHLET_DEBUG === "1" || process.env.SLOTHLET_DEBUG === "true") {
|
|
217
|
-
console.log(`[slothlet] Cleaned up ${cleanedCount} listeners (${errorCount} errors)`);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
export function disableAlsForEventEmitters() {
|
|
222
|
-
const kPatched = Symbol.for("slothlet.als.patched");
|
|
223
|
-
|
|
224
|
-
if (!EventEmitter.prototype[kPatched] || !originalMethods) return;
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
cleanupAllSlothletListeners();
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
for (const resource of globalResourceSet) {
|
|
231
|
-
try {
|
|
232
|
-
resource.emitDestroy();
|
|
233
|
-
} catch (err) {
|
|
234
|
-
|
|
235
|
-
console.warn("[slothlet] AsyncResource cleanup warning:", err.message);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
globalResourceSet.clear();
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
const proto = EventEmitter.prototype;
|
|
242
|
-
proto.on = originalMethods.on;
|
|
243
|
-
proto.once = originalMethods.once;
|
|
244
|
-
proto.addListener = originalMethods.addListener;
|
|
245
|
-
if (originalMethods.prependListener) proto.prependListener = originalMethods.prependListener;
|
|
246
|
-
if (originalMethods.prependOnceListener) proto.prependOnceListener = originalMethods.prependOnceListener;
|
|
247
|
-
if (originalMethods.off) proto.off = originalMethods.off;
|
|
248
|
-
proto.removeListener = originalMethods.removeListener;
|
|
249
|
-
proto.removeAllListeners = originalMethods.removeAllListeners;
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
delete EventEmitter.prototype[kPatched];
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
originalMethods = null;
|
|
256
|
-
}
|
|
@@ -1,292 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2026 CLDMV/Shinrai
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
import fs from "node:fs/promises";
|
|
22
|
-
import path from "node:path";
|
|
23
|
-
import { resolvePathFromCaller } from "@cldmv/slothlet/helpers/resolve-from-caller";
|
|
24
|
-
import { cleanMetadata, tagLoadedFunctions } from "./metadata.mjs";
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
export async function addApiFromFolder({ apiPath, folderPath, instance, metadata = {} }) {
|
|
28
|
-
if (!instance.loaded) {
|
|
29
|
-
throw new Error("[slothlet] Cannot add API: API not loaded. Call create() or load() first.");
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (typeof apiPath !== "string") {
|
|
34
|
-
throw new TypeError("[slothlet] addApi: 'apiPath' must be a string.");
|
|
35
|
-
}
|
|
36
|
-
const normalizedApiPath = apiPath.trim();
|
|
37
|
-
if (normalizedApiPath === "") {
|
|
38
|
-
throw new TypeError("[slothlet] addApi: 'apiPath' must be a non-empty, non-whitespace string.");
|
|
39
|
-
}
|
|
40
|
-
const pathParts = normalizedApiPath.split(".");
|
|
41
|
-
if (pathParts.some((part) => part === "")) {
|
|
42
|
-
throw new Error(`[slothlet] addApi: 'apiPath' must not contain empty segments. Received: "${normalizedApiPath}"`);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (typeof folderPath !== "string") {
|
|
47
|
-
throw new TypeError("[slothlet] addApi: 'folderPath' must be a string.");
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
let resolvedFolderPath = folderPath;
|
|
54
|
-
const isAbsolute = path.isAbsolute(folderPath);
|
|
55
|
-
|
|
56
|
-
if (instance.config.debug) {
|
|
57
|
-
console.log(`[DEBUG] addApi: folderPath="${folderPath}"`);
|
|
58
|
-
console.log(`[DEBUG] addApi: isAbsolute=${isAbsolute}`);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (!isAbsolute) {
|
|
62
|
-
resolvedFolderPath = resolvePathFromCaller(folderPath);
|
|
63
|
-
if (instance.config.debug) {
|
|
64
|
-
console.log(`[DEBUG] addApi: Resolved relative path to: ${resolvedFolderPath}`);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
let stats;
|
|
70
|
-
try {
|
|
71
|
-
stats = await fs.stat(resolvedFolderPath);
|
|
72
|
-
} catch (error) {
|
|
73
|
-
throw new Error(`[slothlet] addApi: Cannot access folder: ${resolvedFolderPath} - ${error.message}`);
|
|
74
|
-
}
|
|
75
|
-
if (!stats.isDirectory()) {
|
|
76
|
-
throw new Error(`[slothlet] addApi: Path is not a directory: ${resolvedFolderPath}`);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (instance.config.debug) {
|
|
80
|
-
console.log(`[DEBUG] addApi: Loading modules from ${resolvedFolderPath} to path: ${normalizedApiPath}`);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
let newModules;
|
|
85
|
-
if (instance.config.lazy) {
|
|
86
|
-
|
|
87
|
-
newModules = await instance.modes.lazy.create.call(instance, resolvedFolderPath, instance.config.apiDepth || Infinity, 0);
|
|
88
|
-
} else {
|
|
89
|
-
|
|
90
|
-
newModules = await instance.modes.eager.create.call(instance, resolvedFolderPath, instance.config.apiDepth || Infinity, 0);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (newModules && metadata && typeof metadata === "object" && Object.keys(metadata).length > 0) {
|
|
97
|
-
|
|
98
|
-
const fullMetadata = {
|
|
99
|
-
...metadata,
|
|
100
|
-
sourceFolder: resolvedFolderPath
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
if (instance.config.debug) {
|
|
104
|
-
console.log(`[DEBUG] addApi: Tagging functions with metadata:`, Object.keys(fullMetadata));
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
tagLoadedFunctions(newModules, fullMetadata, resolvedFolderPath);
|
|
108
|
-
} else if (newModules) {
|
|
109
|
-
|
|
110
|
-
if (instance.config.debug) {
|
|
111
|
-
console.log(`[DEBUG] addApi: Cleaning metadata from functions (no metadata provided)`);
|
|
112
|
-
}
|
|
113
|
-
cleanMetadata(newModules);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if (instance.config.debug) {
|
|
117
|
-
if (newModules && typeof newModules === "object") {
|
|
118
|
-
console.log(`[DEBUG] addApi: Loaded modules:`, Object.keys(newModules));
|
|
119
|
-
} else {
|
|
120
|
-
console.log(
|
|
121
|
-
`[DEBUG] addApi: Loaded modules (non-object):`,
|
|
122
|
-
typeof newModules === "function" ? `[Function: ${newModules.name || "anonymous"}]` : newModules
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
let currentTarget = instance.api;
|
|
129
|
-
let currentBoundTarget = instance.boundapi;
|
|
130
|
-
|
|
131
|
-
for (let i = 0; i < pathParts.length - 1; i++) {
|
|
132
|
-
const part = pathParts[i];
|
|
133
|
-
const key = instance._toapiPathKey(part);
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
if (Object.prototype.hasOwnProperty.call(currentTarget, key)) {
|
|
139
|
-
const existing = currentTarget[key];
|
|
140
|
-
if (existing === null || (typeof existing !== "object" && typeof existing !== "function")) {
|
|
141
|
-
throw new Error(
|
|
142
|
-
`[slothlet] Cannot extend API path "${normalizedApiPath}" through segment "${part}": ` +
|
|
143
|
-
`existing value is type "${typeof existing}", cannot add properties.`
|
|
144
|
-
);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
} else {
|
|
149
|
-
currentTarget[key] = {};
|
|
150
|
-
}
|
|
151
|
-
if (Object.prototype.hasOwnProperty.call(currentBoundTarget, key)) {
|
|
152
|
-
const existingBound = currentBoundTarget[key];
|
|
153
|
-
if (existingBound === null || (typeof existingBound !== "object" && typeof existingBound !== "function")) {
|
|
154
|
-
throw new Error(
|
|
155
|
-
`[slothlet] Cannot extend bound API path "${normalizedApiPath}" through segment "${part}": ` +
|
|
156
|
-
`existing value is type "${typeof existingBound}", cannot add properties.`
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
} else {
|
|
161
|
-
currentBoundTarget[key] = {};
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
currentTarget = currentTarget[key];
|
|
166
|
-
currentBoundTarget = currentBoundTarget[key];
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
const finalKey = instance._toapiPathKey(pathParts[pathParts.length - 1]);
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if (typeof newModules === "function") {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
if (Object.prototype.hasOwnProperty.call(currentTarget, finalKey)) {
|
|
177
|
-
const existing = currentTarget[finalKey];
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
if (instance.config.allowApiOverwrite === false) {
|
|
181
|
-
console.warn(
|
|
182
|
-
`[slothlet] Skipping addApi: API path "${normalizedApiPath}" final key "${finalKey}" ` +
|
|
183
|
-
`already exists (type: "${typeof existing}"). Set allowApiOverwrite: true to allow overwrites.`
|
|
184
|
-
);
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if (existing !== null && typeof existing !== "function") {
|
|
190
|
-
console.warn(
|
|
191
|
-
`[slothlet] Overwriting existing non-function value at API path "${normalizedApiPath}" ` +
|
|
192
|
-
`final key "${finalKey}" with a function. Previous type: "${typeof existing}".`
|
|
193
|
-
);
|
|
194
|
-
} else if (typeof existing === "function") {
|
|
195
|
-
|
|
196
|
-
console.warn(
|
|
197
|
-
`[slothlet] Overwriting existing function at API path "${normalizedApiPath}" ` + `final key "${finalKey}" with a new function.`
|
|
198
|
-
);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
currentTarget[finalKey] = newModules;
|
|
202
|
-
currentBoundTarget[finalKey] = newModules;
|
|
203
|
-
} else if (typeof newModules === "object" && newModules !== null) {
|
|
204
|
-
|
|
205
|
-
if (Object.prototype.hasOwnProperty.call(currentTarget, finalKey)) {
|
|
206
|
-
const existing = currentTarget[finalKey];
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if (instance.config.allowApiOverwrite === false && existing !== undefined && existing !== null) {
|
|
210
|
-
|
|
211
|
-
const hasContent = typeof existing === "object" ? Object.keys(existing).length > 0 : true;
|
|
212
|
-
if (hasContent) {
|
|
213
|
-
console.warn(
|
|
214
|
-
`[slothlet] Skipping addApi merge: API path "${normalizedApiPath}" final key "${finalKey}" ` +
|
|
215
|
-
`already exists with content (type: "${typeof existing}"). Set allowApiOverwrite: true to allow merging.`
|
|
216
|
-
);
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
if (existing !== null && typeof existing !== "object" && typeof existing !== "function") {
|
|
222
|
-
throw new Error(
|
|
223
|
-
`[slothlet] Cannot merge API at "${normalizedApiPath}": ` +
|
|
224
|
-
`existing value at final key "${finalKey}" is type "${typeof existing}", cannot merge into primitives.`
|
|
225
|
-
);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
if (Object.prototype.hasOwnProperty.call(currentBoundTarget, finalKey)) {
|
|
229
|
-
const existingBound = currentBoundTarget[finalKey];
|
|
230
|
-
if (existingBound !== null && typeof existingBound !== "object" && typeof existingBound !== "function") {
|
|
231
|
-
throw new Error(
|
|
232
|
-
`[slothlet] Cannot merge bound API at "${normalizedApiPath}": ` +
|
|
233
|
-
`existing value at final key "${finalKey}" is type "${typeof existingBound}", cannot merge into primitives.`
|
|
234
|
-
);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
const targetValue = currentTarget[finalKey];
|
|
242
|
-
if (typeof targetValue === "function" && targetValue.__slothletPath) {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
const _ = targetValue.__trigger;
|
|
246
|
-
await targetValue();
|
|
247
|
-
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
const boundTargetValue = currentBoundTarget[finalKey];
|
|
251
|
-
if (typeof boundTargetValue === "function" && boundTargetValue.__slothletPath) {
|
|
252
|
-
|
|
253
|
-
const _ = boundTargetValue.__trigger;
|
|
254
|
-
await boundTargetValue();
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
if (!currentTarget[finalKey]) {
|
|
259
|
-
currentTarget[finalKey] = {};
|
|
260
|
-
}
|
|
261
|
-
if (!currentBoundTarget[finalKey]) {
|
|
262
|
-
currentBoundTarget[finalKey] = {};
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
Object.assign(currentTarget[finalKey], newModules);
|
|
271
|
-
Object.assign(currentBoundTarget[finalKey], newModules);
|
|
272
|
-
} else if (newModules === null || newModules === undefined) {
|
|
273
|
-
|
|
274
|
-
const receivedType = newModules === null ? "null" : "undefined";
|
|
275
|
-
console.warn(
|
|
276
|
-
`[slothlet] addApi: No modules loaded from folder at API path "${normalizedApiPath}". ` +
|
|
277
|
-
`Loaded modules resulted in ${receivedType}. Check that the folder contains valid module files.`
|
|
278
|
-
);
|
|
279
|
-
} else {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
currentTarget[finalKey] = newModules;
|
|
283
|
-
currentBoundTarget[finalKey] = newModules;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
instance.updateBindings(instance.context, instance.reference, instance.boundapi);
|
|
288
|
-
|
|
289
|
-
if (instance.config.debug) {
|
|
290
|
-
console.log(`[DEBUG] addApi: Successfully added modules at ${normalizedApiPath}`);
|
|
291
|
-
}
|
|
292
|
-
}
|