alloy-di 1.1.0 → 1.2.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 (40) hide show
  1. package/dist/lib/container.d.ts +6 -7
  2. package/dist/lib/container.js +1 -3
  3. package/dist/lib/decorators.d.ts +0 -1
  4. package/dist/lib/decorators.js +5 -7
  5. package/dist/lib/dependency-error.js +1 -3
  6. package/dist/lib/env-detection.js +2 -4
  7. package/dist/lib/lazy.js +1 -2
  8. package/dist/lib/providers.d.ts +0 -1
  9. package/dist/lib/providers.js +3 -5
  10. package/dist/lib/scope.js +1 -2
  11. package/dist/lib/service-identifiers.d.ts +0 -1
  12. package/dist/lib/service-identifiers.js +1 -2
  13. package/dist/lib/testing/mocking.d.ts +1 -3
  14. package/dist/lib/testing/mocking.js +1 -3
  15. package/dist/lib/testing/registry.js +1 -3
  16. package/dist/lib/types.js +1 -2
  17. package/dist/plugins/core/codegen.js +118 -54
  18. package/dist/plugins/core/decorators.js +1 -3
  19. package/dist/plugins/core/discovery-store.js +1 -3
  20. package/dist/plugins/core/identifier-resolver.js +1 -3
  21. package/dist/plugins/core/lazy.js +83 -45
  22. package/dist/plugins/core/scanner.js +121 -42
  23. package/dist/plugins/core/types.d.ts +33 -15
  24. package/dist/plugins/core/utils.js +13 -15
  25. package/dist/plugins/rollup-plugin/build-utils.js +1 -3
  26. package/dist/plugins/rollup-plugin/index.js +73 -45
  27. package/dist/plugins/vite-plugin/container-loader.js +92 -0
  28. package/dist/plugins/vite-plugin/discovery-runtime.js +76 -0
  29. package/dist/plugins/vite-plugin/index.d.ts +1 -11
  30. package/dist/plugins/vite-plugin/index.js +57 -134
  31. package/dist/plugins/vite-plugin/manifest-utils.js +176 -79
  32. package/dist/plugins/vite-plugin/visualization-utils.d.ts +15 -0
  33. package/dist/plugins/vite-plugin/visualization-utils.js +28 -0
  34. package/dist/plugins/vite-plugin/visualizer.js +4 -6
  35. package/dist/rollup.js +2 -4
  36. package/dist/runtime.js +1 -2
  37. package/dist/test.js +1 -3
  38. package/dist/tsconfig.tsbuildinfo +1 -1
  39. package/dist/vite.js +1 -3
  40. package/package.json +34 -29
@@ -2,7 +2,6 @@ import { Constructor, Newable, Token } from "./types.js";
2
2
  import { ServiceIdentifier } from "./service-identifiers.js";
3
3
 
4
4
  //#region src/lib/container.d.ts
5
-
6
5
  /**
7
6
  * Runtime dependency injection container used by generated modules and tests.
8
7
  *
@@ -10,12 +9,12 @@ import { ServiceIdentifier } from "./service-identifiers.js";
10
9
  * performs singleton caching, and supports token-based value providers.
11
10
  */
12
11
  declare class Container {
13
- private singletons;
14
- private pendingSingletons;
15
- private instanceOverrides;
16
- private metadataCache;
17
- private valueProviders;
18
- private factoryWarningCache;
12
+ private readonly singletons;
13
+ private readonly pendingSingletons;
14
+ private readonly instanceOverrides;
15
+ private readonly metadataCache;
16
+ private readonly valueProviders;
17
+ private readonly factoryWarningCache;
19
18
  /**
20
19
  * Resolve (and construct) the requested service.
21
20
  *
@@ -5,7 +5,6 @@ import { dependenciesRegistry } from "./decorators.js";
5
5
  import { DependencyResolutionError } from "./dependency-error.js";
6
6
  import { getConstructorByIdentifier, getServiceIdentifier } from "./service-identifiers.js";
7
7
  import { isDevEnvironment } from "./env-detection.js";
8
-
9
8
  //#region src/lib/container.ts
10
9
  function classifyDependency(value) {
11
10
  if (isLazy(value)) return {
@@ -261,6 +260,5 @@ var Container = class {
261
260
  return metadata;
262
261
  }
263
262
  };
264
-
265
263
  //#endregion
266
- export { Container };
264
+ export { Container };
@@ -3,7 +3,6 @@ import { Lazy } from "./lazy.js";
3
3
  import { ServiceScope } from "./scope.js";
4
4
 
5
5
  //#region src/lib/decorators.d.ts
6
-
7
6
  /**
8
7
  * Resolve a declared dependency to the constructor parameter type expected by the service.
9
8
  *
@@ -1,5 +1,4 @@
1
1
  import { ServiceScope } from "./scope.js";
2
-
3
2
  //#region src/lib/decorators.ts
4
3
  /**
5
4
  * Global registry for service metadata used by the runtime container.
@@ -27,16 +26,16 @@ const dependenciesRegistry = /* @__PURE__ */ new Map();
27
26
  */
28
27
  function createDecoratorWithDeps(scope, depsOpt) {
29
28
  if (typeof depsOpt === "function") {
30
- const depsFn$1 = depsOpt;
29
+ const depsFn = depsOpt;
31
30
  return (target) => {
32
31
  dependenciesRegistry.set(target, {
33
32
  scope,
34
- dependencies: depsFn$1
33
+ dependencies: depsFn
35
34
  });
36
35
  };
37
36
  }
38
- const deps$1 = depsOpt;
39
- const depsFn = () => deps$1;
37
+ const deps = depsOpt;
38
+ const depsFn = () => deps;
40
39
  return (target) => {
41
40
  dependenciesRegistry.set(target, {
42
41
  scope,
@@ -121,6 +120,5 @@ function deps(...items) {
121
120
  function assertDeps(depsFn, klass) {
122
121
  return klass;
123
122
  }
124
-
125
123
  //#endregion
126
- export { Injectable, Singleton, assertDeps, dependenciesRegistry, deps };
124
+ export { Injectable, Singleton, assertDeps, dependenciesRegistry, deps };
@@ -1,6 +1,5 @@
1
1
  import { isConstructor, isToken } from "./types.js";
2
2
  import { isLazy } from "./lazy.js";
3
-
4
3
  //#region src/lib/dependency-error.ts
5
4
  function describeDependency(value) {
6
5
  if (isConstructor(value)) return `constructor ${value.name || "<anonymous>"}`;
@@ -26,6 +25,5 @@ var DependencyResolutionError = class extends Error {
26
25
  return `${this.message}\nResolution path: ${stackPath}${dependencyInfo}`;
27
26
  }
28
27
  };
29
-
30
28
  //#endregion
31
- export { DependencyResolutionError };
29
+ export { DependencyResolutionError };
@@ -16,8 +16,7 @@ function readImportMetaEnvFromRuntime() {
16
16
  }
17
17
  function readProcessNodeEnv() {
18
18
  if (typeof process === "undefined") return;
19
- const nodeEnv = "development";
20
- return typeof nodeEnv === "string" ? nodeEnv : void 0;
19
+ return "development";
21
20
  }
22
21
  function getImportMetaEnv(overrides) {
23
22
  if (overrides?.importMetaEnv === null) return;
@@ -39,6 +38,5 @@ function isDevEnvironment(overrides) {
39
38
  if (typeof importMetaEnv?.NODE_ENV === "string") return importMetaEnv.NODE_ENV !== "production";
40
39
  return true;
41
40
  }
42
-
43
41
  //#endregion
44
- export { isDevEnvironment };
42
+ export { isDevEnvironment };
package/dist/lib/lazy.js CHANGED
@@ -13,6 +13,5 @@ function Lazy(importer, retry) {
13
13
  retry
14
14
  };
15
15
  }
16
-
17
16
  //#endregion
18
- export { LAZY_IDENTIFIER, Lazy, isLazy };
17
+ export { LAZY_IDENTIFIER, Lazy, isLazy };
@@ -4,7 +4,6 @@ import { Lazy } from "./lazy.js";
4
4
  import { ServiceScope } from "./scope.js";
5
5
 
6
6
  //#region src/lib/providers.d.ts
7
-
8
7
  /**
9
8
  * Explicit lifecycle choices for providers. Mirrors decorator scopes but externalized.
10
9
  */
@@ -2,7 +2,6 @@ import { ServiceScope } from "./scope.js";
2
2
  import { isConstructor } from "./types.js";
3
3
  import { Lazy } from "./lazy.js";
4
4
  import { dependenciesRegistry } from "./decorators.js";
5
-
6
5
  //#region src/lib/providers.ts
7
6
  /**
8
7
  * Hidden symbol used to attach lazy provider metadata to its placeholder constructor.
@@ -146,9 +145,9 @@ function applyProviders(container, definitions) {
146
145
  detectProviderCycles(planEntries);
147
146
  for (const definition of list) {
148
147
  for (const valueProvider of definition.values ?? []) container.provideValue(valueProvider.token, valueProvider.value);
149
- const registerService = (ctor, lifecycle$1, deps, factory) => {
148
+ const registerService = (ctor, lifecycle, deps, factory) => {
150
149
  dependenciesRegistry.set(ctor, {
151
- scope: lifecycle$1,
150
+ scope: lifecycle,
152
151
  dependencies: normalizeDependencies(deps),
153
152
  factory
154
153
  });
@@ -161,6 +160,5 @@ function applyProviders(container, definitions) {
161
160
  }
162
161
  }
163
162
  }
164
-
165
163
  //#endregion
166
- export { applyProviders, asClass, asLazyClass, asValue, defineProviders, lifecycle };
164
+ export { applyProviders, asClass, asLazyClass, asValue, defineProviders, lifecycle };
package/dist/lib/scope.js CHANGED
@@ -3,6 +3,5 @@ const ServiceScope = {
3
3
  SINGLETON: "singleton",
4
4
  TRANSIENT: "transient"
5
5
  };
6
-
7
6
  //#endregion
8
- export { ServiceScope };
7
+ export { ServiceScope };
@@ -1,7 +1,6 @@
1
1
  import { Constructor } from "./types.js";
2
2
 
3
3
  //#region src/lib/service-identifiers.d.ts
4
-
5
4
  /**
6
5
  * Symbol-based identifier used to resolve services in a minifier-safe way.
7
6
  * These identifiers never collide with minified constructor names and can be
@@ -49,6 +49,5 @@ function clearServiceIdentifierRegistry() {
49
49
  ctorToIdentifier = /* @__PURE__ */ new WeakMap();
50
50
  identifierToCtor.clear();
51
51
  }
52
-
53
52
  //#endregion
54
- export { clearServiceIdentifierRegistry, getConstructorByIdentifier, getServiceIdentifier, registerServiceIdentifier };
53
+ export { clearServiceIdentifierRegistry, getConstructorByIdentifier, getServiceIdentifier, registerServiceIdentifier };
@@ -5,9 +5,7 @@ import { vi } from "vitest";
5
5
  type MethodKeys<T> = { [K in keyof T]: T[K] extends ((...args: any[]) => any) ? K : never }[keyof T];
6
6
  /** Typed mock shape returned for class auto-mocking. */
7
7
  type MockOf<T> = Partial<T> & {
8
- /** Map of method name -> vi spy function */
9
- spies: Record<Extract<MethodKeys<T>, string>, ReturnType<typeof vi.fn>>;
10
- /** Original constructor reference for introspection */
8
+ /** Map of method name -> vi spy function */spies: Record<Extract<MethodKeys<T>, string>, ReturnType<typeof vi.fn>>; /** Original constructor reference for introspection */
11
9
  __target: Newable<T>;
12
10
  };
13
11
  //#endregion
@@ -2,7 +2,6 @@ import { isConstructor } from "../types.js";
2
2
  import { isLazy } from "../lazy.js";
3
3
  import { getRawDependencies } from "./registry.js";
4
4
  import { vi } from "vitest";
5
-
6
5
  //#region src/lib/testing/mocking.ts
7
6
  /** Create a lightweight auto-mock instance for a class constructor. */
8
7
  function mockClass(ctor) {
@@ -104,6 +103,5 @@ function buildMockCtorFrom(realCtor, mock) {
104
103
  }
105
104
  return MockCtor;
106
105
  }
107
-
108
106
  //#endregion
109
- export { applyAutoMocks };
107
+ export { applyAutoMocks };
@@ -1,5 +1,4 @@
1
1
  import { dependenciesRegistry } from "../decorators.js";
2
-
3
2
  //#region src/lib/testing/registry.ts
4
3
  /** Take a deep(ish) snapshot of current dependency registry state. */
5
4
  function snapshotRegistry() {
@@ -14,6 +13,5 @@ function restoreRegistry(snapshot) {
14
13
  function getRawDependencies(target) {
15
14
  return (dependenciesRegistry.get(target)?.dependencies ?? (() => []))();
16
15
  }
17
-
18
16
  //#endregion
19
- export { getRawDependencies, restoreRegistry, snapshotRegistry };
17
+ export { getRawDependencies, restoreRegistry, snapshotRegistry };
package/dist/lib/types.js CHANGED
@@ -16,6 +16,5 @@ function isConstructor(value) {
16
16
  if (proto.constructor !== value) return false;
17
17
  return true;
18
18
  }
19
-
20
19
  //#endregion
21
- export { createToken, isConstructor, isToken };
20
+ export { createToken, isConstructor, isToken };
@@ -1,10 +1,9 @@
1
1
  import { createClassKey, createSymbolKey, hashString, normalizeImportPath } from "./utils.js";
2
2
  import { IdentifierResolver } from "./identifier-resolver.js";
3
3
  import path from "node:path";
4
-
5
4
  //#region src/plugins/core/codegen.ts
6
5
  function escapeSingleQuotes(value) {
7
- return value.replace(/'/g, "\\'");
6
+ return value.replaceAll("'", "\\'");
8
7
  }
9
8
  /**
10
9
  * Generates a unique export key for the service identifier map.
@@ -26,23 +25,22 @@ function resolveDependencyImports(metas) {
26
25
  const importMap = /* @__PURE__ */ new Map();
27
26
  const nameCounts = /* @__PURE__ */ new Map();
28
27
  const getUniqueName = (name) => {
29
- const count = nameCounts.get(name) || 0;
28
+ const count = nameCounts.get(name) ?? 0;
30
29
  nameCounts.set(name, count + 1);
31
30
  return count === 0 ? name : `${name}_${count}`;
32
31
  };
33
- for (const meta of metas) if (meta.referencedImports) for (const ref of meta.referencedImports) {
34
- if (ref.isTypeOnly) continue;
35
- const dir = path.dirname(meta.filePath);
36
- const normalizedPath = normalizeImportPath(ref.path.startsWith(".") ? path.resolve(dir, ref.path) : ref.path);
37
- const key = `${normalizedPath}::${ref.originalName ?? "default"}`;
38
- let resolved = importMap.get(key);
39
- if (!resolved) {
40
- resolved = {
32
+ for (const meta of metas) {
33
+ if (!meta.referencedImports?.length) continue;
34
+ for (const ref of meta.referencedImports) {
35
+ if (ref.isTypeOnly) continue;
36
+ const normalizedPath = normalizeImportPath(ref.path.startsWith(".") ? path.resolve(path.dirname(meta.filePath), ref.path) : ref.path);
37
+ const key = `${normalizedPath}::${ref.originalName ?? "default"}`;
38
+ if (importMap.has(key)) continue;
39
+ importMap.set(key, {
41
40
  localName: getUniqueName(ref.name),
42
41
  importPath: normalizedPath,
43
42
  originalName: ref.originalName
44
- };
45
- importMap.set(key, resolved);
43
+ });
46
44
  }
47
45
  }
48
46
  return {
@@ -54,9 +52,9 @@ function reconstructDependencyExpression(dep, rewriter, contextDir) {
54
52
  let expr = dep.expression;
55
53
  for (const ident of dep.referencedIdentifiers) {
56
54
  const replacement = rewriter(ident);
57
- if (replacement && replacement !== ident) expr = expr.replace(new RegExp(`\\b${ident}\\b`, "g"), replacement);
55
+ if (replacement && replacement !== ident) expr = expr.replaceAll(new RegExp(`\\b${ident}\\b`, "g"), replacement);
58
56
  }
59
- if (dep.isLazy) expr = expr.replace(/import\s*\(\s*(['"])(.+?)\1\s*\)/g, (match, quote, importPath) => {
57
+ if (dep.isLazy) expr = expr.replaceAll(/import\s*\(\s*(['"])(.+?)\1\s*\)/g, (match, quote, importPath) => {
60
58
  if (importPath.startsWith(".")) return `import(${quote}${normalizeImportPath(path.resolve(contextDir, importPath))}${quote})`;
61
59
  return match;
62
60
  });
@@ -89,12 +87,25 @@ function reconstructOptionsText(meta, importMap) {
89
87
  return `{ ${parts.join(", ")} }`;
90
88
  }
91
89
  function buildImportsAndRegistrations(metas, lazyReferencedClassKeys, hasProviderModules) {
92
- const activeMetas = metas.filter((meta) => !lazyReferencedClassKeys.has(createClassKey(meta.filePath, meta.className)));
90
+ const activeMetas = filterActiveMetas(metas, lazyReferencedClassKeys);
93
91
  const { dependencyImports, importMap } = resolveDependencyImports(activeMetas);
94
- const resolver = new IdentifierResolver(activeMetas);
95
- const resolvedImports = activeMetas.map((meta) => {
92
+ const resolvedRegistrations = enrichRegistrations(activeMetas, new IdentifierResolver(activeMetas), importMap);
93
+ const runtimeImports = computeRuntimeImports(resolvedRegistrations, hasProviderModules);
94
+ const runtimeImportStatement = formatRuntimeImportStatement(runtimeImports);
95
+ const stubsBlock = createStubBlock(dependencyImports, resolvedRegistrations, runtimeImports);
96
+ return {
97
+ runtimeImportStatement,
98
+ registrationsBlock: createRegistrationsBlock(buildRegistrationEntries(resolvedRegistrations)),
99
+ stubsBlock,
100
+ identifierExportBlock: createIdentifierExports(resolvedRegistrations)
101
+ };
102
+ }
103
+ function filterActiveMetas(metas, lazyReferencedClassKeys) {
104
+ return metas.filter((meta) => !lazyReferencedClassKeys.has(createClassKey(meta.filePath, meta.className)));
105
+ }
106
+ function enrichRegistrations(activeMetas, resolver, importMap) {
107
+ return activeMetas.map((meta) => {
96
108
  const importName = resolver.resolve(meta.className, meta.filePath);
97
- const isFactoryLazy = !!meta.metadata.factory;
98
109
  const identifierConst = `${importName}Identifier`;
99
110
  const exportKey = createIdentifierExportKey(meta, resolver);
100
111
  const symbolDescription = meta.identifierKey ?? createSymbolDescription(meta);
@@ -102,53 +113,69 @@ function buildImportsAndRegistrations(metas, lazyReferencedClassKeys, hasProvide
102
113
  return {
103
114
  ...meta,
104
115
  importName,
105
- isFactoryLazy,
116
+ isFactoryLazy: Boolean(meta.metadata.factory),
106
117
  identifierConst,
107
118
  exportKey,
108
119
  symbolDescription,
109
120
  optionsText
110
121
  };
111
122
  });
112
- const needsLazyImport = activeMetas.some((m) => m.metadata.dependencies.some((d) => d.isLazy) || !!m.metadata.factory);
113
- const runtimeImports = new Set(["Container", "dependenciesRegistry"]);
114
- if (hasProviderModules) runtimeImports.add("applyProviders");
115
- if (needsLazyImport) runtimeImports.add("Lazy");
116
- if (resolvedImports.length) runtimeImports.add("registerServiceIdentifier");
117
- const runtimeImportStatement = `\nimport { ${Array.from(runtimeImports).join(", ")} } from 'alloy-di/runtime';\n`;
118
- const stubDeclarations = [];
123
+ }
124
+ function computeRuntimeImports(registrations, hasProviderModules) {
125
+ const imports = new Set(["Container", "dependenciesRegistry"]);
126
+ const needsLazyImport = registrations.some((m) => m.metadata.dependencies.some((d) => d.isLazy) || !!m.metadata.factory);
127
+ if (hasProviderModules) imports.add("applyProviders");
128
+ if (needsLazyImport) imports.add("Lazy");
129
+ if (registrations.length) imports.add("registerServiceIdentifier");
130
+ return imports;
131
+ }
132
+ function formatRuntimeImportStatement(imports) {
133
+ return `\nimport { ${Array.from(imports).join(", ")} } from 'alloy-di/runtime';\n`;
134
+ }
135
+ function createStubBlock(dependencyImports, registrations, runtimeImports) {
136
+ const statements = [];
119
137
  const importedNames = new Set(runtimeImports);
120
138
  for (const dep of dependencyImports) {
121
139
  if (dep.importPath === "alloy-di/runtime" && dep.originalName && dep.localName === dep.originalName && runtimeImports.has(dep.originalName)) continue;
122
140
  if (importedNames.has(dep.localName)) continue;
123
- if (dep.originalName === "default") stubDeclarations.push(`import ${dep.localName} from '${dep.importPath}';`);
124
- else if (dep.originalName === "*") stubDeclarations.push(`import * as ${dep.localName} from '${dep.importPath}';`);
125
- else if (dep.originalName && dep.originalName !== dep.localName) stubDeclarations.push(`import { ${dep.originalName} as ${dep.localName} } from '${dep.importPath}';`);
126
- else stubDeclarations.push(`import { ${dep.localName} } from '${dep.importPath}';`);
141
+ statements.push(createDependencyImportStatement(dep));
127
142
  importedNames.add(dep.localName);
128
143
  }
129
- for (const meta of resolvedImports) {
144
+ for (const meta of registrations) {
130
145
  if (meta.isFactoryLazy) {
131
- stubDeclarations.push(`class ${meta.importName} {}`);
146
+ statements.push(`class ${meta.importName} {}`);
132
147
  continue;
133
148
  }
134
149
  if (importedNames.has(meta.importName)) continue;
135
- const importPath = !/^(\/|[A-Za-z]:\\|\.|~)/.test(meta.filePath) && !meta.filePath.includes("\\") ? meta.filePath : normalizeImportPath(meta.filePath);
136
- if (meta.importName === meta.className) stubDeclarations.push(`import { ${meta.className} } from '${importPath}';`);
137
- else stubDeclarations.push(`import { ${meta.className} as ${meta.importName} } from '${importPath}';`);
150
+ statements.push(createServiceImportStatement(meta));
138
151
  importedNames.add(meta.importName);
139
152
  }
140
- const registrationEntries = resolvedImports.map((m) => ` { ctor: ${m.importName}, meta: ${m.optionsText} }`).join(",\n");
141
- const registrationsBlock = registrationEntries ? `const registrations = [\n${registrationEntries}\n];` : `const registrations = [];`;
142
- const stubsBlock = stubDeclarations.length ? `${stubDeclarations.join("\n")}\n` : "";
143
- const identifierDeclarations = resolvedImports.map((meta) => `const ${meta.identifierConst} = registerServiceIdentifier(${meta.importName}, Symbol.for('${escapeSingleQuotes(meta.symbolDescription)}'));`).join("\n");
144
- const identifierExportEntries = resolvedImports.map((meta) => ` '${meta.exportKey}': ${meta.identifierConst}`).join(",\n");
145
- return {
146
- runtimeImportStatement,
147
- registrationsBlock,
148
- stubsBlock,
149
- identifierDeclarations,
150
- identifierExportBlock: resolvedImports.length ? `${identifierDeclarations}\n\nexport const serviceIdentifiers = {\n${identifierExportEntries}\n};\n` : `export const serviceIdentifiers = {};\n`
151
- };
153
+ return statements.length ? `${statements.join("\n")}\n` : "";
154
+ }
155
+ function createDependencyImportStatement(dep) {
156
+ if (dep.originalName === "default") return `import ${dep.localName} from '${dep.importPath}';`;
157
+ if (dep.originalName === "*") return `import * as ${dep.localName} from '${dep.importPath}';`;
158
+ if (dep.originalName && dep.originalName !== dep.localName) return `import { ${dep.originalName} as ${dep.localName} } from '${dep.importPath}';`;
159
+ return `import { ${dep.localName} } from '${dep.importPath}';`;
160
+ }
161
+ function createServiceImportStatement(meta) {
162
+ const importPath = !/^(\/|[A-Za-z]:\\|\.|~)/.test(meta.filePath) && !meta.filePath.includes("\\") ? meta.filePath : normalizeImportPath(meta.filePath);
163
+ if (meta.importName === meta.className) return `import { ${meta.className} } from '${importPath}';`;
164
+ return `import { ${meta.className} as ${meta.importName} } from '${importPath}';`;
165
+ }
166
+ function buildRegistrationEntries(registrations) {
167
+ return registrations.map((m) => ({
168
+ ctorName: m.importName,
169
+ metaText: m.optionsText
170
+ }));
171
+ }
172
+ function createRegistrationsBlock(entries) {
173
+ if (!entries.length) return "const registrations = [];";
174
+ return `const registrations = [\n${entries.map((entry) => ` { ctor: ${entry.ctorName}, meta: ${entry.metaText} }`).join(",\n")}\n];`;
175
+ }
176
+ function createIdentifierExports(registrations) {
177
+ if (!registrations.length) return "export const serviceIdentifiers = {};\n";
178
+ return `${registrations.map((meta) => `const ${meta.identifierConst} = registerServiceIdentifier(${meta.importName}, Symbol.for('${escapeSingleQuotes(meta.symbolDescription)}'));`).join("\n")}\n\nexport const serviceIdentifiers = {\n${registrations.map((meta) => ` '${meta.exportKey}': ${meta.identifierConst}`).join(",\n")}\n};\n`;
152
179
  }
153
180
  /**
154
181
  * Generates the virtual container module code.
@@ -237,7 +264,7 @@ function generateManifestTypeDefinition(manifests) {
237
264
  declare module "${m.packageName}/manifest" {
238
265
  type ServiceScope = "singleton" | "transient";
239
266
 
240
- interface ManifestLazyDependency {
267
+ interface ManifestLegacyLazyDependency {
241
268
  exportName: string;
242
269
  importPath: string;
243
270
  retry?: {
@@ -247,22 +274,60 @@ declare module "${m.packageName}/manifest" {
247
274
  };
248
275
  }
249
276
 
277
+ interface ManifestLegacyTokenDependency {
278
+ exportName: string;
279
+ importPath: string;
280
+ symbolKey?: string;
281
+ }
282
+
283
+ interface ManifestClassDependency {
284
+ kind: "class";
285
+ exportName: string;
286
+ }
287
+
250
288
  interface ManifestTokenDependency {
289
+ kind: "token";
251
290
  exportName: string;
252
291
  importPath: string;
253
292
  symbolKey?: string;
254
293
  }
255
294
 
256
- interface ManifestService {
295
+ interface ManifestLazyDependency {
296
+ kind: "lazy";
297
+ exportName: string;
298
+ importPath: string;
299
+ retry?: {
300
+ retries: number;
301
+ backoffMs?: number;
302
+ factor?: number;
303
+ };
304
+ }
305
+
306
+ type ManifestDependency =
307
+ | ManifestClassDependency
308
+ | ManifestTokenDependency
309
+ | ManifestLazyDependency;
310
+
311
+ interface ManifestServiceV1 {
257
312
  exportName: string;
258
313
  importPath: string;
259
314
  symbolKey: string;
260
315
  scope: ServiceScope;
261
316
  deps: string[];
262
- lazyDeps: ManifestLazyDependency[];
263
- tokenDeps?: ManifestTokenDependency[];
317
+ lazyDeps: ManifestLegacyLazyDependency[];
318
+ tokenDeps?: ManifestLegacyTokenDependency[];
319
+ }
320
+
321
+ interface ManifestServiceV2 {
322
+ exportName: string;
323
+ importPath: string;
324
+ symbolKey: string;
325
+ scope: ServiceScope;
326
+ deps: ManifestDependency[];
264
327
  }
265
328
 
329
+ type ManifestService = ManifestServiceV1 | ManifestServiceV2;
330
+
266
331
  interface LibraryManifest {
267
332
  schemaVersion: number;
268
333
  packageName: string;
@@ -283,6 +348,5 @@ ${serviceIdentifiers}
283
348
  `;
284
349
  }).join("\n");
285
350
  }
286
-
287
351
  //#endregion
288
- export { generateContainerModule, generateContainerTypeDefinition, generateManifestTypeDefinition };
352
+ export { generateContainerModule, generateContainerTypeDefinition, generateManifestTypeDefinition };
@@ -1,6 +1,5 @@
1
1
  import { ServiceScope } from "../../lib/scope.js";
2
2
  import ts from "typescript";
3
-
4
3
  //#region src/plugins/core/decorators.ts
5
4
  function collectBindingIdentifiers(name, ignored) {
6
5
  if (ts.isIdentifier(name)) {
@@ -108,6 +107,5 @@ function extractServiceMetadata(decoratorName, callExpression, sourceFile) {
108
107
  dependencies
109
108
  };
110
109
  }
111
-
112
110
  //#endregion
113
- export { extractServiceMetadata };
111
+ export { extractServiceMetadata };
@@ -1,5 +1,4 @@
1
1
  import { scanSource } from "./scanner.js";
2
-
3
2
  //#region src/plugins/core/discovery-store.ts
4
3
  /**
5
4
  * Maintains a per-file cache of discovered DI metadata, lazy references, and
@@ -73,6 +72,5 @@ function createDiscoveryStore(options = {}) {
73
72
  clear
74
73
  };
75
74
  }
76
-
77
75
  //#endregion
78
- export { createDiscoveryStore };
76
+ export { createDiscoveryStore };
@@ -1,5 +1,4 @@
1
1
  import { createAliasName } from "./utils.js";
2
-
3
2
  //#region src/plugins/core/identifier-resolver.ts
4
3
  var IdentifierResolver = class {
5
4
  counts;
@@ -17,6 +16,5 @@ var IdentifierResolver = class {
17
16
  return this.count(className) > 1 ? createAliasName(className, importPath) : className;
18
17
  }
19
18
  };
20
-
21
19
  //#endregion
22
- export { IdentifierResolver };
20
+ export { IdentifierResolver };