@cldmv/slothlet 3.3.0 → 3.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -8
- package/REFERENCE.md +23 -0
- package/dist/lib/builders/api-assignment.mjs +1 -589
- package/dist/lib/builders/api_builder.mjs +1 -1385
- package/dist/lib/builders/builder.mjs +1 -78
- package/dist/lib/builders/modes-processor.mjs +1 -1800
- package/dist/lib/errors.mjs +9 -211
- package/dist/lib/factories/component-base.mjs +1 -80
- package/dist/lib/factories/context.mjs +1 -22
- package/dist/lib/handlers/api-cache-manager.mjs +1 -200
- package/dist/lib/handlers/api-manager.mjs +1 -2536
- package/dist/lib/handlers/context-async.mjs +1 -172
- package/dist/lib/handlers/context-live.mjs +1 -173
- package/dist/lib/handlers/hook-manager.mjs +1 -667
- package/dist/lib/handlers/lifecycle-token.mjs +1 -28
- package/dist/lib/handlers/lifecycle.mjs +1 -115
- package/dist/lib/handlers/materialize-manager.mjs +1 -48
- package/dist/lib/handlers/metadata.mjs +1 -501
- package/dist/lib/handlers/ownership.mjs +1 -322
- package/dist/lib/handlers/permission-manager.mjs +1 -392
- package/dist/lib/handlers/unified-wrapper.mjs +1 -3110
- package/dist/lib/handlers/version-manager.mjs +1 -885
- package/dist/lib/helpers/class-instance-wrapper.mjs +1 -109
- package/dist/lib/helpers/config.mjs +1 -439
- package/dist/lib/helpers/eventemitter-context.mjs +1 -349
- package/dist/lib/helpers/hint-detector.mjs +1 -47
- package/dist/lib/helpers/modes-utils.mjs +1 -37
- package/dist/lib/helpers/pattern-matcher.mjs +1 -125
- package/dist/lib/helpers/resolve-from-caller.mjs +1 -169
- package/dist/lib/helpers/sanitize.mjs +1 -340
- package/dist/lib/helpers/utilities.mjs +1 -70
- package/dist/lib/i18n/translations.mjs +1 -126
- package/dist/lib/modes/eager.mjs +1 -59
- package/dist/lib/modes/lazy.mjs +1 -81
- package/dist/lib/processors/flatten.mjs +1 -437
- package/dist/lib/processors/loader.mjs +1 -339
- package/dist/lib/processors/type-generator.mjs +1 -275
- package/dist/lib/processors/typescript.mjs +1 -172
- package/dist/lib/runtime/runtime-asynclocalstorage.mjs +1 -113
- package/dist/lib/runtime/runtime-livebindings.mjs +1 -78
- package/dist/lib/runtime/runtime.mjs +1 -102
- package/dist/slothlet.mjs +1 -817
- package/package.json +34 -31
- package/types/dist/lib/builders/api-assignment.d.mts +3 -92
- package/types/dist/lib/builders/api-assignment.d.mts.map +1 -1
- package/types/dist/lib/builders/api_builder.d.mts +102 -91
- package/types/dist/lib/builders/api_builder.d.mts.map +1 -1
- package/types/dist/lib/builders/builder.d.mts +1 -55
- package/types/dist/lib/builders/builder.d.mts.map +1 -1
- package/types/dist/lib/builders/modes-processor.d.mts +3 -27
- package/types/dist/lib/builders/modes-processor.d.mts.map +1 -1
- package/types/dist/lib/errors.d.mts +19 -109
- package/types/dist/lib/errors.d.mts.map +1 -1
- package/types/dist/lib/factories/component-base.d.mts +7 -177
- package/types/dist/lib/factories/component-base.d.mts.map +1 -1
- package/types/dist/lib/factories/context.d.mts +4 -22
- package/types/dist/lib/factories/context.d.mts.map +1 -1
- package/types/dist/lib/handlers/api-cache-manager.d.mts +20 -203
- package/types/dist/lib/handlers/api-cache-manager.d.mts.map +1 -1
- package/types/dist/lib/handlers/api-manager.d.mts +33 -408
- package/types/dist/lib/handlers/api-manager.d.mts.map +1 -1
- package/types/dist/lib/handlers/context-async.d.mts +23 -61
- package/types/dist/lib/handlers/context-async.d.mts.map +1 -1
- package/types/dist/lib/handlers/context-live.d.mts +22 -59
- package/types/dist/lib/handlers/context-live.d.mts.map +1 -1
- package/types/dist/lib/handlers/hook-manager.d.mts +46 -185
- package/types/dist/lib/handlers/hook-manager.d.mts.map +1 -1
- package/types/dist/lib/handlers/lifecycle-token.d.mts +3 -48
- package/types/dist/lib/handlers/lifecycle-token.d.mts.map +1 -1
- package/types/dist/lib/handlers/lifecycle.d.mts +5 -82
- package/types/dist/lib/handlers/lifecycle.d.mts.map +1 -1
- package/types/dist/lib/handlers/materialize-manager.d.mts +8 -70
- package/types/dist/lib/handlers/materialize-manager.d.mts.map +1 -1
- package/types/dist/lib/handlers/metadata.d.mts +17 -221
- package/types/dist/lib/handlers/metadata.d.mts.map +1 -1
- package/types/dist/lib/handlers/ownership.d.mts +44 -160
- package/types/dist/lib/handlers/ownership.d.mts.map +1 -1
- package/types/dist/lib/handlers/permission-manager.d.mts +37 -141
- package/types/dist/lib/handlers/permission-manager.d.mts.map +1 -1
- package/types/dist/lib/handlers/unified-wrapper.d.mts +26 -239
- package/types/dist/lib/handlers/unified-wrapper.d.mts.map +1 -1
- package/types/dist/lib/handlers/version-manager.d.mts +28 -225
- package/types/dist/lib/handlers/version-manager.d.mts.map +1 -1
- package/types/dist/lib/helpers/class-instance-wrapper.d.mts +2 -52
- package/types/dist/lib/helpers/class-instance-wrapper.d.mts.map +1 -1
- package/types/dist/lib/helpers/config.d.mts +125 -139
- package/types/dist/lib/helpers/config.d.mts.map +1 -1
- package/types/dist/lib/helpers/eventemitter-context.d.mts +3 -29
- package/types/dist/lib/helpers/eventemitter-context.d.mts.map +1 -1
- package/types/dist/lib/helpers/hint-detector.d.mts +2 -15
- package/types/dist/lib/helpers/hint-detector.d.mts.map +1 -1
- package/types/dist/lib/helpers/modes-utils.d.mts +3 -30
- package/types/dist/lib/helpers/modes-utils.d.mts.map +1 -1
- package/types/dist/lib/helpers/pattern-matcher.d.mts +3 -43
- package/types/dist/lib/helpers/pattern-matcher.d.mts.map +1 -1
- package/types/dist/lib/helpers/resolve-from-caller.d.mts +3 -27
- package/types/dist/lib/helpers/resolve-from-caller.d.mts.map +1 -1
- package/types/dist/lib/helpers/sanitize.d.mts +4 -92
- package/types/dist/lib/helpers/sanitize.d.mts.map +1 -1
- package/types/dist/lib/helpers/utilities.d.mts +4 -52
- package/types/dist/lib/helpers/utilities.d.mts.map +1 -1
- package/types/dist/lib/i18n/translations.d.mts +4 -37
- package/types/dist/lib/i18n/translations.d.mts.map +1 -1
- package/types/dist/lib/modes/eager.d.mts +8 -30
- package/types/dist/lib/modes/eager.d.mts.map +1 -1
- package/types/dist/lib/modes/lazy.d.mts +10 -43
- package/types/dist/lib/modes/lazy.d.mts.map +1 -1
- package/types/dist/lib/processors/flatten.d.mts +56 -107
- package/types/dist/lib/processors/flatten.d.mts.map +1 -1
- package/types/dist/lib/processors/loader.d.mts +6 -41
- package/types/dist/lib/processors/loader.d.mts.map +1 -1
- package/types/dist/lib/processors/type-generator.d.mts +2 -16
- package/types/dist/lib/processors/type-generator.d.mts.map +1 -1
- package/types/dist/lib/processors/typescript.d.mts +6 -53
- package/types/dist/lib/processors/typescript.d.mts.map +1 -1
- package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts +3 -71
- package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts.map +1 -1
- package/types/dist/lib/runtime/runtime-livebindings.d.mts +2 -37
- package/types/dist/lib/runtime/runtime-livebindings.d.mts.map +1 -1
- package/types/dist/lib/runtime/runtime.d.mts +3 -39
- package/types/dist/lib/runtime/runtime.d.mts.map +1 -1
- package/types/dist/slothlet.d.mts +3 -249
- package/types/dist/slothlet.d.mts.map +1 -1
- package/types/index.d.mts +36 -16
- package/types/index.d.mts.map +1 -0
- package/AGENT-USAGE.md +0 -736
- package/docs/API-RULES.md +0 -712
package/README.md
CHANGED
|
@@ -55,18 +55,17 @@ Every feature has been hardened with a comprehensive test suite - over **5,300 t
|
|
|
55
55
|
|
|
56
56
|
## ✨ What's New
|
|
57
57
|
|
|
58
|
-
### Latest: v3.3.
|
|
58
|
+
### Latest: v3.3.2 (April 2026)
|
|
59
59
|
|
|
60
|
-
- **
|
|
61
|
-
-
|
|
62
|
-
- [View full v3.3.0 Changelog](./docs/changelog/v3/v3.3.0.md)
|
|
60
|
+
- **Workflow maintenance** — `release.yml` and `publish.yml` now match `ci.yml`: minimum Node.js raised to `20.19.0` and `lts_only_matrix` input added (default `true`) to keep matrix tests on LTS-only Node releases.
|
|
61
|
+
- [View full v3.3.2 Changelog](./docs/changelog/v3/v3.3.2.md)
|
|
63
62
|
|
|
64
63
|
### Recent Releases
|
|
65
64
|
|
|
65
|
+
- **v3.3.1** (April 2026) — `construct` trap for proxied classes; Node.js engine requirement raised to ≥ 20.19.0; type declaration fixes ([Changelog](./docs/changelog/v3/v3.3.1.md))
|
|
66
|
+
- **v3.3.0** (April 2026) — Permission System: path-based access control for inter-module calls with glob rules, audit events, and `api.slothlet.permissions.*` runtime API ([Changelog](./docs/changelog/v3/v3.3.0.md))
|
|
66
67
|
- **v3.2.3** (April 2026) — publish workflow fix ([Changelog](./docs/changelog/v3/v3.2.3.md))
|
|
67
68
|
- **v3.2.2** (April 2026) — missing `set` trap on version dispatchers; `util.inspect(api.auth)` now shows resolved versioned namespace ([Changelog](./docs/changelog/v3/v3.2.2.md))
|
|
68
|
-
- **v3.2.1** (April 2026) — version-dispatcher `defineProperty` trap fix; pre-commit validation cleanup ([Changelog](./docs/changelog/v3/v3.2.1.md))
|
|
69
|
-
- **v3.2.0** (April 2026) — API Path Versioning (`versionDispatcher`, `api.slothlet.versioning.*`, version metadata, dispatcher proxy); lazy-mode shutdown race fix ([Changelog](./docs/changelog/v3/v3.2.0.md))
|
|
70
69
|
|
|
71
70
|
|
|
72
71
|
📚 **For complete version history and detailed release notes, see [docs/changelog/](./docs/changelog/) folder.**
|
|
@@ -176,8 +175,7 @@ Automatic context preservation across all asynchronous boundaries:
|
|
|
176
175
|
|
|
177
176
|
### Requirements
|
|
178
177
|
|
|
179
|
-
- **Node.js
|
|
180
|
-
- Node.js 16.4–16.19 has a stack trace regression. For these versions, use slothlet 2.10.0: `npm install @cldmv/slothlet@2.10.0`
|
|
178
|
+
- **Node.js v20.19.0 or higher**
|
|
181
179
|
|
|
182
180
|
### Install
|
|
183
181
|
|
package/REFERENCE.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Slothlet Reference
|
|
2
|
+
|
|
3
|
+
Full documentation lives in the GitHub repository.
|
|
4
|
+
|
|
5
|
+
## Documentation
|
|
6
|
+
|
|
7
|
+
| Topic | Link |
|
|
8
|
+
|---|---|
|
|
9
|
+
| README / overview | [README.md](https://github.com/CLDMV/slothlet/blob/master/README.md) |
|
|
10
|
+
| All docs | [docs/](https://github.com/CLDMV/slothlet/tree/master/docs) |
|
|
11
|
+
| Configuration | [docs/CONFIGURATION.md](https://github.com/CLDMV/slothlet/blob/master/docs/CONFIGURATION.md) |
|
|
12
|
+
| API transformation rules | [docs/API-RULES.md](https://github.com/CLDMV/slothlet/blob/master/docs/API-RULES.md) |
|
|
13
|
+
| Hooks | [docs/HOOKS.md](https://github.com/CLDMV/slothlet/blob/master/docs/HOOKS.md) |
|
|
14
|
+
| Context propagation | [docs/CONTEXT-PROPAGATION.md](https://github.com/CLDMV/slothlet/blob/master/docs/CONTEXT-PROPAGATION.md) |
|
|
15
|
+
| Metadata | [docs/METADATA.md](https://github.com/CLDMV/slothlet/blob/master/docs/METADATA.md) |
|
|
16
|
+
| Permissions | [docs/PERMISSIONS.md](https://github.com/CLDMV/slothlet/blob/master/docs/PERMISSIONS.md) |
|
|
17
|
+
| API versioning | [docs/VERSIONING.md](https://github.com/CLDMV/slothlet/blob/master/docs/VERSIONING.md) |
|
|
18
|
+
| TypeScript | [docs/TYPESCRIPT.md](https://github.com/CLDMV/slothlet/blob/master/docs/TYPESCRIPT.md) |
|
|
19
|
+
| Lifecycle | [docs/LIFECYCLE.md](https://github.com/CLDMV/slothlet/blob/master/docs/LIFECYCLE.md) |
|
|
20
|
+
| Hot reload | [docs/RELOAD.md](https://github.com/CLDMV/slothlet/blob/master/docs/RELOAD.md) |
|
|
21
|
+
| Performance | [docs/PERFORMANCE.md](https://github.com/CLDMV/slothlet/blob/master/docs/PERFORMANCE.md) |
|
|
22
|
+
| Changelog | [docs/changelog/](https://github.com/CLDMV/slothlet/tree/master/docs/changelog) |
|
|
23
|
+
| Agent/AI usage guide | [AGENT-USAGE.md](https://github.com/CLDMV/slothlet/blob/master/AGENT-USAGE.md) |
|
|
@@ -14,592 +14,4 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
import { ComponentBase } from "@cldmv/slothlet/factories/component-base";
|
|
21
|
-
import { resolveWrapper } from "@cldmv/slothlet/handlers/unified-wrapper";
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
export class ApiAssignment extends ComponentBase {
|
|
25
|
-
static slothletProperty = "apiAssignment";
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
constructor(slothlet) {
|
|
29
|
-
super(slothlet);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
isWrapperProxy(value) {
|
|
34
|
-
return !!(value && resolveWrapper(value));
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
assignToApiPath(targetApi, key, value, options = {}) {
|
|
39
|
-
const valueIsWrapper = this.isWrapperProxy(value);
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const valueId = valueIsWrapper ? (resolveWrapper(value)?.____slothletInternal?.id ?? "no-id") : "not-wrapper";
|
|
43
|
-
this.slothlet.debug("api", {
|
|
44
|
-
key: "DEBUG_MODE_ASSIGN_TO_API",
|
|
45
|
-
propKey: key,
|
|
46
|
-
valueId,
|
|
47
|
-
typeOf: typeof value
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
const {
|
|
51
|
-
allowOverwrite = false,
|
|
52
|
-
mutateExisting = false,
|
|
53
|
-
useCollisionDetection = false,
|
|
54
|
-
config = null,
|
|
55
|
-
collisionContext = "initial",
|
|
56
|
-
syncWrapper = null,
|
|
57
|
-
collisionMode = "merge",
|
|
58
|
-
moduleID = null
|
|
59
|
-
} = options;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const existing = targetApi[key];
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (existing !== undefined && this.isWrapperProxy(existing) && this.isWrapperProxy(value)) {
|
|
66
|
-
if (mutateExisting && syncWrapper) {
|
|
67
|
-
syncWrapper(existing, value, config, collisionMode, moduleID);
|
|
68
|
-
return true;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
this.slothlet.debug("api", {
|
|
75
|
-
key: "DEBUG_MODE_COLLISION_CHECK",
|
|
76
|
-
propKey: key,
|
|
77
|
-
useCollisionDetection,
|
|
78
|
-
hasConfig: !!config,
|
|
79
|
-
hasExisting: existing !== undefined,
|
|
80
|
-
existingType: typeof existing
|
|
81
|
-
});
|
|
82
|
-
if (useCollisionDetection && config && existing !== undefined) {
|
|
83
|
-
this.slothlet.debug("api", {
|
|
84
|
-
key: "DEBUG_MODE_COLLISION_DETECT",
|
|
85
|
-
propKey: key,
|
|
86
|
-
context: collisionContext,
|
|
87
|
-
existingType: typeof existing,
|
|
88
|
-
valueType: typeof value
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
const collisionMode = config.collision?.[collisionContext] || "merge";
|
|
92
|
-
|
|
93
|
-
if (collisionMode === "error") {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const SlothletError = this.slothlet?.SlothletError || Error;
|
|
97
|
-
throw new SlothletError("COLLISION_ERROR", {
|
|
98
|
-
key: String(key),
|
|
99
|
-
collisionMode,
|
|
100
|
-
collisionContext
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (collisionMode === "skip") {
|
|
105
|
-
|
|
106
|
-
return false;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
let effectiveMode = collisionMode;
|
|
111
|
-
if (collisionMode === "warn") {
|
|
112
|
-
new this.slothlet.SlothletWarning("WARNING_COLLISION_FILE_FOLDER_MERGE", {
|
|
113
|
-
key: String(key)
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
effectiveMode = "merge";
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const existingIsWrapper = this.isWrapperProxy(existing);
|
|
122
|
-
const valueIsWrapper = this.isWrapperProxy(value);
|
|
123
|
-
|
|
124
|
-
this.slothlet.debug("api", {
|
|
125
|
-
key: "DEBUG_MODE_COLLISION_WRAPPER_DETECTION",
|
|
126
|
-
propKey: key,
|
|
127
|
-
existingIsWrapper,
|
|
128
|
-
valueIsWrapper,
|
|
129
|
-
hasExistingWrapper: resolveWrapper(existing) ? "yes" : "no",
|
|
130
|
-
hasValueWrapper: resolveWrapper(value) ? "yes" : "no"
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
if (existingIsWrapper && valueIsWrapper) {
|
|
134
|
-
const existingWrapper = resolveWrapper(existing);
|
|
135
|
-
const valueWrapper = resolveWrapper(value);
|
|
136
|
-
const existingIsLazyUnmaterialized =
|
|
137
|
-
existingWrapper.____slothletInternal.mode === "lazy" && !existingWrapper.____slothletInternal.state.materialized;
|
|
138
|
-
const valueIsLazyUnmaterialized =
|
|
139
|
-
valueWrapper.____slothletInternal.mode === "lazy" && !valueWrapper.____slothletInternal.state.materialized;
|
|
140
|
-
|
|
141
|
-
this.slothlet.debug("api", {
|
|
142
|
-
key: "DEBUG_MODE_COLLISION_LAZY_DETECTION",
|
|
143
|
-
propKey: key,
|
|
144
|
-
effectiveMode,
|
|
145
|
-
existingLazy: existingIsLazyUnmaterialized,
|
|
146
|
-
valueLazy: valueIsLazyUnmaterialized
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if (existingIsLazyUnmaterialized) {
|
|
153
|
-
this.slothlet.debug("api", {
|
|
154
|
-
key: "DEBUG_MODE_COLLISION_SET_MODE_EXISTING_WRAPPER",
|
|
155
|
-
effectiveMode,
|
|
156
|
-
apiPath: existingWrapper.____slothletInternal.apiPath
|
|
157
|
-
});
|
|
158
|
-
existingWrapper.____slothletInternal.state.collisionMode = effectiveMode;
|
|
159
|
-
this.slothlet.debug("api", {
|
|
160
|
-
key: "DEBUG_MODE_COLLISION_VERIFIED_EXISTING_WRAPPER_MODE",
|
|
161
|
-
collisionMode: existingWrapper.____slothletInternal.state.collisionMode
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
if (valueIsLazyUnmaterialized) {
|
|
165
|
-
this.slothlet.debug("api", {
|
|
166
|
-
key: "DEBUG_MODE_COLLISION_SET_MODE_VALUE_WRAPPER",
|
|
167
|
-
effectiveMode,
|
|
168
|
-
apiPath: valueWrapper.____slothletInternal.apiPath
|
|
169
|
-
});
|
|
170
|
-
valueWrapper.____slothletInternal.state.collisionMode = effectiveMode;
|
|
171
|
-
this.slothlet.debug("api", {
|
|
172
|
-
key: "DEBUG_MODE_COLLISION_VERIFIED_VALUE_WRAPPER_MODE",
|
|
173
|
-
collisionMode: valueWrapper.____slothletInternal.state.collisionMode
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (effectiveMode === "replace") {
|
|
179
|
-
this.slothlet.debug("api", {
|
|
180
|
-
key: "DEBUG_MODE_COLLISION_REPLACE_MATERIALIZE",
|
|
181
|
-
apiPath: valueWrapper.____slothletInternal.apiPath
|
|
182
|
-
});
|
|
183
|
-
valueWrapper._materialize();
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if (effectiveMode === "replace") {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
if (existingIsWrapper && valueIsWrapper) {
|
|
194
|
-
const existingWrapper = resolveWrapper(existing);
|
|
195
|
-
const valueWrapper = resolveWrapper(value);
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
const existingIsLazyUnmaterialized =
|
|
201
|
-
existingWrapper.____slothletInternal.mode === "lazy" && !existingWrapper.____slothletInternal.state.materialized;
|
|
202
|
-
const valueIsLazyUnmaterialized =
|
|
203
|
-
valueWrapper.____slothletInternal.mode === "lazy" && !valueWrapper.____slothletInternal.state.materialized;
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
if (valueIsLazyUnmaterialized && !existingIsLazyUnmaterialized) {
|
|
207
|
-
this.slothlet.debug("api", {
|
|
208
|
-
key: "DEBUG_MODE_COLLISION_REPLACE_NO_COPY"
|
|
209
|
-
});
|
|
210
|
-
this.slothlet.debug("api", {
|
|
211
|
-
key: "DEBUG_MODE_COLLISION_REPLACE_BEFORE",
|
|
212
|
-
propKey: key,
|
|
213
|
-
currentWrapperId: resolveWrapper(existing)?.____slothletInternal.id
|
|
214
|
-
});
|
|
215
|
-
this.slothlet.debug("api", {
|
|
216
|
-
key: "DEBUG_MODE_COLLISION_ASSIGN_REPLACING_WITH_LAZY",
|
|
217
|
-
propKey: key,
|
|
218
|
-
collisionMode: valueWrapper.____slothletInternal.state.collisionMode
|
|
219
|
-
});
|
|
220
|
-
targetApi[key] = value;
|
|
221
|
-
this.slothlet.debug("api", {
|
|
222
|
-
key: "DEBUG_MODE_COLLISION_REPLACE_AFTER",
|
|
223
|
-
propKey: key,
|
|
224
|
-
newWrapperId: resolveWrapper(targetApi[key])?.____slothletInternal.id
|
|
225
|
-
});
|
|
226
|
-
this.slothlet.debug("api", {
|
|
227
|
-
key: "DEBUG_MODE_COLLISION_REPLACE_VERIFY",
|
|
228
|
-
expectedId: valueWrapper.____slothletInternal.id,
|
|
229
|
-
actualId: resolveWrapper(targetApi[key])?.____slothletInternal.id
|
|
230
|
-
});
|
|
231
|
-
return true;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
targetApi[key] = value;
|
|
237
|
-
return true;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
if (effectiveMode === "merge" || effectiveMode === "merge-replace") {
|
|
244
|
-
const isMergeReplace = effectiveMode === "merge-replace";
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
if (existingIsWrapper && valueIsWrapper) {
|
|
248
|
-
|
|
249
|
-
const existingWrapper = resolveWrapper(existing);
|
|
250
|
-
const valueWrapper = resolveWrapper(value);
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
const existingIsLazyUnmaterialized =
|
|
255
|
-
existingWrapper.____slothletInternal.mode === "lazy" && !existingWrapper.____slothletInternal.state.materialized;
|
|
256
|
-
const valueIsLazyUnmaterialized =
|
|
257
|
-
valueWrapper.____slothletInternal.mode === "lazy" && !valueWrapper.____slothletInternal.state.materialized;
|
|
258
|
-
|
|
259
|
-
if (existingIsLazyUnmaterialized && !valueIsLazyUnmaterialized) {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
const valueMetadata = this.slothlet.handlers?.metadata?.getMetadata(value);
|
|
265
|
-
const valueFilePath = valueMetadata?.filePath;
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
if (!existingWrapper.____slothletInternal.childFilePathsPreMaterialize) {
|
|
273
|
-
existingWrapper.____slothletInternal.childFilePathsPreMaterialize = {};
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
const valueChildKeys = Object.keys(valueWrapper).filter((k) => !k.startsWith("_") && !k.startsWith("__"));
|
|
277
|
-
for (const key of valueChildKeys) {
|
|
278
|
-
|
|
279
|
-
Object.defineProperty(existingWrapper, key, {
|
|
280
|
-
configurable: true
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
if (valueFilePath) {
|
|
284
|
-
existingWrapper.____slothletInternal.childFilePathsPreMaterialize[key] = valueFilePath;
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
return true;
|
|
289
|
-
} else if (valueIsLazyUnmaterialized && !existingIsLazyUnmaterialized) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
if (!isMergeReplace) {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
const existingMetadata = this.slothlet.handlers?.metadata?.getMetadata(existing);
|
|
305
|
-
const existingFilePath = existingMetadata?.filePath;
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
if (!valueWrapper.____slothletInternal.childFilePathsPreMaterialize) {
|
|
309
|
-
valueWrapper.____slothletInternal.childFilePathsPreMaterialize = {};
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
const existingChildKeys = Object.keys(existingWrapper).filter((k) => !k.startsWith("_") && !k.startsWith("__"));
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
this.slothlet.debug("api", {
|
|
317
|
-
key: "DEBUG_MODE_COLLISION_COPY_CHILD_KEYS",
|
|
318
|
-
existingChildKeys: existingChildKeys.join(","),
|
|
319
|
-
fromApiPath: existingWrapper.____slothletInternal.apiPath,
|
|
320
|
-
toApiPath: valueWrapper.____slothletInternal.apiPath,
|
|
321
|
-
valueWrapperId: valueWrapper.____slothletInternal.id || "no-id"
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
if (!valueWrapper.____slothletInternal.collisionMergedKeys) {
|
|
326
|
-
valueWrapper.____slothletInternal.collisionMergedKeys = new Set();
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
for (const key of existingChildKeys) {
|
|
330
|
-
const child = existingWrapper[key];
|
|
331
|
-
this.slothlet.debug("api", {
|
|
332
|
-
key: "DEBUG_MODE_COLLISION_COPY_INDIVIDUAL_KEY",
|
|
333
|
-
propKey: key,
|
|
334
|
-
childName: child?.name,
|
|
335
|
-
typeOf: typeof child,
|
|
336
|
-
valueWrapperId: valueWrapper.____slothletInternal.id || "no-id"
|
|
337
|
-
});
|
|
338
|
-
Object.defineProperty(valueWrapper, key, {
|
|
339
|
-
value: child,
|
|
340
|
-
writable: false,
|
|
341
|
-
enumerable: true,
|
|
342
|
-
configurable: true
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
valueWrapper.____slothletInternal.collisionMergedKeys.add(key);
|
|
346
|
-
|
|
347
|
-
if (existingFilePath) {
|
|
348
|
-
valueWrapper.____slothletInternal.childFilePathsPreMaterialize[key] = existingFilePath;
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
this.slothlet.debug("api", {
|
|
357
|
-
key: "DEBUG_MODE_COLLISION_TRIGGER_EARLY_MAT",
|
|
358
|
-
apiPath: valueWrapper.____slothletInternal.apiPath
|
|
359
|
-
});
|
|
360
|
-
valueWrapper.____slothletInternal.needsImmediateChildAdoption = true;
|
|
361
|
-
if (
|
|
362
|
-
valueWrapper.____slothletInternal.materializeFunc &&
|
|
363
|
-
!valueWrapper.____slothletInternal.state?.materialized &&
|
|
364
|
-
!valueWrapper.____slothletInternal.state?.inFlight
|
|
365
|
-
) {
|
|
366
|
-
valueWrapper._materialize().catch((err) => {
|
|
367
|
-
new this.slothlet.SlothletWarning(
|
|
368
|
-
"WARNING_COLLISION_TRIGGER_MATERIALIZE_ERROR",
|
|
369
|
-
{
|
|
370
|
-
apiPath: valueWrapper.____slothletInternal.apiPath
|
|
371
|
-
},
|
|
372
|
-
err
|
|
373
|
-
);
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
} else {
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
valueWrapper._mergeAfterMaterialize = {
|
|
383
|
-
existingWrapper,
|
|
384
|
-
isMergeReplace: true
|
|
385
|
-
};
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
this.slothlet.debug("api", {
|
|
390
|
-
key: "DEBUG_MODE_COLLISION_ASSIGN_REPLACING_WITH_LAZY",
|
|
391
|
-
propKey: key,
|
|
392
|
-
collisionMode: valueWrapper.____slothletInternal.state.collisionMode
|
|
393
|
-
});
|
|
394
|
-
targetApi[key] = value;
|
|
395
|
-
return true;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
const existingChildCount = Object.keys(existingWrapper).filter((k) => !k.startsWith("_") && !k.startsWith("__")).length;
|
|
401
|
-
const valueChildCount = Object.keys(valueWrapper).filter((k) => !k.startsWith("_") && !k.startsWith("__")).length;
|
|
402
|
-
if (existingWrapper.____slothletInternal.impl && existingChildCount === 0) {
|
|
403
|
-
existingWrapper.___adoptImplChildren();
|
|
404
|
-
}
|
|
405
|
-
if (valueWrapper.____slothletInternal.impl && valueChildCount === 0) {
|
|
406
|
-
valueWrapper.___adoptImplChildren();
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
const valueChildKeys2 = Object.keys(valueWrapper).filter((k) => !k.startsWith("_") && !k.startsWith("__"));
|
|
416
|
-
for (const key of valueChildKeys2) {
|
|
417
|
-
const child = valueWrapper[key];
|
|
418
|
-
const isInternal = typeof key === "string" && (key.startsWith("_") || key.startsWith("__"));
|
|
419
|
-
|
|
420
|
-
const keyExists = !isInternal && Object.prototype.hasOwnProperty.call(existingWrapper, key);
|
|
421
|
-
|
|
422
|
-
if (!keyExists) {
|
|
423
|
-
Object.defineProperty(existingWrapper, key, {
|
|
424
|
-
value: child,
|
|
425
|
-
writable: false,
|
|
426
|
-
enumerable: true,
|
|
427
|
-
configurable: true
|
|
428
|
-
});
|
|
429
|
-
} else if (isMergeReplace) {
|
|
430
|
-
const descriptor = Object.getOwnPropertyDescriptor(existingWrapper, key);
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
if (descriptor?.configurable) {
|
|
436
|
-
delete existingWrapper[key];
|
|
437
|
-
}
|
|
438
|
-
Object.defineProperty(existingWrapper, key, {
|
|
439
|
-
value: child,
|
|
440
|
-
writable: false,
|
|
441
|
-
enumerable: true,
|
|
442
|
-
configurable: true
|
|
443
|
-
});
|
|
444
|
-
} else {
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
const existingChild = existingWrapper[key];
|
|
449
|
-
const existingChildWrapper = resolveWrapper(existingChild);
|
|
450
|
-
const newChildWrapper = resolveWrapper(child);
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
if (existingChildWrapper && newChildWrapper) {
|
|
454
|
-
|
|
455
|
-
const newChildChildCount = Object.keys(newChildWrapper).filter((k) => !k.startsWith("_") && !k.startsWith("__")).length;
|
|
456
|
-
if (newChildWrapper.____slothletInternal.impl && newChildChildCount === 0) {
|
|
457
|
-
newChildWrapper.___adoptImplChildren();
|
|
458
|
-
}
|
|
459
|
-
const newChildKeys = Object.keys(newChildWrapper).filter((k) => !k.startsWith("_") && !k.startsWith("__"));
|
|
460
|
-
const ____existingChildKeys = Object.keys(existingChildWrapper).filter((k) => !k.startsWith("_") && !k.startsWith("__"));
|
|
461
|
-
for (const childKey of newChildKeys) {
|
|
462
|
-
const childKeyExists = Object.prototype.hasOwnProperty.call(existingChildWrapper, childKey);
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
if (!childKeyExists) {
|
|
466
|
-
Object.defineProperty(existingChildWrapper, childKey, {
|
|
467
|
-
value: newChildWrapper[childKey],
|
|
468
|
-
writable: false,
|
|
469
|
-
enumerable: true,
|
|
470
|
-
configurable: true
|
|
471
|
-
});
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
if (
|
|
479
|
-
valueWrapper.____slothletInternal.mode === "lazy" &&
|
|
480
|
-
!valueWrapper.____slothletInternal.state.materialized &&
|
|
481
|
-
valueWrapper.____slothletInternal.materializeFunc
|
|
482
|
-
) {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
return false;
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
return true;
|
|
489
|
-
} else if (existingIsWrapper && !valueIsWrapper) {
|
|
490
|
-
|
|
491
|
-
const existingWrapper = resolveWrapper(existing);
|
|
492
|
-
const existingImpl = existingWrapper.__impl;
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
const mergedImpl = { ...(existingImpl || {}), ...value };
|
|
496
|
-
existingWrapper.___setImpl(mergedImpl);
|
|
497
|
-
return true;
|
|
498
|
-
} else if (!existingIsWrapper && valueIsWrapper) {
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
} else {
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
if (typeof existing === "object" && existing !== null && typeof value === "object" && value !== null) {
|
|
506
|
-
Object.assign(existing, value);
|
|
507
|
-
return true;
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
if (existing !== undefined && !allowOverwrite && !mutateExisting && !useCollisionDetection) {
|
|
518
|
-
return false;
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
targetApi[key] = value;
|
|
523
|
-
return true;
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
async mergeApiObjects(targetApi, sourceApi, options = {}) {
|
|
528
|
-
const config = options.config;
|
|
529
|
-
if (config?.debug?.api) {
|
|
530
|
-
this.slothlet.debug("api", {
|
|
531
|
-
key: "DEBUG_MODE_MERGE_API_OBJECTS_ENTRY",
|
|
532
|
-
targetApiType: typeof targetApi,
|
|
533
|
-
sourceApiType: typeof sourceApi
|
|
534
|
-
});
|
|
535
|
-
this.slothlet.debug("api", {
|
|
536
|
-
key: "DEBUG_MODE_MERGE_API_OBJECTS_SOURCE_KEYS",
|
|
537
|
-
sourceApiKeys: sourceApi ? Object.keys(sourceApi) : []
|
|
538
|
-
});
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
if (!sourceApi || (typeof sourceApi !== "object" && typeof sourceApi !== "function")) {
|
|
543
|
-
if (config?.debug?.api) {
|
|
544
|
-
this.slothlet.debug("api", {
|
|
545
|
-
key: "DEBUG_MODE_MERGE_API_OBJECTS_EXIT_INVALID_SOURCE"
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
|
-
return;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
const { removeMissing = false, moduleID = null, ...assignOptions } = options;
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
const sourceKeys = new Set(Object.keys(sourceApi));
|
|
555
|
-
for (const key of sourceKeys) {
|
|
556
|
-
const sourceValue = sourceApi[key];
|
|
557
|
-
const targetValue = targetApi[key];
|
|
558
|
-
|
|
559
|
-
if (config?.debug?.api) {
|
|
560
|
-
this.slothlet.debug("api", {
|
|
561
|
-
key: "DEBUG_MODE_MERGE_API_OBJECTS_PROCESSING_KEY",
|
|
562
|
-
propKey: key,
|
|
563
|
-
targetValueType: typeof targetValue,
|
|
564
|
-
sourceValueType: typeof sourceValue
|
|
565
|
-
});
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
if (
|
|
570
|
-
targetValue &&
|
|
571
|
-
typeof targetValue === "object" &&
|
|
572
|
-
!this.isWrapperProxy(targetValue) &&
|
|
573
|
-
sourceValue &&
|
|
574
|
-
typeof sourceValue === "object" &&
|
|
575
|
-
!this.isWrapperProxy(sourceValue)
|
|
576
|
-
) {
|
|
577
|
-
if (config?.debug?.api) {
|
|
578
|
-
this.slothlet.debug("api", {
|
|
579
|
-
key: "DEBUG_MODE_MERGE_API_OBJECTS_RECURSING",
|
|
580
|
-
propKey: key
|
|
581
|
-
});
|
|
582
|
-
}
|
|
583
|
-
await this.mergeApiObjects(targetValue, sourceValue, options);
|
|
584
|
-
} else {
|
|
585
|
-
|
|
586
|
-
if (config?.debug?.api) {
|
|
587
|
-
this.slothlet.debug("api", {
|
|
588
|
-
key: "DEBUG_MODE_MERGE_API_OBJECTS_CALLING_ASSIGN",
|
|
589
|
-
propKey: key
|
|
590
|
-
});
|
|
591
|
-
}
|
|
592
|
-
this.assignToApiPath(targetApi, key, sourceValue, { ...assignOptions, moduleID });
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
if (removeMissing) {
|
|
598
|
-
for (const key of Object.keys(targetApi)) {
|
|
599
|
-
if (!sourceKeys.has(key)) {
|
|
600
|
-
delete targetApi[key];
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
}
|
|
17
|
+
import{ComponentBase}from"@cldmv/slothlet/factories/component-base";import{resolveWrapper}from"@cldmv/slothlet/handlers/unified-wrapper";class ApiAssignment extends ComponentBase{static slothletProperty="apiAssignment";constructor(slothlet){super(slothlet)}isWrapperProxy(value){return!!(value&&resolveWrapper(value))}assignToApiPath(targetApi,key,value,options={}){const valueIsWrapper=this.isWrapperProxy(value);const valueId=valueIsWrapper?resolveWrapper(value)?.____slothletInternal?.id??"no-id":"not-wrapper";this.slothlet.debug("api",{key:"DEBUG_MODE_ASSIGN_TO_API",propKey:key,valueId,typeOf:typeof value});const{allowOverwrite=false,mutateExisting=false,useCollisionDetection=false,config=null,collisionContext="initial",syncWrapper=null,collisionMode="merge",moduleID=null}=options;const existing=targetApi[key];if(existing!==void 0&&this.isWrapperProxy(existing)&&this.isWrapperProxy(value)){if(mutateExisting&&syncWrapper){syncWrapper(existing,value,config,collisionMode,moduleID);return true}}this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_CHECK",propKey:key,useCollisionDetection,hasConfig:!!config,hasExisting:existing!==void 0,existingType:typeof existing});if(useCollisionDetection&&config&&existing!==void 0){this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_DETECT",propKey:key,context:collisionContext,existingType:typeof existing,valueType:typeof value});const collisionMode2=config.collision?.[collisionContext]||"merge";if(collisionMode2==="error"){const SlothletError=this.slothlet?.SlothletError||Error;throw new SlothletError("COLLISION_ERROR",{key:String(key),collisionMode:collisionMode2,collisionContext})}if(collisionMode2==="skip"){return false}let effectiveMode=collisionMode2;if(collisionMode2==="warn"){new this.slothlet.SlothletWarning("WARNING_COLLISION_FILE_FOLDER_MERGE",{key:String(key)});effectiveMode="merge"}const existingIsWrapper=this.isWrapperProxy(existing);const valueIsWrapper2=this.isWrapperProxy(value);this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_WRAPPER_DETECTION",propKey:key,existingIsWrapper,valueIsWrapper:valueIsWrapper2,hasExistingWrapper:resolveWrapper(existing)?"yes":"no",hasValueWrapper:resolveWrapper(value)?"yes":"no"});if(existingIsWrapper&&valueIsWrapper2){const existingWrapper=resolveWrapper(existing);const valueWrapper=resolveWrapper(value);const existingIsLazyUnmaterialized=existingWrapper.____slothletInternal.mode==="lazy"&&!existingWrapper.____slothletInternal.state.materialized;const valueIsLazyUnmaterialized=valueWrapper.____slothletInternal.mode==="lazy"&&!valueWrapper.____slothletInternal.state.materialized;this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_LAZY_DETECTION",propKey:key,effectiveMode,existingLazy:existingIsLazyUnmaterialized,valueLazy:valueIsLazyUnmaterialized});if(existingIsLazyUnmaterialized){this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_SET_MODE_EXISTING_WRAPPER",effectiveMode,apiPath:existingWrapper.____slothletInternal.apiPath});existingWrapper.____slothletInternal.state.collisionMode=effectiveMode;this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_VERIFIED_EXISTING_WRAPPER_MODE",collisionMode:existingWrapper.____slothletInternal.state.collisionMode})}if(valueIsLazyUnmaterialized){this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_SET_MODE_VALUE_WRAPPER",effectiveMode,apiPath:valueWrapper.____slothletInternal.apiPath});valueWrapper.____slothletInternal.state.collisionMode=effectiveMode;this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_VERIFIED_VALUE_WRAPPER_MODE",collisionMode:valueWrapper.____slothletInternal.state.collisionMode});if(effectiveMode==="replace"){this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_REPLACE_MATERIALIZE",apiPath:valueWrapper.____slothletInternal.apiPath});valueWrapper._materialize()}}}if(effectiveMode==="replace"){if(existingIsWrapper&&valueIsWrapper2){const existingWrapper=resolveWrapper(existing);const valueWrapper=resolveWrapper(value);const existingIsLazyUnmaterialized=existingWrapper.____slothletInternal.mode==="lazy"&&!existingWrapper.____slothletInternal.state.materialized;const valueIsLazyUnmaterialized=valueWrapper.____slothletInternal.mode==="lazy"&&!valueWrapper.____slothletInternal.state.materialized;if(valueIsLazyUnmaterialized&&!existingIsLazyUnmaterialized){this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_REPLACE_NO_COPY"});this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_REPLACE_BEFORE",propKey:key,currentWrapperId:resolveWrapper(existing)?.____slothletInternal.id});this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_ASSIGN_REPLACING_WITH_LAZY",propKey:key,collisionMode:valueWrapper.____slothletInternal.state.collisionMode});targetApi[key]=value;this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_REPLACE_AFTER",propKey:key,newWrapperId:resolveWrapper(targetApi[key])?.____slothletInternal.id});this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_REPLACE_VERIFY",expectedId:valueWrapper.____slothletInternal.id,actualId:resolveWrapper(targetApi[key])?.____slothletInternal.id});return true}}targetApi[key]=value;return true}if(effectiveMode==="merge"||effectiveMode==="merge-replace"){const isMergeReplace=effectiveMode==="merge-replace";if(existingIsWrapper&&valueIsWrapper2){const existingWrapper=resolveWrapper(existing);const valueWrapper=resolveWrapper(value);const existingIsLazyUnmaterialized=existingWrapper.____slothletInternal.mode==="lazy"&&!existingWrapper.____slothletInternal.state.materialized;const valueIsLazyUnmaterialized=valueWrapper.____slothletInternal.mode==="lazy"&&!valueWrapper.____slothletInternal.state.materialized;if(existingIsLazyUnmaterialized&&!valueIsLazyUnmaterialized){const valueMetadata=this.slothlet.handlers?.metadata?.getMetadata(value);const valueFilePath=valueMetadata?.filePath;if(!existingWrapper.____slothletInternal.childFilePathsPreMaterialize){existingWrapper.____slothletInternal.childFilePathsPreMaterialize={}}const valueChildKeys=Object.keys(valueWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__"));for(const key2 of valueChildKeys){Object.defineProperty(existingWrapper,key2,{configurable:true});if(valueFilePath){existingWrapper.____slothletInternal.childFilePathsPreMaterialize[key2]=valueFilePath}}return true}else if(valueIsLazyUnmaterialized&&!existingIsLazyUnmaterialized){if(!isMergeReplace){const existingMetadata=this.slothlet.handlers?.metadata?.getMetadata(existing);const existingFilePath=existingMetadata?.filePath;if(!valueWrapper.____slothletInternal.childFilePathsPreMaterialize){valueWrapper.____slothletInternal.childFilePathsPreMaterialize={}}const existingChildKeys=Object.keys(existingWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__"));this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_COPY_CHILD_KEYS",existingChildKeys:existingChildKeys.join(","),fromApiPath:existingWrapper.____slothletInternal.apiPath,toApiPath:valueWrapper.____slothletInternal.apiPath,valueWrapperId:valueWrapper.____slothletInternal.id||"no-id"});if(!valueWrapper.____slothletInternal.collisionMergedKeys){valueWrapper.____slothletInternal.collisionMergedKeys=new Set}for(const key2 of existingChildKeys){const child=existingWrapper[key2];this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_COPY_INDIVIDUAL_KEY",propKey:key2,childName:child?.name,typeOf:typeof child,valueWrapperId:valueWrapper.____slothletInternal.id||"no-id"});Object.defineProperty(valueWrapper,key2,{value:child,writable:false,enumerable:true,configurable:true});valueWrapper.____slothletInternal.collisionMergedKeys.add(key2);if(existingFilePath){valueWrapper.____slothletInternal.childFilePathsPreMaterialize[key2]=existingFilePath}}this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_TRIGGER_EARLY_MAT",apiPath:valueWrapper.____slothletInternal.apiPath});valueWrapper.____slothletInternal.needsImmediateChildAdoption=true;if(valueWrapper.____slothletInternal.materializeFunc&&!valueWrapper.____slothletInternal.state?.materialized&&!valueWrapper.____slothletInternal.state?.inFlight){valueWrapper._materialize().catch(err=>{new this.slothlet.SlothletWarning("WARNING_COLLISION_TRIGGER_MATERIALIZE_ERROR",{apiPath:valueWrapper.____slothletInternal.apiPath},err)})}}else{valueWrapper._mergeAfterMaterialize={existingWrapper,isMergeReplace:true}}this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_ASSIGN_REPLACING_WITH_LAZY",propKey:key,collisionMode:valueWrapper.____slothletInternal.state.collisionMode});targetApi[key]=value;return true}const existingChildCount=Object.keys(existingWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__")).length;const valueChildCount=Object.keys(valueWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__")).length;if(existingWrapper.____slothletInternal.impl&&existingChildCount===0){existingWrapper.___adoptImplChildren()}if(valueWrapper.____slothletInternal.impl&&valueChildCount===0){valueWrapper.___adoptImplChildren()}const valueChildKeys2=Object.keys(valueWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__"));for(const key2 of valueChildKeys2){const child=valueWrapper[key2];const isInternal=typeof key2==="string"&&(key2.startsWith("_")||key2.startsWith("__"));const keyExists=!isInternal&&Object.prototype.hasOwnProperty.call(existingWrapper,key2);if(!keyExists){Object.defineProperty(existingWrapper,key2,{value:child,writable:false,enumerable:true,configurable:true})}else if(isMergeReplace){const descriptor=Object.getOwnPropertyDescriptor(existingWrapper,key2);if(descriptor?.configurable){delete existingWrapper[key2]}Object.defineProperty(existingWrapper,key2,{value:child,writable:false,enumerable:true,configurable:true})}else{const existingChild=existingWrapper[key2];const existingChildWrapper=resolveWrapper(existingChild);const newChildWrapper=resolveWrapper(child);if(existingChildWrapper&&newChildWrapper){const newChildChildCount=Object.keys(newChildWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__")).length;if(newChildWrapper.____slothletInternal.impl&&newChildChildCount===0){newChildWrapper.___adoptImplChildren()}const newChildKeys=Object.keys(newChildWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__"));const ____existingChildKeys=Object.keys(existingChildWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__"));for(const childKey of newChildKeys){const childKeyExists=Object.prototype.hasOwnProperty.call(existingChildWrapper,childKey);if(!childKeyExists){Object.defineProperty(existingChildWrapper,childKey,{value:newChildWrapper[childKey],writable:false,enumerable:true,configurable:true})}}}}}if(valueWrapper.____slothletInternal.mode==="lazy"&&!valueWrapper.____slothletInternal.state.materialized&&valueWrapper.____slothletInternal.materializeFunc){return false}return true}else if(existingIsWrapper&&!valueIsWrapper2){const existingWrapper=resolveWrapper(existing);const existingImpl=existingWrapper.__impl;const mergedImpl={...existingImpl||{},...value};existingWrapper.___setImpl(mergedImpl);return true}else if(!existingIsWrapper&&valueIsWrapper2){}else{if(typeof existing==="object"&&existing!==null&&typeof value==="object"&&value!==null){Object.assign(existing,value);return true}}}}if(existing!==void 0&&!allowOverwrite&&!mutateExisting&&!useCollisionDetection){return false}targetApi[key]=value;return true}async mergeApiObjects(targetApi,sourceApi,options={}){const config=options.config;if(config?.debug?.api){this.slothlet.debug("api",{key:"DEBUG_MODE_MERGE_API_OBJECTS_ENTRY",targetApiType:typeof targetApi,sourceApiType:typeof sourceApi});this.slothlet.debug("api",{key:"DEBUG_MODE_MERGE_API_OBJECTS_SOURCE_KEYS",sourceApiKeys:sourceApi?Object.keys(sourceApi):[]})}if(!sourceApi||typeof sourceApi!=="object"&&typeof sourceApi!=="function"){if(config?.debug?.api){this.slothlet.debug("api",{key:"DEBUG_MODE_MERGE_API_OBJECTS_EXIT_INVALID_SOURCE"})}return}const{removeMissing=false,moduleID=null,...assignOptions}=options;const sourceKeys=new Set(Object.keys(sourceApi));for(const key of sourceKeys){const sourceValue=sourceApi[key];const targetValue=targetApi[key];if(config?.debug?.api){this.slothlet.debug("api",{key:"DEBUG_MODE_MERGE_API_OBJECTS_PROCESSING_KEY",propKey:key,targetValueType:typeof targetValue,sourceValueType:typeof sourceValue})}if(targetValue&&typeof targetValue==="object"&&!this.isWrapperProxy(targetValue)&&sourceValue&&typeof sourceValue==="object"&&!this.isWrapperProxy(sourceValue)){if(config?.debug?.api){this.slothlet.debug("api",{key:"DEBUG_MODE_MERGE_API_OBJECTS_RECURSING",propKey:key})}await this.mergeApiObjects(targetValue,sourceValue,options)}else{if(config?.debug?.api){this.slothlet.debug("api",{key:"DEBUG_MODE_MERGE_API_OBJECTS_CALLING_ASSIGN",propKey:key})}this.assignToApiPath(targetApi,key,sourceValue,{...assignOptions,moduleID})}}if(removeMissing){for(const key of Object.keys(targetApi)){if(!sourceKeys.has(key)){delete targetApi[key]}}}}}export{ApiAssignment};
|