@cldmv/slothlet 3.2.3 → 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.
Files changed (138) hide show
  1. package/README.md +22 -9
  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 -1155
  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 -2513
  12. package/dist/lib/handlers/context-async.mjs +1 -168
  13. package/dist/lib/handlers/context-live.mjs +1 -168
  14. package/dist/lib/handlers/hook-manager.mjs +1 -773
  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 +17 -0
  21. package/dist/lib/handlers/unified-wrapper.mjs +1 -3042
  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 -355
  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 +17 -0
  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 +21 -1
  33. package/dist/lib/i18n/languages/en-gb.json +21 -1
  34. package/dist/lib/i18n/languages/en-us.json +21 -1
  35. package/dist/lib/i18n/languages/es-mx.json +21 -1
  36. package/dist/lib/i18n/languages/fr-fr.json +21 -1
  37. package/dist/lib/i18n/languages/hi-in.json +21 -1
  38. package/dist/lib/i18n/languages/ja-jp.json +21 -1
  39. package/dist/lib/i18n/languages/ko-kr.json +21 -1
  40. package/dist/lib/i18n/languages/pt-br.json +21 -1
  41. package/dist/lib/i18n/languages/ru-ru.json +21 -1
  42. package/dist/lib/i18n/languages/zh-cn.json +21 -1
  43. package/dist/lib/i18n/translations.mjs +1 -126
  44. package/dist/lib/modes/eager.mjs +1 -59
  45. package/dist/lib/modes/lazy.mjs +1 -81
  46. package/dist/lib/processors/flatten.mjs +1 -437
  47. package/dist/lib/processors/loader.mjs +1 -339
  48. package/dist/lib/processors/type-generator.mjs +1 -275
  49. package/dist/lib/processors/typescript.mjs +1 -172
  50. package/dist/lib/runtime/runtime-asynclocalstorage.mjs +1 -113
  51. package/dist/lib/runtime/runtime-livebindings.mjs +1 -78
  52. package/dist/lib/runtime/runtime.mjs +1 -102
  53. package/dist/slothlet.mjs +1 -808
  54. package/package.json +37 -31
  55. package/types/dist/lib/builders/api-assignment.d.mts +3 -92
  56. package/types/dist/lib/builders/api-assignment.d.mts.map +1 -1
  57. package/types/dist/lib/builders/api_builder.d.mts +102 -91
  58. package/types/dist/lib/builders/api_builder.d.mts.map +1 -1
  59. package/types/dist/lib/builders/builder.d.mts +1 -55
  60. package/types/dist/lib/builders/builder.d.mts.map +1 -1
  61. package/types/dist/lib/builders/modes-processor.d.mts +3 -27
  62. package/types/dist/lib/builders/modes-processor.d.mts.map +1 -1
  63. package/types/dist/lib/errors.d.mts +19 -109
  64. package/types/dist/lib/errors.d.mts.map +1 -1
  65. package/types/dist/lib/factories/component-base.d.mts +7 -177
  66. package/types/dist/lib/factories/component-base.d.mts.map +1 -1
  67. package/types/dist/lib/factories/context.d.mts +4 -22
  68. package/types/dist/lib/factories/context.d.mts.map +1 -1
  69. package/types/dist/lib/handlers/api-cache-manager.d.mts +20 -203
  70. package/types/dist/lib/handlers/api-cache-manager.d.mts.map +1 -1
  71. package/types/dist/lib/handlers/api-manager.d.mts +33 -408
  72. package/types/dist/lib/handlers/api-manager.d.mts.map +1 -1
  73. package/types/dist/lib/handlers/context-async.d.mts +23 -61
  74. package/types/dist/lib/handlers/context-async.d.mts.map +1 -1
  75. package/types/dist/lib/handlers/context-live.d.mts +22 -59
  76. package/types/dist/lib/handlers/context-live.d.mts.map +1 -1
  77. package/types/dist/lib/handlers/hook-manager.d.mts +46 -185
  78. package/types/dist/lib/handlers/hook-manager.d.mts.map +1 -1
  79. package/types/dist/lib/handlers/lifecycle-token.d.mts +3 -48
  80. package/types/dist/lib/handlers/lifecycle-token.d.mts.map +1 -1
  81. package/types/dist/lib/handlers/lifecycle.d.mts +5 -82
  82. package/types/dist/lib/handlers/lifecycle.d.mts.map +1 -1
  83. package/types/dist/lib/handlers/materialize-manager.d.mts +8 -70
  84. package/types/dist/lib/handlers/materialize-manager.d.mts.map +1 -1
  85. package/types/dist/lib/handlers/metadata.d.mts +17 -221
  86. package/types/dist/lib/handlers/metadata.d.mts.map +1 -1
  87. package/types/dist/lib/handlers/ownership.d.mts +44 -160
  88. package/types/dist/lib/handlers/ownership.d.mts.map +1 -1
  89. package/types/dist/lib/handlers/permission-manager.d.mts +47 -0
  90. package/types/dist/lib/handlers/permission-manager.d.mts.map +1 -0
  91. package/types/dist/lib/handlers/unified-wrapper.d.mts +26 -239
  92. package/types/dist/lib/handlers/unified-wrapper.d.mts.map +1 -1
  93. package/types/dist/lib/handlers/version-manager.d.mts +28 -225
  94. package/types/dist/lib/handlers/version-manager.d.mts.map +1 -1
  95. package/types/dist/lib/helpers/class-instance-wrapper.d.mts +2 -52
  96. package/types/dist/lib/helpers/class-instance-wrapper.d.mts.map +1 -1
  97. package/types/dist/lib/helpers/config.d.mts +125 -123
  98. package/types/dist/lib/helpers/config.d.mts.map +1 -1
  99. package/types/dist/lib/helpers/eventemitter-context.d.mts +3 -29
  100. package/types/dist/lib/helpers/eventemitter-context.d.mts.map +1 -1
  101. package/types/dist/lib/helpers/hint-detector.d.mts +2 -15
  102. package/types/dist/lib/helpers/hint-detector.d.mts.map +1 -1
  103. package/types/dist/lib/helpers/modes-utils.d.mts +3 -30
  104. package/types/dist/lib/helpers/modes-utils.d.mts.map +1 -1
  105. package/types/dist/lib/helpers/pattern-matcher.d.mts +4 -0
  106. package/types/dist/lib/helpers/pattern-matcher.d.mts.map +1 -0
  107. package/types/dist/lib/helpers/resolve-from-caller.d.mts +3 -27
  108. package/types/dist/lib/helpers/resolve-from-caller.d.mts.map +1 -1
  109. package/types/dist/lib/helpers/sanitize.d.mts +4 -92
  110. package/types/dist/lib/helpers/sanitize.d.mts.map +1 -1
  111. package/types/dist/lib/helpers/utilities.d.mts +4 -52
  112. package/types/dist/lib/helpers/utilities.d.mts.map +1 -1
  113. package/types/dist/lib/i18n/translations.d.mts +4 -37
  114. package/types/dist/lib/i18n/translations.d.mts.map +1 -1
  115. package/types/dist/lib/modes/eager.d.mts +8 -30
  116. package/types/dist/lib/modes/eager.d.mts.map +1 -1
  117. package/types/dist/lib/modes/lazy.d.mts +10 -43
  118. package/types/dist/lib/modes/lazy.d.mts.map +1 -1
  119. package/types/dist/lib/processors/flatten.d.mts +56 -107
  120. package/types/dist/lib/processors/flatten.d.mts.map +1 -1
  121. package/types/dist/lib/processors/loader.d.mts +6 -41
  122. package/types/dist/lib/processors/loader.d.mts.map +1 -1
  123. package/types/dist/lib/processors/type-generator.d.mts +2 -16
  124. package/types/dist/lib/processors/type-generator.d.mts.map +1 -1
  125. package/types/dist/lib/processors/typescript.d.mts +6 -53
  126. package/types/dist/lib/processors/typescript.d.mts.map +1 -1
  127. package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts +3 -71
  128. package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts.map +1 -1
  129. package/types/dist/lib/runtime/runtime-livebindings.d.mts +2 -37
  130. package/types/dist/lib/runtime/runtime-livebindings.d.mts.map +1 -1
  131. package/types/dist/lib/runtime/runtime.d.mts +3 -39
  132. package/types/dist/lib/runtime/runtime.d.mts.map +1 -1
  133. package/types/dist/slothlet.d.mts +3 -249
  134. package/types/dist/slothlet.d.mts.map +1 -1
  135. package/types/index.d.mts +36 -16
  136. package/types/index.d.mts.map +1 -0
  137. package/AGENT-USAGE.md +0 -736
  138. 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};