@cldmv/slothlet 3.3.0 → 3.4.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.
Files changed (139) hide show
  1. package/README.md +9 -10
  2. package/REFERENCE.md +23 -0
  3. package/dist/lib/builders/api-assignment.mjs +1 -589
  4. package/dist/lib/builders/api_builder.mjs +1 -1385
  5. package/dist/lib/builders/builder.mjs +1 -78
  6. package/dist/lib/builders/modes-processor.mjs +1 -1800
  7. package/dist/lib/errors.mjs +9 -211
  8. package/dist/lib/factories/component-base.mjs +1 -80
  9. package/dist/lib/factories/context.mjs +1 -22
  10. package/dist/lib/handlers/api-cache-manager.mjs +1 -200
  11. package/dist/lib/handlers/api-manager.mjs +1 -2536
  12. package/dist/lib/handlers/context-async.mjs +1 -172
  13. package/dist/lib/handlers/context-live.mjs +1 -173
  14. package/dist/lib/handlers/hook-manager.mjs +1 -667
  15. package/dist/lib/handlers/lifecycle-token.mjs +1 -28
  16. package/dist/lib/handlers/lifecycle.mjs +1 -115
  17. package/dist/lib/handlers/materialize-manager.mjs +1 -48
  18. package/dist/lib/handlers/metadata.mjs +1 -501
  19. package/dist/lib/handlers/ownership.mjs +1 -322
  20. package/dist/lib/handlers/permission-manager.mjs +1 -392
  21. package/dist/lib/handlers/unified-wrapper.mjs +1 -3110
  22. package/dist/lib/handlers/version-manager.mjs +1 -885
  23. package/dist/lib/helpers/class-instance-wrapper.mjs +1 -109
  24. package/dist/lib/helpers/config.mjs +1 -439
  25. package/dist/lib/helpers/eventemitter-context.mjs +1 -349
  26. package/dist/lib/helpers/hint-detector.mjs +1 -47
  27. package/dist/lib/helpers/modes-utils.mjs +1 -37
  28. package/dist/lib/helpers/pattern-matcher.mjs +1 -125
  29. package/dist/lib/helpers/resolve-from-caller.mjs +1 -169
  30. package/dist/lib/helpers/sanitize.mjs +1 -340
  31. package/dist/lib/helpers/utilities.mjs +1 -70
  32. package/dist/lib/i18n/languages/de-de.json +1 -0
  33. package/dist/lib/i18n/languages/en-gb.json +1 -0
  34. package/dist/lib/i18n/languages/en-us.json +1 -0
  35. package/dist/lib/i18n/languages/es-es.json +412 -0
  36. package/dist/lib/i18n/languages/es-mx.json +1 -0
  37. package/dist/lib/i18n/languages/fr-fr.json +1 -0
  38. package/dist/lib/i18n/languages/hi-in.json +2 -1
  39. package/dist/lib/i18n/languages/ja-jp.json +1 -0
  40. package/dist/lib/i18n/languages/ko-kr.json +1 -0
  41. package/dist/lib/i18n/languages/pt-br.json +21 -20
  42. package/dist/lib/i18n/languages/ru-ru.json +2 -1
  43. package/dist/lib/i18n/languages/zh-cn.json +6 -5
  44. package/dist/lib/i18n/translations.mjs +1 -126
  45. package/dist/lib/modes/eager.mjs +1 -59
  46. package/dist/lib/modes/lazy.mjs +1 -81
  47. package/dist/lib/processors/flatten.mjs +1 -437
  48. package/dist/lib/processors/loader.mjs +1 -339
  49. package/dist/lib/processors/type-generator.mjs +1 -275
  50. package/dist/lib/processors/typescript.mjs +1 -172
  51. package/dist/lib/runtime/runtime-asynclocalstorage.mjs +1 -113
  52. package/dist/lib/runtime/runtime-livebindings.mjs +1 -78
  53. package/dist/lib/runtime/runtime.mjs +1 -102
  54. package/dist/slothlet.mjs +1 -817
  55. package/package.json +35 -31
  56. package/types/dist/lib/builders/api-assignment.d.mts +3 -92
  57. package/types/dist/lib/builders/api-assignment.d.mts.map +1 -1
  58. package/types/dist/lib/builders/api_builder.d.mts +102 -91
  59. package/types/dist/lib/builders/api_builder.d.mts.map +1 -1
  60. package/types/dist/lib/builders/builder.d.mts +1 -55
  61. package/types/dist/lib/builders/builder.d.mts.map +1 -1
  62. package/types/dist/lib/builders/modes-processor.d.mts +3 -27
  63. package/types/dist/lib/builders/modes-processor.d.mts.map +1 -1
  64. package/types/dist/lib/errors.d.mts +19 -109
  65. package/types/dist/lib/errors.d.mts.map +1 -1
  66. package/types/dist/lib/factories/component-base.d.mts +7 -177
  67. package/types/dist/lib/factories/component-base.d.mts.map +1 -1
  68. package/types/dist/lib/factories/context.d.mts +4 -22
  69. package/types/dist/lib/factories/context.d.mts.map +1 -1
  70. package/types/dist/lib/handlers/api-cache-manager.d.mts +20 -203
  71. package/types/dist/lib/handlers/api-cache-manager.d.mts.map +1 -1
  72. package/types/dist/lib/handlers/api-manager.d.mts +34 -408
  73. package/types/dist/lib/handlers/api-manager.d.mts.map +1 -1
  74. package/types/dist/lib/handlers/context-async.d.mts +23 -61
  75. package/types/dist/lib/handlers/context-async.d.mts.map +1 -1
  76. package/types/dist/lib/handlers/context-live.d.mts +22 -59
  77. package/types/dist/lib/handlers/context-live.d.mts.map +1 -1
  78. package/types/dist/lib/handlers/hook-manager.d.mts +46 -185
  79. package/types/dist/lib/handlers/hook-manager.d.mts.map +1 -1
  80. package/types/dist/lib/handlers/lifecycle-token.d.mts +3 -48
  81. package/types/dist/lib/handlers/lifecycle-token.d.mts.map +1 -1
  82. package/types/dist/lib/handlers/lifecycle.d.mts +5 -82
  83. package/types/dist/lib/handlers/lifecycle.d.mts.map +1 -1
  84. package/types/dist/lib/handlers/materialize-manager.d.mts +8 -70
  85. package/types/dist/lib/handlers/materialize-manager.d.mts.map +1 -1
  86. package/types/dist/lib/handlers/metadata.d.mts +17 -221
  87. package/types/dist/lib/handlers/metadata.d.mts.map +1 -1
  88. package/types/dist/lib/handlers/ownership.d.mts +44 -160
  89. package/types/dist/lib/handlers/ownership.d.mts.map +1 -1
  90. package/types/dist/lib/handlers/permission-manager.d.mts +40 -141
  91. package/types/dist/lib/handlers/permission-manager.d.mts.map +1 -1
  92. package/types/dist/lib/handlers/unified-wrapper.d.mts +26 -239
  93. package/types/dist/lib/handlers/unified-wrapper.d.mts.map +1 -1
  94. package/types/dist/lib/handlers/version-manager.d.mts +28 -225
  95. package/types/dist/lib/handlers/version-manager.d.mts.map +1 -1
  96. package/types/dist/lib/helpers/class-instance-wrapper.d.mts +2 -52
  97. package/types/dist/lib/helpers/class-instance-wrapper.d.mts.map +1 -1
  98. package/types/dist/lib/helpers/config.d.mts +125 -139
  99. package/types/dist/lib/helpers/config.d.mts.map +1 -1
  100. package/types/dist/lib/helpers/eventemitter-context.d.mts +3 -29
  101. package/types/dist/lib/helpers/eventemitter-context.d.mts.map +1 -1
  102. package/types/dist/lib/helpers/hint-detector.d.mts +2 -15
  103. package/types/dist/lib/helpers/hint-detector.d.mts.map +1 -1
  104. package/types/dist/lib/helpers/modes-utils.d.mts +3 -30
  105. package/types/dist/lib/helpers/modes-utils.d.mts.map +1 -1
  106. package/types/dist/lib/helpers/pattern-matcher.d.mts +3 -43
  107. package/types/dist/lib/helpers/pattern-matcher.d.mts.map +1 -1
  108. package/types/dist/lib/helpers/resolve-from-caller.d.mts +3 -27
  109. package/types/dist/lib/helpers/resolve-from-caller.d.mts.map +1 -1
  110. package/types/dist/lib/helpers/sanitize.d.mts +4 -92
  111. package/types/dist/lib/helpers/sanitize.d.mts.map +1 -1
  112. package/types/dist/lib/helpers/utilities.d.mts +4 -52
  113. package/types/dist/lib/helpers/utilities.d.mts.map +1 -1
  114. package/types/dist/lib/i18n/translations.d.mts +4 -37
  115. package/types/dist/lib/i18n/translations.d.mts.map +1 -1
  116. package/types/dist/lib/modes/eager.d.mts +8 -30
  117. package/types/dist/lib/modes/eager.d.mts.map +1 -1
  118. package/types/dist/lib/modes/lazy.d.mts +10 -43
  119. package/types/dist/lib/modes/lazy.d.mts.map +1 -1
  120. package/types/dist/lib/processors/flatten.d.mts +56 -107
  121. package/types/dist/lib/processors/flatten.d.mts.map +1 -1
  122. package/types/dist/lib/processors/loader.d.mts +6 -41
  123. package/types/dist/lib/processors/loader.d.mts.map +1 -1
  124. package/types/dist/lib/processors/type-generator.d.mts +2 -16
  125. package/types/dist/lib/processors/type-generator.d.mts.map +1 -1
  126. package/types/dist/lib/processors/typescript.d.mts +6 -53
  127. package/types/dist/lib/processors/typescript.d.mts.map +1 -1
  128. package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts +3 -71
  129. package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts.map +1 -1
  130. package/types/dist/lib/runtime/runtime-livebindings.d.mts +2 -37
  131. package/types/dist/lib/runtime/runtime-livebindings.d.mts.map +1 -1
  132. package/types/dist/lib/runtime/runtime.d.mts +3 -39
  133. package/types/dist/lib/runtime/runtime.d.mts.map +1 -1
  134. package/types/dist/slothlet.d.mts +3 -249
  135. package/types/dist/slothlet.d.mts.map +1 -1
  136. package/types/index.d.mts +36 -16
  137. package/types/index.d.mts.map +1 -0
  138. package/AGENT-USAGE.md +0 -736
  139. package/docs/API-RULES.md +0 -712
@@ -14,888 +14,4 @@
14
14
  limitations under the License.
15
15
  */
16
16
 
17
-
18
-
19
-
20
-
21
- import { inspect } from "node:util";
22
- import { ComponentBase } from "@cldmv/slothlet/factories/component-base";
23
-
24
-
25
-
26
-
27
- function stripPrefix(tag) {
28
-
29
- return tag.replace(/^[^0-9]+/, "");
30
- }
31
-
32
-
33
- function stripSuffix(s) {
34
-
35
- return s.replace(/[-+].*$/, "");
36
- }
37
-
38
-
39
- function normaliseVersionTag(tag) {
40
- const bare = stripSuffix(stripPrefix(tag));
41
- const parts = bare.split(".").map((p) => {
42
- const n = parseInt(p, 10);
43
-
44
-
45
- return isNaN(n) ? 0 : n;
46
- });
47
-
48
-
49
- return [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];
50
- }
51
-
52
-
53
- function compareTuples(a, b) {
54
- for (let i = 0; i < 3; i++) {
55
- if (a[i] !== b[i]) return b[i] - a[i];
56
- }
57
-
58
-
59
-
60
-
61
-
62
- return 0;
63
- }
64
-
65
-
66
-
67
- const FORCE_VERSION_SYMBOL = Symbol.for("slothlet.versioning.force");
68
-
69
-
70
-
71
-
72
- export class VersionManager extends ComponentBase {
73
- static slothletProperty = "versionManager";
74
-
75
-
76
- #registry = new Map();
77
-
78
-
79
- #versionMetadataByModule = new Map();
80
-
81
-
82
- #moduleToVersionKey = new Map();
83
-
84
-
85
- #dispatchers = new Map();
86
-
87
-
88
-
89
-
90
- registerVersion(logicalPath, versionTag, moduleID, versionMeta, isDefault) {
91
- if (!this.#registry.has(logicalPath)) {
92
- this.#registry.set(logicalPath, { versions: new Map() });
93
- }
94
-
95
- const entry = this.#registry.get(logicalPath);
96
-
97
-
98
- if (entry.versions.has(versionTag)) {
99
- throw new this.SlothletError("VERSION_REGISTER_DUPLICATE", {
100
- version: versionTag,
101
- apiPath: logicalPath
102
- });
103
- }
104
-
105
-
106
- const versionEntry = {
107
- moduleID,
108
- versionTag,
109
- versionedPath: `${versionTag}.${logicalPath}`,
110
-
111
-
112
-
113
- versionedParts: [versionTag, ...logicalPath.split(".")],
114
-
115
-
116
- isDefault: isDefault ?? false,
117
-
118
- versionMeta: versionMeta ?? {},
119
- registeredAt: Date.now()
120
- };
121
-
122
- entry.versions.set(versionTag, versionEntry);
123
- this.#moduleToVersionKey.set(moduleID, { logicalPath, versionTag });
124
-
125
-
126
- this.#versionMetadataByModule.set(moduleID, {
127
-
128
-
129
- ...(versionMeta ?? {}),
130
- version: versionTag,
131
- logicalPath
132
- });
133
-
134
- this.slothlet.debug("versioning", {
135
- key: "DEBUG_VERSION_REGISTERED",
136
- version: versionTag,
137
- logicalPath,
138
- moduleID
139
- });
140
-
141
-
142
- this.updateDispatcher(logicalPath);
143
- }
144
-
145
-
146
- unregisterVersion(logicalPath, versionTag) {
147
- const entry = this.#registry.get(logicalPath);
148
-
149
-
150
-
151
- if (!entry) return false;
152
-
153
- const versionEntry = entry.versions.get(versionTag);
154
-
155
-
156
- if (!versionEntry) return false;
157
-
158
-
159
- this.#moduleToVersionKey.delete(versionEntry.moduleID);
160
- this.#versionMetadataByModule.delete(versionEntry.moduleID);
161
- entry.versions.delete(versionTag);
162
-
163
- this.slothlet.debug("versioning", {
164
- key: "DEBUG_VERSION_UNREGISTERED",
165
- version: versionTag,
166
- logicalPath
167
- });
168
-
169
- if (entry.versions.size === 0) {
170
-
171
- this.#registry.delete(logicalPath);
172
- this.teardownDispatcher(logicalPath);
173
- } else {
174
-
175
- this.updateDispatcher(logicalPath);
176
- }
177
-
178
- return true;
179
- }
180
-
181
-
182
- getVersionKeyForModule(moduleID) {
183
- return this.#moduleToVersionKey.get(moduleID);
184
- }
185
-
186
-
187
- hasDispatcher(logicalPath) {
188
- return this.#dispatchers.has(logicalPath);
189
- }
190
-
191
-
192
- getVersionMetadata(moduleID) {
193
- return this.#versionMetadataByModule.get(moduleID);
194
- }
195
-
196
-
197
- getVersionMetadataByPath(logicalPath, versionTag) {
198
- const entry = this.#registry.get(logicalPath);
199
- if (!entry) return undefined;
200
- const ve = entry.versions.get(versionTag);
201
- if (!ve) return undefined;
202
- return this.#versionMetadataByModule.get(ve.moduleID);
203
- }
204
-
205
-
206
- setVersionMetadataByPath(logicalPath, versionTag, patch) {
207
- const entry = this.#registry.get(logicalPath);
208
- if (!entry || !entry.versions.has(versionTag)) {
209
- throw new this.SlothletError("VERSION_NOT_FOUND", {
210
- version: versionTag,
211
- apiPath: logicalPath
212
- });
213
- }
214
- const ve = entry.versions.get(versionTag);
215
-
216
-
217
- const existing = this.#versionMetadataByModule.get(ve.moduleID) ?? {};
218
-
219
- this.#versionMetadataByModule.set(ve.moduleID, {
220
- ...existing,
221
- ...(patch && typeof patch === "object" ? patch : {}),
222
- version: ve.versionTag,
223
- logicalPath
224
- });
225
- }
226
-
227
-
228
- list(logicalPath) {
229
- const entry = this.#registry.get(logicalPath);
230
- if (!entry) return undefined;
231
-
232
- const versions = {};
233
- for (const [tag, ve] of entry.versions) {
234
- versions[tag] = { ...ve };
235
- }
236
- return { versions, default: this.getDefaultVersion(logicalPath) };
237
- }
238
-
239
-
240
- setDefault(logicalPath, versionTag) {
241
- const entry = this.#registry.get(logicalPath);
242
- if (!entry) {
243
- throw new this.SlothletError("VERSION_NOT_FOUND", {
244
- version: versionTag,
245
- apiPath: logicalPath
246
- });
247
- }
248
- if (!entry.versions.has(versionTag)) {
249
- throw new this.SlothletError("VERSION_NOT_FOUND", {
250
- version: versionTag,
251
- apiPath: logicalPath
252
- });
253
- }
254
-
255
- for (const ve of entry.versions.values()) {
256
- ve.isDefault = false;
257
- }
258
- entry.versions.get(versionTag).isDefault = true;
259
- }
260
-
261
-
262
-
263
-
264
- getDefaultVersion(logicalPath) {
265
- const entry = this.#registry.get(logicalPath);
266
-
267
-
268
-
269
- if (!entry || entry.versions.size === 0) return null;
270
-
271
-
272
- for (const [tag, ve] of entry.versions) {
273
- if (ve.isDefault) return tag;
274
- }
275
-
276
-
277
- const tags = Array.from(entry.versions.keys());
278
- if (tags.length === 1) return tags[0];
279
-
280
-
281
- const sorted = tags
282
- .map((tag) => ({ tag, tuple: normaliseVersionTag(tag) }))
283
- .sort((a, b) => {
284
- const cmp = compareTuples(a.tuple, b.tuple);
285
- if (cmp !== 0) return cmp;
286
-
287
-
288
-
289
- const aSuffix = a.tag.match(/[-+]/) ? 1 : 0;
290
-
291
- const bSuffix = b.tag.match(/[-+]/) ? 1 : 0;
292
- return aSuffix - bSuffix;
293
- });
294
-
295
- return sorted[0].tag;
296
- }
297
-
298
-
299
-
300
-
301
- resolveForPath(logicalPath, allVersions, caller) {
302
- const discriminator = this.slothlet.config?.versionDispatcher ?? "version";
303
-
304
- let resolvedTag = null;
305
-
306
- if (typeof discriminator === "string") {
307
-
308
- resolvedTag = caller.versionMetadata?.[discriminator] ?? null;
309
- }
310
-
311
-
312
-
313
- if (typeof discriminator === "function") {
314
- try {
315
- resolvedTag = discriminator(allVersions, caller);
316
- } catch {
317
- resolvedTag = null;
318
- }
319
- }
320
-
321
- if (resolvedTag == null) return null;
322
-
323
-
324
- const entry = this.#registry.get(logicalPath);
325
- if (!entry || !entry.versions.has(resolvedTag)) {
326
- this.slothlet.debug("versioning", {
327
- key: "DEBUG_VERSION_RESOLVED",
328
- version: null,
329
- apiPath: logicalPath,
330
-
331
-
332
- callerModule: caller?.metadata?.moduleID ?? null
333
- });
334
- return null;
335
- }
336
-
337
- this.slothlet.debug("versioning", {
338
- key: "DEBUG_VERSION_RESOLVED",
339
- version: resolvedTag,
340
- apiPath: logicalPath,
341
-
342
-
343
- callerModule: caller?.metadata?.moduleID ?? null
344
- });
345
-
346
- return resolvedTag;
347
- }
348
-
349
-
350
-
351
-
352
- buildAllVersionsArg(logicalPath) {
353
- const entry = this.#registry.get(logicalPath);
354
-
355
-
356
-
357
- if (!entry) return {};
358
-
359
- const defaultTag = this.getDefaultVersion(logicalPath);
360
- const result = {};
361
-
362
- for (const [tag, ve] of entry.versions) {
363
-
364
-
365
-
366
- const mountedWrapper = this.#walkApiPath(ve.versionedParts);
367
-
368
-
369
- const regularMetadata = this.slothlet.handlers.metadata?.getMetadata?.(mountedWrapper) ?? {};
370
-
371
- const versionMetadata = this.#versionMetadataByModule.get(ve.moduleID) ?? {};
372
-
373
- result[tag] = {
374
- version: tag,
375
- default: tag === defaultTag,
376
- metadata: regularMetadata,
377
- versionMetadata
378
- };
379
- }
380
-
381
- return result;
382
- }
383
-
384
-
385
- buildCallerArg(callerWrapper) {
386
-
387
-
388
- const callerModuleID = callerWrapper?.____slothletInternal?.moduleID ?? callerWrapper?.__moduleID;
389
- const callerVersionEntry = callerModuleID ? this.#findVersionEntryForModule(callerModuleID) : null;
390
-
391
-
392
- const regularMetadata = this.slothlet.handlers.metadata?.getMetadata?.(callerWrapper) ?? {};
393
-
394
- if (!callerVersionEntry) {
395
- return {
396
- version: null,
397
- default: null,
398
- metadata: regularMetadata,
399
- versionMetadata: null
400
- };
401
- }
402
-
403
- const defaultTag = this.getDefaultVersion(callerVersionEntry.logicalPath);
404
-
405
-
406
- const versionMetadata = this.#versionMetadataByModule.get(callerModuleID) ?? {};
407
-
408
- return {
409
- version: callerVersionEntry.versionTag,
410
- default: callerVersionEntry.versionTag === defaultTag,
411
- metadata: regularMetadata,
412
- versionMetadata
413
- };
414
- }
415
-
416
-
417
- #findVersionEntryForModule(moduleID) {
418
- const key = this.#moduleToVersionKey.get(moduleID);
419
-
420
-
421
- if (!key) return null;
422
- const entry = this.#registry.get(key.logicalPath);
423
-
424
-
425
-
426
- if (!entry) return null;
427
-
428
-
429
- return entry.versions.get(key.versionTag) ?? null;
430
- }
431
-
432
-
433
- #walkApiPath(apiPath) {
434
-
435
-
436
- if (!apiPath) return undefined;
437
- let node = this.slothlet.api;
438
-
439
-
440
-
441
-
442
- const segments = Array.isArray(apiPath) ? apiPath : apiPath.split(".");
443
- for (const segment of segments) {
444
-
445
-
446
- if (node == null) return undefined;
447
- node = node[segment];
448
- }
449
- return node;
450
- }
451
-
452
-
453
-
454
-
455
- createDispatcher(logicalPath) {
456
- const manager = this;
457
- const target = { __isVersionDispatcher: true, __logicalPath: logicalPath };
458
- const displayName = logicalPath.split(".").pop();
459
-
460
-
461
- const resolveVersion = () => {
462
-
463
-
464
-
465
- const ctx = manager.slothlet.contextManager?.tryGetContext?.();
466
- const forcedVersion = ctx?.context?.[FORCE_VERSION_SYMBOL];
467
- if (forcedVersion) {
468
- const entry = manager.#registry.get(logicalPath);
469
- if (entry?.versions.has(forcedVersion)) return forcedVersion;
470
- }
471
-
472
-
473
-
474
- const callerWrapper = ctx?.currentWrapper ?? null;
475
- const allVersions = manager.buildAllVersionsArg(logicalPath);
476
- const caller = manager.buildCallerArg(callerWrapper);
477
-
478
-
479
- let tag = manager.resolveForPath(logicalPath, allVersions, caller);
480
-
481
- if (tag == null) {
482
-
483
- tag = manager.getDefaultVersion(logicalPath);
484
-
485
-
486
-
487
- if (tag != null) {
488
- manager.slothlet.debug("versioning", {
489
- key: "DEBUG_VERSION_DEFAULT_USED",
490
- apiPath: logicalPath,
491
- version: tag
492
- });
493
- }
494
- }
495
-
496
- return tag;
497
- };
498
-
499
-
500
- const resolveVersionedWrapper = () => {
501
- const versionTag = resolveVersion();
502
-
503
-
504
-
505
- if (!versionTag) return null;
506
-
507
-
508
- return manager.#walkApiPath([versionTag, ...logicalPath.split(".")]);
509
- };
510
-
511
-
512
-
513
-
514
-
515
-
516
- target[Symbol.for("nodejs.util.inspect.custom")] = function (_depth, options, inspectFn) {
517
- const vw = resolveVersionedWrapper();
518
- if (vw) {
519
- try {
520
- return typeof inspectFn === "function" ? inspectFn(vw, options) : inspect(vw, options);
521
- } catch {
522
-
523
-
524
- void 0;
525
- }
526
- }
527
-
528
-
529
-
530
- const entry = manager.#registry.get(logicalPath);
531
- const versions = entry ? Array.from(entry.versions.keys()) : [];
532
- return { __versionDispatcher: logicalPath, versions };
533
- };
534
-
535
- const handlers = {
536
-
537
- get(t, prop) {
538
-
539
- if (typeof prop === "string") {
540
- if (prop === "____slothletInternal" || prop === "_impl" || prop === "__impl" || prop === "__state" || prop === "__invalid") {
541
- return undefined;
542
- }
543
- }
544
-
545
-
546
- if (prop === "__isVersionDispatcher") return true;
547
-
548
-
549
- if (prop === "__mode") return "eager";
550
- if (prop === "__apiPath") return logicalPath;
551
-
552
-
553
- if (prop === "__slothletPath") return logicalPath;
554
- if (prop === "__isCallable") return false;
555
-
556
-
557
-
558
-
559
- if (prop === "__materializeOnCreate") return false;
560
- if (prop === "__materialized") return true;
561
- if (prop === "__inFlight") return false;
562
- if (prop === "__displayName") return displayName;
563
- if (prop === "__moduleID") return `versionDispatcher:${logicalPath}`;
564
- if (prop === "_materialize") return () => {};
565
- if (prop === "length") return 0;
566
- if (prop === "name") return displayName;
567
-
568
-
569
-
570
-
571
-
572
- if (prop === "then") return undefined;
573
-
574
-
575
-
576
-
577
- if (prop === "constructor") return Object.prototype.constructor;
578
-
579
-
580
- if (prop === Symbol.toStringTag) {
581
- const vw = resolveVersionedWrapper();
582
-
583
-
584
- if (!vw) return "Object";
585
- return vw[Symbol.toStringTag];
586
- }
587
-
588
-
589
-
590
-
591
-
592
-
593
-
594
- if (prop === inspect.custom) {
595
- return (_depth, options, inspectFn) => {
596
- const vw = resolveVersionedWrapper();
597
- if (vw) {
598
- try {
599
- return typeof inspectFn === "function" ? inspectFn(vw, options) : inspect(vw, options);
600
- } catch {
601
-
602
-
603
- void 0;
604
- }
605
- }
606
-
607
-
608
- const entry = manager.#registry.get(logicalPath);
609
- const versions = entry ? Array.from(entry.versions.keys()) : [];
610
- return { __versionDispatcher: logicalPath, versions };
611
- };
612
- }
613
-
614
-
615
- if (prop === "toString") return () => `[VersionDispatcher: ${logicalPath}]`;
616
-
617
-
618
- if (prop === "valueOf") return () => dispatcherProxy;
619
-
620
-
621
- if (prop === "toJSON") return () => undefined;
622
-
623
-
624
- if (typeof prop === "symbol") return undefined;
625
-
626
-
627
- if (prop === "__metadata" || prop === "__filePath" || prop === "__sourceFolder" || prop === "__type") {
628
- const vw = resolveVersionedWrapper();
629
-
630
-
631
-
632
- if (!vw) return undefined;
633
- return vw[prop];
634
- }
635
-
636
-
637
-
638
- const versionTag = resolveVersion();
639
-
640
-
641
-
642
- if (!versionTag) {
643
- throw new manager.SlothletError("VERSION_NO_DEFAULT", {
644
- apiPath: logicalPath
645
- });
646
- }
647
-
648
-
649
- const versionedWrapper = manager.#walkApiPath([versionTag, ...logicalPath.split(".")]);
650
-
651
-
652
-
653
- if (!versionedWrapper) return undefined;
654
-
655
- return versionedWrapper[prop];
656
- },
657
-
658
-
659
-
660
- apply() {
661
- throw new manager.SlothletError("VERSION_DISPATCH_NOT_CALLABLE", {
662
- apiPath: logicalPath
663
- });
664
- },
665
-
666
-
667
- has(t, key) {
668
-
669
-
670
-
671
- if (Reflect.has(t, key)) return true;
672
- const entry = manager.#registry.get(logicalPath);
673
-
674
-
675
- if (!entry) return false;
676
- for (const ve of entry.versions.values()) {
677
- const vw = manager.#walkApiPath(ve.versionedParts);
678
-
679
-
680
-
681
-
682
-
683
- if (vw && key in vw) return true;
684
- }
685
- return false;
686
- },
687
-
688
-
689
- ownKeys(t) {
690
- const keySet = new Set(Reflect.ownKeys(t));
691
- const entry = manager.#registry.get(logicalPath);
692
-
693
-
694
- if (entry) {
695
- for (const ve of entry.versions.values()) {
696
- const vw = manager.#walkApiPath(ve.versionedParts);
697
-
698
-
699
- if (vw) {
700
- for (const k of Reflect.ownKeys(Object(vw))) {
701
- keySet.add(k);
702
- }
703
- }
704
- }
705
- }
706
- return Array.from(keySet);
707
- },
708
-
709
-
710
- getOwnPropertyDescriptor(t, prop) {
711
- const targetDesc = Reflect.getOwnPropertyDescriptor(t, prop);
712
- if (targetDesc) {
713
- if (!targetDesc.configurable) {
714
-
715
-
716
-
717
-
718
-
719
- return targetDesc;
720
- }
721
-
722
-
723
- return { configurable: true, enumerable: true, writable: false, value: t[prop] };
724
- }
725
-
726
-
727
-
728
- return { configurable: true, enumerable: true, writable: false, value: undefined };
729
- },
730
-
731
-
732
- defineProperty(t, prop, descriptor) {
733
- const vw = resolveVersionedWrapper();
734
-
735
-
736
-
737
- if (!vw) return Reflect.defineProperty(t, prop, descriptor);
738
- if (descriptor.configurable === false) {
739
-
740
-
741
-
742
-
743
-
744
-
745
- const shadow = Object.create(Reflect.getPrototypeOf(t));
746
- const currentDescriptor = Reflect.getOwnPropertyDescriptor(t, prop);
747
- if (currentDescriptor) {
748
- Reflect.defineProperty(shadow, prop, currentDescriptor);
749
- }
750
-
751
-
752
-
753
-
754
-
755
-
756
-
757
- if (!Reflect.isExtensible(t)) {
758
- Reflect.preventExtensions(shadow);
759
- }
760
- if (!Reflect.defineProperty(shadow, prop, descriptor)) return false;
761
-
762
- if (!Reflect.defineProperty(vw, prop, descriptor)) return false;
763
-
764
-
765
-
766
- return Reflect.defineProperty(t, prop, descriptor);
767
- }
768
-
769
- return Reflect.defineProperty(vw, prop, descriptor);
770
- },
771
-
772
-
773
- set(t, prop, value) {
774
-
775
-
776
-
777
-
778
-
779
- if (typeof prop === "symbol") return true;
780
-
781
-
782
- if (prop === "____slothletInternal" || prop === "_impl" || prop === "__impl" || prop === "__state" || prop === "__invalid")
783
- return true;
784
-
785
-
786
- if (
787
- prop === "__isVersionDispatcher" ||
788
- prop === "__mode" ||
789
- prop === "__apiPath" ||
790
- prop === "__slothletPath" ||
791
- prop === "__isCallable" ||
792
- prop === "__materializeOnCreate" ||
793
- prop === "__materialized" ||
794
- prop === "__inFlight" ||
795
- prop === "__displayName" ||
796
- prop === "__moduleID" ||
797
- prop === "_materialize" ||
798
- prop === "length" ||
799
- prop === "name"
800
- )
801
- return true;
802
-
803
-
804
- if (prop === "then" || prop === "constructor" || prop === "toString" || prop === "valueOf" || prop === "toJSON") return true;
805
-
806
- const vw = resolveVersionedWrapper();
807
-
808
-
809
-
810
-
811
-
812
- if (!vw) return true;
813
-
814
-
815
-
816
- return Reflect.set(vw, prop, value, vw);
817
- }
818
- };
819
-
820
- let dispatcherProxy;
821
- dispatcherProxy = new Proxy(target, handlers);
822
- return dispatcherProxy;
823
- }
824
-
825
-
826
- updateDispatcher(logicalPath) {
827
-
828
-
829
- if (this.#dispatchers.has(logicalPath)) {
830
- return;
831
- }
832
-
833
- const dispatcher = this.createDispatcher(logicalPath);
834
- this.#dispatchers.set(logicalPath, dispatcher);
835
-
836
- const parts = logicalPath.split(".");
837
- const mountOptions = {
838
- collisionMode: "replace",
839
- moduleID: `versionDispatcher:${logicalPath}`,
840
- allowOverwrite: true,
841
- mutateExisting: false
842
- };
843
-
844
-
845
-
846
-
847
- if (this.slothlet.api) {
848
- this.slothlet.handlers.apiManager.setValueAtPath(this.slothlet.api, parts, dispatcher, mountOptions);
849
- }
850
-
851
-
852
- if (this.slothlet.boundApi) {
853
- this.slothlet.handlers.apiManager.setValueAtPath(this.slothlet.boundApi, parts, dispatcher, mountOptions);
854
- }
855
- }
856
-
857
-
858
- teardownDispatcher(logicalPath) {
859
- this.#dispatchers.delete(logicalPath);
860
-
861
- const parts = logicalPath.split(".");
862
-
863
-
864
-
865
- if (this.slothlet.api) {
866
- this.slothlet.handlers.apiManager.deletePath(this.slothlet.api, parts).catch(() => {});
867
- }
868
- if (this.slothlet.boundApi) {
869
- this.slothlet.handlers.apiManager.deletePath(this.slothlet.boundApi, parts).catch(() => {});
870
- }
871
-
872
- }
873
-
874
-
875
-
876
-
877
- onVersionedModuleReload(moduleID) {
878
- const key = this.#moduleToVersionKey.get(moduleID);
879
- if (!key) return;
880
-
881
- const { logicalPath } = key;
882
-
883
-
884
- this.updateDispatcher(logicalPath);
885
-
886
- this.slothlet.debug("versioning", {
887
- key: "DEBUG_VERSION_REGISTERED",
888
- version: key.versionTag,
889
- logicalPath,
890
- moduleID
891
- });
892
- }
893
-
894
-
895
- shutdown() {
896
- this.#registry.clear();
897
- this.#versionMetadataByModule.clear();
898
- this.#moduleToVersionKey.clear();
899
- this.#dispatchers.clear();
900
- }
901
- }
17
+ import{inspect}from"node:util";import{ComponentBase}from"@cldmv/slothlet/factories/component-base";function stripPrefix(tag){return tag.replace(/^[^0-9]+/,"")}function stripSuffix(s){return s.replace(/[-+].*$/,"")}function normaliseVersionTag(tag){const bare=stripSuffix(stripPrefix(tag));const parts=bare.split(".").map(p=>{const n=parseInt(p,10);return isNaN(n)?0:n});return[parts[0]??0,parts[1]??0,parts[2]??0]}function compareTuples(a,b){for(let i=0;i<3;i++){if(a[i]!==b[i])return b[i]-a[i]}return 0}const FORCE_VERSION_SYMBOL=Symbol.for("slothlet.versioning.force");class VersionManager extends ComponentBase{static slothletProperty="versionManager";#registry=new Map;#versionMetadataByModule=new Map;#moduleToVersionKey=new Map;#dispatchers=new Map;registerVersion(logicalPath,versionTag,moduleID,versionMeta,isDefault){if(!this.#registry.has(logicalPath)){this.#registry.set(logicalPath,{versions:new Map})}const entry=this.#registry.get(logicalPath);if(entry.versions.has(versionTag)){throw new this.SlothletError("VERSION_REGISTER_DUPLICATE",{version:versionTag,apiPath:logicalPath})}const versionEntry={moduleID,versionTag,versionedPath:`${versionTag}.${logicalPath}`,versionedParts:[versionTag,...logicalPath.split(".")],isDefault:isDefault??false,versionMeta:versionMeta??{},registeredAt:Date.now()};entry.versions.set(versionTag,versionEntry);this.#moduleToVersionKey.set(moduleID,{logicalPath,versionTag});this.#versionMetadataByModule.set(moduleID,{...versionMeta??{},version:versionTag,logicalPath});this.slothlet.debug("versioning",{key:"DEBUG_VERSION_REGISTERED",version:versionTag,logicalPath,moduleID});this.updateDispatcher(logicalPath)}unregisterVersion(logicalPath,versionTag){const entry=this.#registry.get(logicalPath);if(!entry)return false;const versionEntry=entry.versions.get(versionTag);if(!versionEntry)return false;this.#moduleToVersionKey.delete(versionEntry.moduleID);this.#versionMetadataByModule.delete(versionEntry.moduleID);entry.versions.delete(versionTag);this.slothlet.debug("versioning",{key:"DEBUG_VERSION_UNREGISTERED",version:versionTag,logicalPath});if(entry.versions.size===0){this.#registry.delete(logicalPath);this.teardownDispatcher(logicalPath)}else{this.updateDispatcher(logicalPath)}return true}getVersionKeyForModule(moduleID){return this.#moduleToVersionKey.get(moduleID)}hasDispatcher(logicalPath){return this.#dispatchers.has(logicalPath)}getVersionMetadata(moduleID){return this.#versionMetadataByModule.get(moduleID)}getVersionMetadataByPath(logicalPath,versionTag){const entry=this.#registry.get(logicalPath);if(!entry)return void 0;const ve=entry.versions.get(versionTag);if(!ve)return void 0;return this.#versionMetadataByModule.get(ve.moduleID)}setVersionMetadataByPath(logicalPath,versionTag,patch){const entry=this.#registry.get(logicalPath);if(!entry||!entry.versions.has(versionTag)){throw new this.SlothletError("VERSION_NOT_FOUND",{version:versionTag,apiPath:logicalPath})}const ve=entry.versions.get(versionTag);const existing=this.#versionMetadataByModule.get(ve.moduleID)??{};this.#versionMetadataByModule.set(ve.moduleID,{...existing,...patch&&typeof patch==="object"?patch:{},version:ve.versionTag,logicalPath})}list(logicalPath){const entry=this.#registry.get(logicalPath);if(!entry)return void 0;const versions={};for(const[tag,ve]of entry.versions){versions[tag]={...ve}}return{versions,default:this.getDefaultVersion(logicalPath)}}setDefault(logicalPath,versionTag){const entry=this.#registry.get(logicalPath);if(!entry){throw new this.SlothletError("VERSION_NOT_FOUND",{version:versionTag,apiPath:logicalPath})}if(!entry.versions.has(versionTag)){throw new this.SlothletError("VERSION_NOT_FOUND",{version:versionTag,apiPath:logicalPath})}for(const ve of entry.versions.values()){ve.isDefault=false}entry.versions.get(versionTag).isDefault=true}getDefaultVersion(logicalPath){const entry=this.#registry.get(logicalPath);if(!entry||entry.versions.size===0)return null;for(const[tag,ve]of entry.versions){if(ve.isDefault)return tag}const tags=Array.from(entry.versions.keys());if(tags.length===1)return tags[0];const sorted=tags.map(tag=>({tag,tuple:normaliseVersionTag(tag)})).sort((a,b)=>{const cmp=compareTuples(a.tuple,b.tuple);if(cmp!==0)return cmp;const aSuffix=a.tag.match(/[-+]/)?1:0;const bSuffix=b.tag.match(/[-+]/)?1:0;return aSuffix-bSuffix});return sorted[0].tag}resolveForPath(logicalPath,allVersions,caller){const discriminator=this.slothlet.config?.versionDispatcher??"version";let resolvedTag=null;if(typeof discriminator==="string"){resolvedTag=caller.versionMetadata?.[discriminator]??null}if(typeof discriminator==="function"){try{resolvedTag=discriminator(allVersions,caller)}catch{resolvedTag=null}}if(resolvedTag==null)return null;const entry=this.#registry.get(logicalPath);if(!entry||!entry.versions.has(resolvedTag)){this.slothlet.debug("versioning",{key:"DEBUG_VERSION_RESOLVED",version:null,apiPath:logicalPath,callerModule:caller?.metadata?.moduleID??null});return null}this.slothlet.debug("versioning",{key:"DEBUG_VERSION_RESOLVED",version:resolvedTag,apiPath:logicalPath,callerModule:caller?.metadata?.moduleID??null});return resolvedTag}buildAllVersionsArg(logicalPath){const entry=this.#registry.get(logicalPath);if(!entry)return{};const defaultTag=this.getDefaultVersion(logicalPath);const result={};for(const[tag,ve]of entry.versions){const mountedWrapper=this.#walkApiPath(ve.versionedParts);const regularMetadata=this.slothlet.handlers.metadata?.getMetadata?.(mountedWrapper)??{};const versionMetadata=this.#versionMetadataByModule.get(ve.moduleID)??{};result[tag]={version:tag,default:tag===defaultTag,metadata:regularMetadata,versionMetadata}}return result}buildCallerArg(callerWrapper){const callerModuleID=callerWrapper?.____slothletInternal?.moduleID??callerWrapper?.__moduleID;const callerVersionEntry=callerModuleID?this.#findVersionEntryForModule(callerModuleID):null;const regularMetadata=this.slothlet.handlers.metadata?.getMetadata?.(callerWrapper)??{};if(!callerVersionEntry){return{version:null,default:null,metadata:regularMetadata,versionMetadata:null}}const defaultTag=this.getDefaultVersion(callerVersionEntry.logicalPath);const versionMetadata=this.#versionMetadataByModule.get(callerModuleID)??{};return{version:callerVersionEntry.versionTag,default:callerVersionEntry.versionTag===defaultTag,metadata:regularMetadata,versionMetadata}}#findVersionEntryForModule(moduleID){const key=this.#moduleToVersionKey.get(moduleID);if(!key)return null;const entry=this.#registry.get(key.logicalPath);if(!entry)return null;return entry.versions.get(key.versionTag)??null}#walkApiPath(apiPath){if(!apiPath)return void 0;let node=this.slothlet.api;const segments=Array.isArray(apiPath)?apiPath:apiPath.split(".");for(const segment of segments){if(node==null)return void 0;node=node[segment]}return node}createDispatcher(logicalPath){const manager=this;const target={__isVersionDispatcher:true,__logicalPath:logicalPath};const displayName=logicalPath.split(".").pop();const resolveVersion=()=>{const ctx=manager.slothlet.contextManager?.tryGetContext?.();const forcedVersion=ctx?.context?.[FORCE_VERSION_SYMBOL];if(forcedVersion){const entry=manager.#registry.get(logicalPath);if(entry?.versions.has(forcedVersion))return forcedVersion}const callerWrapper=ctx?.currentWrapper??null;const allVersions=manager.buildAllVersionsArg(logicalPath);const caller=manager.buildCallerArg(callerWrapper);let tag=manager.resolveForPath(logicalPath,allVersions,caller);if(tag==null){tag=manager.getDefaultVersion(logicalPath);if(tag!=null){manager.slothlet.debug("versioning",{key:"DEBUG_VERSION_DEFAULT_USED",apiPath:logicalPath,version:tag})}}return tag};const resolveVersionedWrapper=()=>{const versionTag=resolveVersion();if(!versionTag)return null;return manager.#walkApiPath([versionTag,...logicalPath.split(".")])};target[Symbol.for("nodejs.util.inspect.custom")]=function(_depth,options,inspectFn){const vw=resolveVersionedWrapper();if(vw){try{return typeof inspectFn==="function"?inspectFn(vw,options):inspect(vw,options)}catch{}}const entry=manager.#registry.get(logicalPath);const versions=entry?Array.from(entry.versions.keys()):[];return{__versionDispatcher:logicalPath,versions}};const handlers={get(t,prop){if(typeof prop==="string"){if(prop==="____slothletInternal"||prop==="_impl"||prop==="__impl"||prop==="__state"||prop==="__invalid"){return void 0}}if(prop==="__isVersionDispatcher")return true;if(prop==="__mode")return"eager";if(prop==="__apiPath")return logicalPath;if(prop==="__slothletPath")return logicalPath;if(prop==="__isCallable")return false;if(prop==="__materializeOnCreate")return false;if(prop==="__materialized")return true;if(prop==="__inFlight")return false;if(prop==="__displayName")return displayName;if(prop==="__moduleID")return`versionDispatcher:${logicalPath}`;if(prop==="_materialize")return()=>{};if(prop==="length")return 0;if(prop==="name")return displayName;if(prop==="then")return void 0;if(prop==="constructor")return Object.prototype.constructor;if(prop===Symbol.toStringTag){const vw=resolveVersionedWrapper();if(!vw)return"Object";return vw[Symbol.toStringTag]}if(prop===inspect.custom){return(_depth,options,inspectFn)=>{const vw=resolveVersionedWrapper();if(vw){try{return typeof inspectFn==="function"?inspectFn(vw,options):inspect(vw,options)}catch{}}const entry=manager.#registry.get(logicalPath);const versions=entry?Array.from(entry.versions.keys()):[];return{__versionDispatcher:logicalPath,versions}}}if(prop==="toString")return()=>`[VersionDispatcher: ${logicalPath}]`;if(prop==="valueOf")return()=>dispatcherProxy;if(prop==="toJSON")return()=>void 0;if(typeof prop==="symbol")return void 0;if(prop==="__metadata"||prop==="__filePath"||prop==="__sourceFolder"||prop==="__type"){const vw=resolveVersionedWrapper();if(!vw)return void 0;return vw[prop]}const versionTag=resolveVersion();if(!versionTag){throw new manager.SlothletError("VERSION_NO_DEFAULT",{apiPath:logicalPath})}const versionedWrapper=manager.#walkApiPath([versionTag,...logicalPath.split(".")]);if(!versionedWrapper)return void 0;return versionedWrapper[prop]},apply(){throw new manager.SlothletError("VERSION_DISPATCH_NOT_CALLABLE",{apiPath:logicalPath})},has(t,key){if(Reflect.has(t,key))return true;const entry=manager.#registry.get(logicalPath);if(!entry)return false;for(const ve of entry.versions.values()){const vw=manager.#walkApiPath(ve.versionedParts);if(vw&&key in vw)return true}return false},ownKeys(t){const keySet=new Set(Reflect.ownKeys(t));const entry=manager.#registry.get(logicalPath);if(entry){for(const ve of entry.versions.values()){const vw=manager.#walkApiPath(ve.versionedParts);if(vw){for(const k of Reflect.ownKeys(Object(vw))){keySet.add(k)}}}}return Array.from(keySet)},getOwnPropertyDescriptor(t,prop){const targetDesc=Reflect.getOwnPropertyDescriptor(t,prop);if(targetDesc){if(!targetDesc.configurable){return targetDesc}return{configurable:true,enumerable:true,writable:false,value:t[prop]}}return{configurable:true,enumerable:true,writable:false,value:void 0}},defineProperty(t,prop,descriptor){const vw=resolveVersionedWrapper();if(!vw)return Reflect.defineProperty(t,prop,descriptor);if(descriptor.configurable===false){const shadow=Object.create(Reflect.getPrototypeOf(t));const currentDescriptor=Reflect.getOwnPropertyDescriptor(t,prop);if(currentDescriptor){Reflect.defineProperty(shadow,prop,currentDescriptor)}if(!Reflect.isExtensible(t)){Reflect.preventExtensions(shadow)}if(!Reflect.defineProperty(shadow,prop,descriptor))return false;if(!Reflect.defineProperty(vw,prop,descriptor))return false;return Reflect.defineProperty(t,prop,descriptor)}return Reflect.defineProperty(vw,prop,descriptor)},set(t,prop,value){if(typeof prop==="symbol")return true;if(prop==="____slothletInternal"||prop==="_impl"||prop==="__impl"||prop==="__state"||prop==="__invalid")return true;if(prop==="__isVersionDispatcher"||prop==="__mode"||prop==="__apiPath"||prop==="__slothletPath"||prop==="__isCallable"||prop==="__materializeOnCreate"||prop==="__materialized"||prop==="__inFlight"||prop==="__displayName"||prop==="__moduleID"||prop==="_materialize"||prop==="length"||prop==="name")return true;if(prop==="then"||prop==="constructor"||prop==="toString"||prop==="valueOf"||prop==="toJSON")return true;const vw=resolveVersionedWrapper();if(!vw)return true;return Reflect.set(vw,prop,value,vw)}};let dispatcherProxy;dispatcherProxy=new Proxy(target,handlers);return dispatcherProxy}updateDispatcher(logicalPath){if(this.#dispatchers.has(logicalPath)){return}const dispatcher=this.createDispatcher(logicalPath);this.#dispatchers.set(logicalPath,dispatcher);const parts=logicalPath.split(".");const mountOptions={collisionMode:"replace",moduleID:`versionDispatcher:${logicalPath}`,allowOverwrite:true,mutateExisting:false};if(this.slothlet.api){this.slothlet.handlers.apiManager.setValueAtPath(this.slothlet.api,parts,dispatcher,mountOptions)}if(this.slothlet.boundApi){this.slothlet.handlers.apiManager.setValueAtPath(this.slothlet.boundApi,parts,dispatcher,mountOptions)}}teardownDispatcher(logicalPath){this.#dispatchers.delete(logicalPath);const parts=logicalPath.split(".");if(this.slothlet.api){this.slothlet.handlers.apiManager.deletePath(this.slothlet.api,parts).catch(()=>{})}if(this.slothlet.boundApi){this.slothlet.handlers.apiManager.deletePath(this.slothlet.boundApi,parts).catch(()=>{})}}onVersionedModuleReload(moduleID){const key=this.#moduleToVersionKey.get(moduleID);if(!key)return;const{logicalPath}=key;this.updateDispatcher(logicalPath);this.slothlet.debug("versioning",{key:"DEBUG_VERSION_REGISTERED",version:key.versionTag,logicalPath,moduleID})}shutdown(){this.#registry.clear();this.#versionMetadataByModule.clear();this.#moduleToVersionKey.clear();this.#dispatchers.clear()}}export{VersionManager};