@devcraft-ts/diadem 0.1.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.
@@ -0,0 +1,683 @@
1
+ 'use strict';
2
+
3
+ var chunkFHQRDO5C_cjs = require('./chunk-FHQRDO5C.cjs');
4
+
5
+ // src/core/dependency-resolver.ts
6
+ var EnhancedDependencyResolver = class {
7
+ registeredServices = /* @__PURE__ */ new Set();
8
+ serviceClassMap = /* @__PURE__ */ new Map();
9
+ serviceMetadataMap = /* @__PURE__ */ new Map();
10
+ /**
11
+ * Register services using build-time dependency analysis
12
+ * Services are registered in the correct order based on their dependencies
13
+ */
14
+ async registerServicesWithManifest(container, services, manifestEntries, environment) {
15
+ const warnings = [];
16
+ const registrationOrder = [];
17
+ let registeredCount = 0;
18
+ let skippedCount = 0;
19
+ const manifestMap = /* @__PURE__ */ new Map();
20
+ this.serviceClassMap.clear();
21
+ this.serviceMetadataMap.clear();
22
+ let servicesWithMetadata = 0;
23
+ const reverseMapping = /* @__PURE__ */ new Map();
24
+ try {
25
+ const { SERVICE_CLASSES } = await chunkFHQRDO5C_cjs.loadManifest();
26
+ Object.entries(SERVICE_CLASSES).forEach(([originalName, serviceClass]) => {
27
+ reverseMapping.set(serviceClass, originalName);
28
+ });
29
+ } catch {
30
+ }
31
+ for (const serviceClass of services) {
32
+ const metadata = chunkFHQRDO5C_cjs.getDIMetadata(serviceClass);
33
+ if (metadata) {
34
+ const originalName = reverseMapping.get(serviceClass) || serviceClass.name;
35
+ this.serviceClassMap.set(originalName, serviceClass);
36
+ this.serviceMetadataMap.set(originalName, metadata);
37
+ servicesWithMetadata++;
38
+ }
39
+ }
40
+ chunkFHQRDO5C_cjs.getLogger().info(
41
+ `\u{1F4CB} Built service map: ${servicesWithMetadata}/${services.length} services with DI metadata`
42
+ );
43
+ if (servicesWithMetadata === 0) {
44
+ chunkFHQRDO5C_cjs.getLogger().error("\u274C CRITICAL: No services have DI metadata!");
45
+ chunkFHQRDO5C_cjs.getLogger().error(
46
+ "\u{1F50D} Service analysis:",
47
+ services.slice(0, 3).map((s) => ({
48
+ name: s.name,
49
+ hasDI: !!chunkFHQRDO5C_cjs.getDIMetadata(s)
50
+ }))
51
+ );
52
+ }
53
+ for (const entry of manifestEntries) {
54
+ if (environment && entry.environment && entry.environment !== environment) {
55
+ continue;
56
+ }
57
+ manifestMap.set(entry.className, entry);
58
+ }
59
+ chunkFHQRDO5C_cjs.getLogger().info(
60
+ `\u{1F4CB} Manifest map: ${manifestMap.size}/${manifestEntries.length} entries for ${environment || "any"}`
61
+ );
62
+ const sortedEntries = Array.from(manifestMap.values()).sort(
63
+ (a, b) => a.registrationOrder - b.registrationOrder
64
+ );
65
+ if (sortedEntries.length === 0) {
66
+ chunkFHQRDO5C_cjs.getLogger().error("\u274C CRITICAL: No services to register after filtering!");
67
+ chunkFHQRDO5C_cjs.getLogger().error("\u{1F50D} Debug analysis:", {
68
+ serviceClassMapSize: this.serviceClassMap.size,
69
+ manifestMapSize: manifestMap.size,
70
+ serviceNames: Array.from(this.serviceClassMap.keys()).slice(0, 5),
71
+ manifestNames: manifestEntries.slice(0, 5).map((e) => e.className),
72
+ environment
73
+ });
74
+ return {
75
+ registeredServices: [],
76
+ registeredCount: 0,
77
+ skippedCount: 0,
78
+ dependencyStats: {
79
+ totalServices: 0,
80
+ servicesWithDependencies: 0,
81
+ totalDependencies: 0,
82
+ externalDependencies: 0,
83
+ maxDependencyDepth: 0
84
+ },
85
+ warnings: ["No services to register"],
86
+ registrationOrder: []
87
+ };
88
+ }
89
+ chunkFHQRDO5C_cjs.getLogger().info(`\u{1F517} Registering ${sortedEntries.length} services`);
90
+ for (const manifestEntry of sortedEntries) {
91
+ const serviceClass = this.serviceClassMap.get(manifestEntry.className);
92
+ if (!serviceClass) {
93
+ chunkFHQRDO5C_cjs.getLogger().error(`\u274C Service class not found: ${manifestEntry.className}`);
94
+ chunkFHQRDO5C_cjs.getLogger().error(
95
+ `\u{1F50D} Available: ${Array.from(this.serviceClassMap.keys()).slice(0, 5).join(", ")}...`
96
+ );
97
+ warnings.push(`Service class ${manifestEntry.className} not found`);
98
+ skippedCount++;
99
+ continue;
100
+ }
101
+ try {
102
+ await this.registerSingleService(
103
+ container,
104
+ serviceClass,
105
+ manifestEntry,
106
+ warnings
107
+ );
108
+ registeredCount++;
109
+ registrationOrder.push(manifestEntry.className);
110
+ this.registeredServices.add(manifestEntry.className);
111
+ } catch (error) {
112
+ const err = error;
113
+ skippedCount++;
114
+ chunkFHQRDO5C_cjs.getLogger().error(
115
+ `\u274C Registration failed: ${manifestEntry.className} - ${err.message}`
116
+ );
117
+ warnings.push(
118
+ `Failed to register ${manifestEntry.className}: ${err.message}`
119
+ );
120
+ }
121
+ }
122
+ chunkFHQRDO5C_cjs.getLogger().info(
123
+ `\u{1F4CA} Registration complete: ${registeredCount} registered, ${skippedCount} skipped`
124
+ );
125
+ const dependencyStats = this.calculateDependencyStats(manifestEntries);
126
+ const result = {
127
+ registeredServices: Array.from(this.registeredServices),
128
+ registeredCount,
129
+ skippedCount,
130
+ dependencyStats,
131
+ warnings,
132
+ registrationOrder
133
+ };
134
+ if (process.env.DEBUG_DI) {
135
+ chunkFHQRDO5C_cjs.getLogger().info(`\u{1F4CA} Registration Summary:`);
136
+ chunkFHQRDO5C_cjs.getLogger().info(` \u2705 Registered: ${registeredCount}`);
137
+ chunkFHQRDO5C_cjs.getLogger().info(` \u26A0\uFE0F Skipped: ${skippedCount}`);
138
+ chunkFHQRDO5C_cjs.getLogger().info(
139
+ ` \u{1F517} Dependencies resolved: ${dependencyStats.totalDependencies}`
140
+ );
141
+ if (warnings.length > 0) {
142
+ chunkFHQRDO5C_cjs.getLogger().warn(` \u26A0\uFE0F Warnings: ${warnings.length}`);
143
+ }
144
+ }
145
+ return result;
146
+ }
147
+ /**
148
+ * Register a single service with proper dependency injection
149
+ */
150
+ async registerSingleService(container, ServiceClass, manifestEntry, warnings) {
151
+ const metadata = chunkFHQRDO5C_cjs.getDIMetadata(ServiceClass);
152
+ if (!metadata) {
153
+ chunkFHQRDO5C_cjs.getLogger().error(`\u274C No DI metadata: ${ServiceClass.name}`);
154
+ throw new Error(`No DI metadata found for ${ServiceClass.name}`);
155
+ }
156
+ if (typeof container.registerSingleton !== "function" || typeof container.registerFactory !== "function") {
157
+ chunkFHQRDO5C_cjs.getLogger().error(
158
+ `\u274C Container missing registration methods for ${ServiceClass.name}`
159
+ );
160
+ throw new Error(`Container missing registration methods`);
161
+ }
162
+ const createInstance = () => {
163
+ const resolvedArgs = [];
164
+ for (const dependency of manifestEntry.resolvedDependencies) {
165
+ try {
166
+ if (dependency.external) {
167
+ if (dependency.isOptional) {
168
+ resolvedArgs[dependency.paramIndex] = void 0;
169
+ } else {
170
+ const defaultValue = this.getDefaultValueForExternalDependency(dependency);
171
+ if (defaultValue !== void 0) {
172
+ resolvedArgs[dependency.paramIndex] = defaultValue;
173
+ } else {
174
+ throw new Error(
175
+ `External dependency ${dependency.typeName} is required but no default available`
176
+ );
177
+ }
178
+ }
179
+ } else if (dependency.implementingService) {
180
+ const depMetadata = this.serviceMetadataMap.get(
181
+ dependency.implementingService
182
+ );
183
+ if (!depMetadata) {
184
+ throw new Error(
185
+ `No DI metadata found for dependency ${dependency.implementingService}`
186
+ );
187
+ }
188
+ const resolvedDep = container.resolve(depMetadata.token);
189
+ resolvedArgs[dependency.paramIndex] = resolvedDep;
190
+ } else {
191
+ if (dependency.isOptional) {
192
+ resolvedArgs[dependency.paramIndex] = void 0;
193
+ } else {
194
+ throw new Error(
195
+ `Unknown dependency type for ${dependency.typeName}`
196
+ );
197
+ }
198
+ }
199
+ } catch (error) {
200
+ if (dependency.isOptional) {
201
+ resolvedArgs[dependency.paramIndex] = void 0;
202
+ warnings.push(
203
+ `Optional dependency ${dependency.typeName} could not be resolved for ${ServiceClass.name}: ${error}`
204
+ );
205
+ } else {
206
+ throw new Error(
207
+ `Cannot resolve required dependency ${dependency.typeName} for service ${ServiceClass.name}: ${error}`,
208
+ { cause: error }
209
+ );
210
+ }
211
+ }
212
+ }
213
+ return new ServiceClass(...resolvedArgs);
214
+ };
215
+ chunkFHQRDO5C_cjs.getLogger().info(
216
+ `\u{1F527} Registering ${ServiceClass.name} (${manifestEntry.lifecycle})`
217
+ );
218
+ try {
219
+ switch (manifestEntry.lifecycle) {
220
+ case "singleton":
221
+ container.registerSingleton(metadata.token, createInstance);
222
+ break;
223
+ case "factory":
224
+ container.registerFactory(metadata.token, createInstance);
225
+ break;
226
+ case "lazy":
227
+ container.registerFactory(metadata.token, createInstance);
228
+ break;
229
+ case "lazySingleton": {
230
+ let lazySingletonInstance = null;
231
+ container.registerFactory(metadata.token, () => {
232
+ if (lazySingletonInstance === null) {
233
+ lazySingletonInstance = createInstance();
234
+ }
235
+ return lazySingletonInstance;
236
+ });
237
+ break;
238
+ }
239
+ default:
240
+ container.registerSingleton(metadata.token, createInstance);
241
+ }
242
+ chunkFHQRDO5C_cjs.getLogger().info(`\u2705 Registered ${ServiceClass.name}`);
243
+ } catch (error) {
244
+ const err = error;
245
+ chunkFHQRDO5C_cjs.getLogger().error(
246
+ `\u274C Container registration failed for ${ServiceClass.name}: ${err.message}`
247
+ );
248
+ throw error;
249
+ }
250
+ }
251
+ /**
252
+ * Get default value for external dependencies
253
+ */
254
+ getDefaultValueForExternalDependency(dependency) {
255
+ switch (dependency.typeName) {
256
+ case "string":
257
+ return "";
258
+ case "number":
259
+ return 0;
260
+ case "boolean":
261
+ return false;
262
+ default:
263
+ return void 0;
264
+ }
265
+ }
266
+ /**
267
+ * Calculate dependency statistics from manifest entries
268
+ */
269
+ calculateDependencyStats(manifestEntries) {
270
+ let servicesWithDependencies = 0;
271
+ let totalDependencies = 0;
272
+ let externalDependencies = 0;
273
+ let maxDependencyDepth = 0;
274
+ for (const entry of manifestEntries) {
275
+ if (entry.resolvedDependencies.length > 0) {
276
+ servicesWithDependencies++;
277
+ totalDependencies += entry.resolvedDependencies.length;
278
+ maxDependencyDepth = Math.max(
279
+ maxDependencyDepth,
280
+ entry.resolvedDependencies.length
281
+ );
282
+ externalDependencies += entry.resolvedDependencies.filter(
283
+ (dep) => dep.external
284
+ ).length;
285
+ }
286
+ }
287
+ return {
288
+ totalServices: manifestEntries.length,
289
+ servicesWithDependencies,
290
+ totalDependencies,
291
+ externalDependencies,
292
+ maxDependencyDepth
293
+ };
294
+ }
295
+ /**
296
+ * Validate that all required dependencies can be resolved
297
+ */
298
+ validateDependencies(manifestEntries) {
299
+ const missingDependencies = [];
300
+ const availableServices = new Set(
301
+ manifestEntries.map((entry) => entry.className)
302
+ );
303
+ for (const entry of manifestEntries) {
304
+ for (const dep of entry.resolvedDependencies) {
305
+ if (!dep.external && !dep.isOptional && dep.implementingService) {
306
+ if (!availableServices.has(dep.implementingService)) {
307
+ missingDependencies.push(
308
+ `${entry.className} requires ${dep.implementingService} (${dep.typeName})`
309
+ );
310
+ }
311
+ }
312
+ }
313
+ }
314
+ const circularDependencies = this.detectCircularDependencies(manifestEntries);
315
+ return {
316
+ valid: missingDependencies.length === 0 && circularDependencies.length === 0,
317
+ missingDependencies,
318
+ circularDependencies
319
+ };
320
+ }
321
+ /**
322
+ * Detect circular dependencies in manifest entries
323
+ */
324
+ detectCircularDependencies(manifestEntries) {
325
+ const cycles = [];
326
+ const entryMap = new Map(
327
+ manifestEntries.map((entry) => [entry.className, entry])
328
+ );
329
+ const visited = /* @__PURE__ */ new Set();
330
+ const visiting = /* @__PURE__ */ new Set();
331
+ const findCycles = (className, path) => {
332
+ if (visiting.has(className)) {
333
+ const cycleStart = path.indexOf(className);
334
+ const cycle = path.slice(cycleStart).join(" -> ") + ` -> ${className}`;
335
+ cycles.push(cycle);
336
+ return;
337
+ }
338
+ if (visited.has(className)) return;
339
+ const entry = entryMap.get(className);
340
+ if (!entry) return;
341
+ visited.add(className);
342
+ visiting.add(className);
343
+ for (const dep of entry.resolvedDependencies) {
344
+ if (dep.implementingService && !dep.external) {
345
+ findCycles(dep.implementingService, [...path, className]);
346
+ }
347
+ }
348
+ visiting.delete(className);
349
+ };
350
+ for (const entry of manifestEntries) {
351
+ if (!visited.has(entry.className)) {
352
+ findCycles(entry.className, []);
353
+ }
354
+ }
355
+ return cycles;
356
+ }
357
+ };
358
+ async function registerServicesWithManifestDependencies(container, services, manifestEntries, environment) {
359
+ const resolver = new EnhancedDependencyResolver();
360
+ const validation = resolver.validateDependencies(manifestEntries);
361
+ if (!validation.valid) {
362
+ if (process.env.NODE_ENV === "development" || process.env.DEBUG_DI) {
363
+ chunkFHQRDO5C_cjs.getLogger().warn("\u26A0\uFE0F Dependency validation warnings:");
364
+ validation.missingDependencies.forEach((dep) => {
365
+ chunkFHQRDO5C_cjs.getLogger().warn(` - ${dep}`);
366
+ });
367
+ validation.circularDependencies.forEach((cycle) => {
368
+ chunkFHQRDO5C_cjs.getLogger().warn(` - Circular: ${cycle}`);
369
+ });
370
+ }
371
+ }
372
+ return resolver.registerServicesWithManifest(
373
+ container,
374
+ services,
375
+ manifestEntries,
376
+ environment
377
+ );
378
+ }
379
+
380
+ // src/core/container.ts
381
+ function isDisposable(value) {
382
+ return typeof value === "object" && value !== null && typeof value.dispose === "function";
383
+ }
384
+ var DiademContainer = class _DiademContainer {
385
+ dependencies = /* @__PURE__ */ new Map();
386
+ singletons = /* @__PURE__ */ new Map();
387
+ factories = /* @__PURE__ */ new Map();
388
+ asyncFactories = /* @__PURE__ */ new Map();
389
+ disposers = [];
390
+ ready = false;
391
+ disposed = false;
392
+ /**
393
+ * Register a dependency by value or class instance.
394
+ * @param token Dependency token
395
+ * @param implementation The value or instance to register
396
+ */
397
+ register(token, implementation) {
398
+ this.dependencies.set(token, implementation);
399
+ this.trackDisposable(implementation);
400
+ }
401
+ /**
402
+ * Register a factory that returns a new instance on every resolve.
403
+ * Use for transient dependencies.
404
+ * @param token Dependency token
405
+ * @param factory Factory function
406
+ */
407
+ registerFactory(token, factory) {
408
+ this.factories.set(token, factory);
409
+ }
410
+ /**
411
+ * Register a singleton (one instance per container).
412
+ *
413
+ * **Order matters:** the factory runs immediately, at registration time, so
414
+ * anything it resolves must already be registered. Register dependencies
415
+ * before their dependents — the build-time manifest is emitted in exactly this
416
+ * (topological) order. To defer construction until first resolve instead, use
417
+ * a `lazySingleton` lifecycle via the decorator/manifest.
418
+ *
419
+ * @param token Dependency token
420
+ * @param factory Factory function, called once, immediately
421
+ */
422
+ registerSingleton(token, factory) {
423
+ if (!this.singletons.has(token)) {
424
+ const instance = factory();
425
+ this.singletons.set(token, instance);
426
+ this.trackDisposable(instance);
427
+ }
428
+ }
429
+ /**
430
+ * Register a factory that awaits its result on every {@link resolveAsync}.
431
+ * Use for transient dependencies that require asynchronous construction.
432
+ * @param token Dependency token
433
+ * @param factory Async factory function
434
+ */
435
+ registerAsyncFactory(token, factory) {
436
+ this.asyncFactories.set(token, factory);
437
+ }
438
+ /**
439
+ * Register an async singleton: the factory runs at most once (on the first
440
+ * {@link resolveAsync}) and the awaited instance is cached. If the instance
441
+ * is {@link Disposable} it is torn down on {@link dispose}.
442
+ * @param token Dependency token
443
+ * @param factory Async factory function, called at most once
444
+ */
445
+ registerAsyncSingleton(token, factory) {
446
+ let cached;
447
+ this.asyncFactories.set(token, () => {
448
+ cached ??= factory().then((instance) => {
449
+ this.trackDisposable(instance);
450
+ return instance;
451
+ });
452
+ return cached;
453
+ });
454
+ }
455
+ /** Record a value's disposer if it implements {@link Disposable}. */
456
+ trackDisposable(value) {
457
+ if (isDisposable(value)) {
458
+ this.disposers.push(() => value.dispose());
459
+ }
460
+ }
461
+ /**
462
+ * Resolve a dependency by token.
463
+ * @param token Dependency token
464
+ * @returns The resolved dependency
465
+ * @throws If the dependency is not found
466
+ */
467
+ resolve(token) {
468
+ if (!token) {
469
+ throw new Error("Dependency token is undefined or null");
470
+ }
471
+ if (this.dependencies.has(token)) {
472
+ return this.dependencies.get(token);
473
+ }
474
+ if (this.singletons.has(token)) {
475
+ return this.singletons.get(token);
476
+ }
477
+ if (this.factories.has(token)) {
478
+ const factory = this.factories.get(token);
479
+ return factory?.();
480
+ }
481
+ if (this.asyncFactories.has(token)) {
482
+ throw new Error(
483
+ `Dependency ${token?.name || "Unknown"} is registered as an async factory; resolve it with resolveAsync() instead of resolve().`
484
+ );
485
+ }
486
+ const tokenName = token?.name || "Unknown";
487
+ const registeredTokens = this.getRegisteredTokens();
488
+ const registeredNames = registeredTokens.map((t) => t?.name || "Unknown").join(", ");
489
+ throw new Error(
490
+ `Dependency not found: ${tokenName}. Available services: [${registeredNames}]. Total registered: ${registeredTokens.length}`
491
+ );
492
+ }
493
+ /**
494
+ * Resolve a dependency that may have been registered asynchronously.
495
+ * Synchronous registrations resolve immediately; async factories/singletons
496
+ * are awaited.
497
+ * @param token Dependency token
498
+ * @returns A promise of the resolved dependency
499
+ * @throws If the dependency is not found
500
+ */
501
+ async resolveAsync(token) {
502
+ if (!token) {
503
+ throw new Error("Dependency token is undefined or null");
504
+ }
505
+ if (this.dependencies.has(token) || this.singletons.has(token) || this.factories.has(token)) {
506
+ return this.resolve(token);
507
+ }
508
+ const asyncFactory = this.asyncFactories.get(token);
509
+ if (asyncFactory) {
510
+ return asyncFactory();
511
+ }
512
+ return this.resolve(token);
513
+ }
514
+ /**
515
+ * Returns true if the container is fully set up.
516
+ */
517
+ isReady() {
518
+ return this.ready;
519
+ }
520
+ /**
521
+ * Mark the container as ready (all dependencies registered).
522
+ */
523
+ setReady() {
524
+ this.ready = true;
525
+ }
526
+ /**
527
+ * Clear all registrations (useful for testing or container reset).
528
+ */
529
+ clear() {
530
+ this.dependencies.clear();
531
+ this.singletons.clear();
532
+ this.factories.clear();
533
+ this.asyncFactories.clear();
534
+ this.disposers.length = 0;
535
+ this.ready = false;
536
+ }
537
+ /**
538
+ * Register an arbitrary teardown callback, run on {@link dispose} in reverse
539
+ * order of registration.
540
+ */
541
+ onDispose(callback) {
542
+ this.disposers.push(callback);
543
+ }
544
+ /**
545
+ * Dispose the container: run all teardown callbacks (and the `dispose()` of
546
+ * any registered {@link Disposable} singletons/values) in reverse order, then
547
+ * clear all registrations. Idempotent.
548
+ *
549
+ * Note: transient (`factory`) and lazy instances are owned by the caller, not
550
+ * the container, so they are not disposed here.
551
+ */
552
+ async dispose() {
553
+ if (this.disposed) {
554
+ return;
555
+ }
556
+ this.disposed = true;
557
+ for (const disposer of [...this.disposers].reverse()) {
558
+ try {
559
+ await disposer();
560
+ } catch (error) {
561
+ chunkFHQRDO5C_cjs.getLogger().error("Diadem: disposer threw during dispose()", error);
562
+ }
563
+ }
564
+ this.clear();
565
+ }
566
+ /** Whether {@link dispose} has been called. */
567
+ isDisposed() {
568
+ return this.disposed;
569
+ }
570
+ /**
571
+ * Get diagnostic information about registered dependencies.
572
+ */
573
+ getDiagnostics() {
574
+ return {
575
+ dependencies: this.dependencies.size,
576
+ singletons: this.singletons.size,
577
+ factories: this.factories.size,
578
+ asyncFactories: this.asyncFactories.size,
579
+ isReady: this.ready
580
+ };
581
+ }
582
+ /**
583
+ * Check if a token is registered in the container
584
+ */
585
+ has(token) {
586
+ if (!token) {
587
+ return false;
588
+ }
589
+ return this.dependencies.has(token) || this.singletons.has(token) || this.factories.has(token) || this.asyncFactories.has(token);
590
+ }
591
+ /**
592
+ * Get all registered tokens
593
+ */
594
+ getRegisteredTokens() {
595
+ const tokens = /* @__PURE__ */ new Set();
596
+ this.dependencies.forEach((_, token) => tokens.add(token));
597
+ this.singletons.forEach((_, token) => tokens.add(token));
598
+ this.factories.forEach((_, token) => tokens.add(token));
599
+ this.asyncFactories.forEach((_, token) => tokens.add(token));
600
+ return Array.from(tokens);
601
+ }
602
+ /**
603
+ * Create a child container that inherits this container's registrations and
604
+ * can override them locally. Useful for per-request or per-test scopes.
605
+ *
606
+ * The child shares the parent's already-created singleton instances by
607
+ * reference; it deliberately does NOT inherit the parent's disposers, so
608
+ * disposing the child never tears down shared parent-owned resources. Only
609
+ * resources the child registers itself are disposed with it.
610
+ */
611
+ createChild() {
612
+ const child = new _DiademContainer();
613
+ this.dependencies.forEach((impl, token) => {
614
+ child.dependencies.set(token, impl);
615
+ });
616
+ this.singletons.forEach((impl, token) => {
617
+ child.singletons.set(token, impl);
618
+ });
619
+ this.factories.forEach((factory, token) => {
620
+ child.factories.set(token, factory);
621
+ });
622
+ this.asyncFactories.forEach((factory, token) => {
623
+ child.asyncFactories.set(token, factory);
624
+ });
625
+ return child;
626
+ }
627
+ /**
628
+ * Auto-discover and get information about available services.
629
+ * Does not register them - use autoRegisterDiscovered() for that.
630
+ */
631
+ async autoDiscover(config) {
632
+ const { discoverServices } = await import('./auto-discovery-5IV22D5D.cjs');
633
+ return discoverServices(config);
634
+ }
635
+ /**
636
+ * Auto-discover and register all DI-decorated services using build-time manifest.
637
+ * This is true autowiring that doesn't require hardcoded paths or explicit imports.
638
+ *
639
+ * @param environment Optional environment filter
640
+ * @example
641
+ * ```typescript
642
+ * const container = new DiademContainer()
643
+ * await container.autoRegisterDiscovered('production')
644
+ * container.setReady()
645
+ * ```
646
+ */
647
+ async autoRegisterDiscovered(environment) {
648
+ try {
649
+ const { discoverServices } = await import('./auto-discovery-5IV22D5D.cjs');
650
+ const discoveryResult = await discoverServices({ environment });
651
+ const services = discoveryResult.services;
652
+ if (!discoveryResult.manifestAvailable) {
653
+ chunkFHQRDO5C_cjs.getLogger().warn(
654
+ "Diadem: no manifest configured \u2014 nothing was auto-registered."
655
+ );
656
+ return;
657
+ }
658
+ const { getServicesForEnvironment } = await chunkFHQRDO5C_cjs.loadManifest();
659
+ const manifestEntries = getServicesForEnvironment(environment);
660
+ const result = await registerServicesWithManifestDependencies(
661
+ this,
662
+ services,
663
+ manifestEntries,
664
+ environment
665
+ );
666
+ const log = chunkFHQRDO5C_cjs.getLogger();
667
+ log.debug(
668
+ `Diadem: registered ${result.registeredCount} services for "${environment ?? "all"}"`,
669
+ result.dependencyStats
670
+ );
671
+ if (result.warnings.length > 0) {
672
+ log.warn("Diadem: registration warnings", result.warnings);
673
+ }
674
+ } catch (error) {
675
+ chunkFHQRDO5C_cjs.getLogger().error("Diadem: auto-registration failed", error);
676
+ throw error;
677
+ }
678
+ }
679
+ };
680
+
681
+ exports.DiademContainer = DiademContainer;
682
+ //# sourceMappingURL=chunk-72YY5X6T.cjs.map
683
+ //# sourceMappingURL=chunk-72YY5X6T.cjs.map