@goodie-ts/transformer 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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 GOOD Code ApS
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,13 @@
1
+ import type { IRBeanDefinition } from './ir.js';
2
+ /** Options for code generation. */
3
+ export interface CodegenOptions {
4
+ /** Absolute path of the output file (used for computing relative imports). */
5
+ outputPath: string;
6
+ /** Transformer version string (e.g. '0.1.0'). Embedded in the header comment. */
7
+ version?: string;
8
+ }
9
+ /**
10
+ * Generate the AppContext.generated.ts source from topologically sorted beans.
11
+ */
12
+ export declare function generateCode(beans: IRBeanDefinition[], options: CodegenOptions): string;
13
+ //# sourceMappingURL=codegen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAY,MAAM,SAAS,CAAC;AAQ1D,mCAAmC;AACnC,MAAM,WAAW,cAAc;IAC7B,8EAA8E;IAC9E,UAAU,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,gBAAgB,EAAE,EACzB,OAAO,EAAE,cAAc,GACtB,MAAM,CA2FR"}
@@ -0,0 +1,294 @@
1
+ import path from 'node:path';
2
+ /**
3
+ * Generate the AppContext.generated.ts source from topologically sorted beans.
4
+ */
5
+ export function generateCode(beans, options) {
6
+ const outputDir = path.dirname(options.outputPath);
7
+ const lines = [];
8
+ // Header
9
+ const versionTag = options.version ? ` v${options.version}` : '';
10
+ const timestamp = new Date().toISOString();
11
+ lines.push(`// AppContext.generated.ts — DO NOT EDIT (generated by @goodie-ts/transformer${versionTag} at ${timestamp})`);
12
+ lines.push("import { ApplicationContext, Goodie } from '@goodie-ts/core'");
13
+ lines.push("import type { BeanDefinition, Dependency } from '@goodie-ts/core'");
14
+ // Collect unique class imports and injection tokens
15
+ const classImports = collectClassImports(beans);
16
+ const injectionTokens = collectInjectionTokens(beans);
17
+ // Build collision-safe tokenName → varName mapping
18
+ const tokenVarNameMap = buildTokenVarNameMap(injectionTokens);
19
+ const resolveTokenRef = (ref) => {
20
+ if (ref.kind === 'class')
21
+ return ref.className;
22
+ return tokenVarNameMap.get(ref.tokenName) ?? tokenVarName(ref.tokenName);
23
+ };
24
+ if (injectionTokens.length > 0) {
25
+ lines.push("import { InjectionToken } from '@goodie-ts/core'");
26
+ }
27
+ // Class imports
28
+ for (const [className, importPath] of classImports) {
29
+ const relativePath = computeRelativeImport(outputDir, importPath);
30
+ lines.push(`import { ${className} } from '${relativePath}'`);
31
+ }
32
+ // Type-only imports for types referenced in token generics
33
+ const typeOnlyImports = collectTypeOnlyImports(beans, classImports, outputDir);
34
+ for (const [typeName, importSpec] of typeOnlyImports) {
35
+ lines.push(`import type { ${typeName} } from '${importSpec}'`);
36
+ }
37
+ lines.push('');
38
+ // InjectionToken declarations (exported + typed)
39
+ for (const token of injectionTokens) {
40
+ const varName = tokenVarNameMap.get(token.tokenName);
41
+ const typeParam = token.typeAnnotation ?? 'unknown';
42
+ lines.push(`export const ${varName} = new InjectionToken<${typeParam}>('${token.tokenName}')`);
43
+ }
44
+ if (injectionTokens.length > 0) {
45
+ lines.push('');
46
+ }
47
+ // Bean definitions array
48
+ lines.push('const definitions: BeanDefinition[] = [');
49
+ for (const bean of beans) {
50
+ lines.push(' {');
51
+ lines.push(` token: ${resolveTokenRef(bean.tokenRef)},`);
52
+ lines.push(` scope: '${bean.scope}',`);
53
+ lines.push(` dependencies: ${depsToCode(bean, resolveTokenRef)},`);
54
+ lines.push(` factory: ${factoryToCode(bean)},`);
55
+ lines.push(` eager: ${bean.eager},`);
56
+ lines.push(` metadata: ${metadataToCode(bean.metadata)},`);
57
+ lines.push(' },');
58
+ }
59
+ lines.push(']');
60
+ lines.push('');
61
+ // createContext function
62
+ lines.push('export async function createContext(): Promise<ApplicationContext> {');
63
+ lines.push(' return ApplicationContext.create(definitions)');
64
+ lines.push('}');
65
+ lines.push('');
66
+ lines.push('export { definitions }');
67
+ lines.push('');
68
+ lines.push('export const app = Goodie.build(definitions)');
69
+ lines.push('');
70
+ return lines.join('\n');
71
+ }
72
+ /** Collect unique class imports: Map<className, absoluteImportPath> */
73
+ function collectClassImports(beans) {
74
+ const imports = new Map();
75
+ for (const bean of beans) {
76
+ addClassImport(imports, bean.tokenRef);
77
+ for (const dep of bean.constructorDeps) {
78
+ addClassImport(imports, dep.tokenRef);
79
+ }
80
+ for (const field of bean.fieldDeps) {
81
+ addClassImport(imports, field.tokenRef);
82
+ }
83
+ if (bean.providesSource) {
84
+ addClassImport(imports, bean.providesSource.moduleTokenRef);
85
+ }
86
+ }
87
+ return imports;
88
+ }
89
+ function addClassImport(imports, ref) {
90
+ if (ref.kind === 'class') {
91
+ imports.set(ref.className, ref.importPath);
92
+ }
93
+ }
94
+ /** Collect unique auto-generated InjectionTokens with their type info. */
95
+ function collectInjectionTokens(beans) {
96
+ const seen = new Map();
97
+ function add(ref) {
98
+ if (ref.kind !== 'injection-token')
99
+ return;
100
+ if (seen.has(ref.tokenName))
101
+ return;
102
+ seen.set(ref.tokenName, {
103
+ tokenName: ref.tokenName,
104
+ typeAnnotation: ref.typeAnnotation,
105
+ });
106
+ }
107
+ for (const bean of beans) {
108
+ add(bean.tokenRef);
109
+ for (const dep of bean.constructorDeps)
110
+ add(dep.tokenRef);
111
+ for (const field of bean.fieldDeps)
112
+ add(field.tokenRef);
113
+ }
114
+ return [...seen.values()];
115
+ }
116
+ /**
117
+ * Collect type-only imports needed for token generic type annotations.
118
+ * Uses the typeImports map from InjectionTokenRefs to find the correct
119
+ * source file for each type.
120
+ */
121
+ function collectTypeOnlyImports(beans, classImports, outputDir) {
122
+ const typeImports = new Map();
123
+ // Collect all InjectionTokenRefs that have type imports
124
+ for (const bean of beans) {
125
+ addTypeImports(bean.tokenRef);
126
+ for (const dep of bean.constructorDeps)
127
+ addTypeImports(dep.tokenRef);
128
+ for (const field of bean.fieldDeps)
129
+ addTypeImports(field.tokenRef);
130
+ }
131
+ function addTypeImports(ref) {
132
+ if (ref.kind !== 'injection-token')
133
+ return;
134
+ if (!ref.typeImports)
135
+ return;
136
+ for (const [typeName, absolutePath] of ref.typeImports) {
137
+ if (classImports.has(typeName))
138
+ continue;
139
+ if (typeImports.has(typeName))
140
+ continue;
141
+ const relativePath = computeRelativeImport(outputDir, absolutePath);
142
+ typeImports.set(typeName, relativePath);
143
+ }
144
+ }
145
+ return typeImports;
146
+ }
147
+ /**
148
+ * Build a Map<tokenName, uniqueVarName> with collision detection.
149
+ * When two different tokenNames produce the same varName, append _2, _3, etc.
150
+ */
151
+ function buildTokenVarNameMap(tokens) {
152
+ const result = new Map();
153
+ // Track varName → how many times it's been assigned (for suffix generation)
154
+ const varNameCounts = new Map();
155
+ for (const token of tokens) {
156
+ const baseVarName = tokenVarName(token.tokenName);
157
+ const count = varNameCounts.get(baseVarName) ?? 0;
158
+ if (count === 0) {
159
+ result.set(token.tokenName, baseVarName);
160
+ }
161
+ else {
162
+ result.set(token.tokenName, `${baseVarName}_${count + 1}`);
163
+ }
164
+ varNameCounts.set(baseVarName, count + 1);
165
+ }
166
+ return result;
167
+ }
168
+ /**
169
+ * Generate the exported variable name for a token in Pascal_Snake_Case.
170
+ * E.g. 'Repository<User>' → 'Repository_User_Token'
171
+ * 'appName' → 'App_Name_Token'
172
+ * 'dbUrl' → 'Db_Url_Token'
173
+ * 'port' → 'Port_Token'
174
+ */
175
+ function tokenVarName(tokenName) {
176
+ // 1. Replace generic chars with underscores
177
+ const sanitized = tokenName.replace(/[<>, ]/g, '_');
178
+ // 2. Split on underscores, filter empty segments
179
+ const segments = sanitized.split('_').filter(Boolean);
180
+ // 3. Split camelCase within each segment, capitalize each word
181
+ const words = segments.flatMap((seg) => seg
182
+ .replace(/([a-z])([A-Z])/g, '$1_$2')
183
+ .split('_')
184
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1)));
185
+ return [...words, 'Token'].join('_');
186
+ }
187
+ /** Convert all dependencies of a bean (constructor + field) to code. */
188
+ function depsToCode(bean, resolveTokenRef) {
189
+ const allDeps = [
190
+ ...bean.constructorDeps.map((d) => ({
191
+ token: resolveTokenRef(d.tokenRef),
192
+ optional: d.optional,
193
+ })),
194
+ ...bean.fieldDeps.map((f) => ({
195
+ token: resolveTokenRef(f.tokenRef),
196
+ optional: f.optional,
197
+ })),
198
+ ];
199
+ if (allDeps.length === 0)
200
+ return '[]';
201
+ const items = allDeps.map((d) => `{ token: ${d.token}, optional: ${d.optional} }`);
202
+ return `[${items.join(', ')}]`;
203
+ }
204
+ /** Generate the factory function code for a bean. */
205
+ function factoryToCode(bean) {
206
+ if (bean.factoryKind === 'provides') {
207
+ return providesFactoryToCode(bean);
208
+ }
209
+ return constructorFactoryToCode(bean);
210
+ }
211
+ function constructorFactoryToCode(bean) {
212
+ const className = bean.tokenRef.kind === 'class'
213
+ ? bean.tokenRef.className
214
+ : bean.tokenRef.tokenName;
215
+ const ctorParams = bean.constructorDeps.map((_, i) => `dep${i}`);
216
+ const allParams = [...ctorParams];
217
+ const fieldParams = bean.fieldDeps.map((_, i) => `field${i}`);
218
+ allParams.push(...fieldParams);
219
+ if (allParams.length === 0 && bean.fieldDeps.length === 0) {
220
+ return `() => new ${className}()`;
221
+ }
222
+ const paramList = allParams.map((p) => `${p}: any`).join(', ');
223
+ const ctorArgs = ctorParams.join(', ');
224
+ if (bean.fieldDeps.length === 0) {
225
+ return `(${paramList}) => new ${className}(${ctorArgs})`;
226
+ }
227
+ // Constructor + field injection
228
+ const fieldAssignments = bean.fieldDeps
229
+ .map((f, i) => ` instance.${f.fieldName} = field${i}`)
230
+ .join('\n');
231
+ return `(${paramList}) => {
232
+ const instance = new ${className}(${ctorArgs})
233
+ ${fieldAssignments}
234
+ return instance
235
+ }`;
236
+ }
237
+ function providesFactoryToCode(bean) {
238
+ if (!bean.providesSource)
239
+ return '() => { throw new Error("missing provides source") }';
240
+ const { moduleTokenRef, methodName } = bean.providesSource;
241
+ // First dep is always the module instance
242
+ const params = bean.constructorDeps.map((_, i) => `dep${i}: any`);
243
+ const args = bean.constructorDeps.slice(1).map((_, i) => `dep${i + 1}`);
244
+ const paramList = params.join(', ');
245
+ const argList = args.join(', ');
246
+ return `(${paramList}) => (dep0 as ${moduleTokenRef.className}).${methodName}(${argList})`;
247
+ }
248
+ function metadataToCode(metadata) {
249
+ const entries = Object.entries(metadata);
250
+ if (entries.length === 0)
251
+ return '{}';
252
+ const items = entries.map(([k, v]) => `${k}: ${JSON.stringify(v)}`);
253
+ return `{ ${items.join(', ')} }`;
254
+ }
255
+ /** Compute a relative import path from the output dir to the target file, with .js extension. */
256
+ function computeRelativeImport(outputDir, absolutePath) {
257
+ // Handle node_modules paths → extract bare package specifier
258
+ if (absolutePath.includes('node_modules')) {
259
+ return extractPackageName(absolutePath);
260
+ }
261
+ let relative = path.relative(outputDir, absolutePath);
262
+ // Replace .ts extension with .js
263
+ relative = relative.replace(/\.tsx?$/, '.js');
264
+ // Ensure it starts with ./
265
+ if (!relative.startsWith('.')) {
266
+ relative = `./${relative}`;
267
+ }
268
+ return relative;
269
+ }
270
+ /**
271
+ * Extract a bare package name from a node_modules path.
272
+ * E.g. '/project/node_modules/pg/lib/index.d.ts' → 'pg'
273
+ * '/project/node_modules/@types/pg/index.d.ts' → 'pg'
274
+ * '/project/node_modules/@scope/pkg/lib/index.d.ts' → '@scope/pkg'
275
+ */
276
+ function extractPackageName(absolutePath) {
277
+ const segments = absolutePath.split('/node_modules/');
278
+ const afterNodeModules = segments[segments.length - 1];
279
+ const parts = afterNodeModules.split('/');
280
+ let packageName;
281
+ if (parts[0].startsWith('@')) {
282
+ // Scoped package: @scope/name
283
+ packageName = `${parts[0]}/${parts[1]}`;
284
+ }
285
+ else {
286
+ packageName = parts[0];
287
+ }
288
+ // Strip @types/ prefix (e.g. @types/pg → pg)
289
+ if (packageName.startsWith('@types/')) {
290
+ packageName = packageName.slice('@types/'.length);
291
+ }
292
+ return packageName;
293
+ }
294
+ //# sourceMappingURL=codegen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codegen.js","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { IRBeanDefinition } from './ir.js';
2
+ import type { ResolveResult } from './resolver.js';
3
+ /** Result of the graph builder stage. */
4
+ export interface GraphResult {
5
+ /** Bean definitions in topological order (dependencies before dependents). */
6
+ beans: IRBeanDefinition[];
7
+ warnings: string[];
8
+ }
9
+ /**
10
+ * Build a full dependency graph from resolved IR, expand modules,
11
+ * validate, and return beans in topological order.
12
+ */
13
+ export declare function buildGraph(resolveResult: ResolveResult): GraphResult;
14
+ //# sourceMappingURL=graph-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-builder.d.ts","sourceRoot":"","sources":["../src/graph-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAIjB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAOnD,yCAAyC;AACzC,MAAM,WAAW,WAAW;IAC1B,8EAA8E;IAC9E,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,aAAa,EAAE,aAAa,GAAG,WAAW,CAkBpE"}
@@ -0,0 +1,264 @@
1
+ import { AmbiguousProviderError, CircularDependencyError, MissingProviderError, } from './transformer-errors.js';
2
+ /**
3
+ * Build a full dependency graph from resolved IR, expand modules,
4
+ * validate, and return beans in topological order.
5
+ */
6
+ export function buildGraph(resolveResult) {
7
+ const warnings = [...resolveResult.warnings];
8
+ const allBeans = [...resolveResult.beans];
9
+ // Expand modules: register the module class itself + each @Provides as a bean
10
+ const processedModules = new Set();
11
+ expandModules(resolveResult.modules, allBeans, processedModules);
12
+ // Build name-based lookup for @Named → @Inject('name') matching
13
+ resolveNamedQualifiers(allBeans, warnings);
14
+ // Validate: no missing providers (except optional)
15
+ validateProviders(allBeans);
16
+ // Topological sort with cycle detection
17
+ const sorted = topoSort(allBeans);
18
+ return { beans: sorted, warnings };
19
+ }
20
+ /**
21
+ * Recursively expand modules: register the module class as a singleton,
22
+ * and each @Provides method as a separate bean.
23
+ */
24
+ function expandModules(modules, allBeans, processed) {
25
+ for (const mod of modules) {
26
+ const key = tokenRefKey(mod.classTokenRef);
27
+ if (processed.has(key))
28
+ continue;
29
+ processed.add(key);
30
+ // Register the module class itself as an implicit singleton
31
+ allBeans.push({
32
+ tokenRef: mod.classTokenRef,
33
+ scope: 'singleton',
34
+ eager: false,
35
+ name: undefined,
36
+ constructorDeps: [],
37
+ fieldDeps: [],
38
+ factoryKind: 'constructor',
39
+ providesSource: undefined,
40
+ metadata: { isModule: true },
41
+ sourceLocation: mod.sourceLocation,
42
+ });
43
+ // Register each @Provides method as a separate bean
44
+ for (const provides of mod.provides) {
45
+ // Module instance is the implicit first dependency
46
+ const moduleDep = {
47
+ tokenRef: mod.classTokenRef,
48
+ optional: false,
49
+ sourceLocation: provides.sourceLocation,
50
+ };
51
+ allBeans.push({
52
+ tokenRef: provides.tokenRef,
53
+ scope: provides.scope,
54
+ eager: provides.eager,
55
+ name: undefined,
56
+ constructorDeps: [moduleDep, ...provides.dependencies],
57
+ fieldDeps: [],
58
+ factoryKind: 'provides',
59
+ providesSource: {
60
+ moduleTokenRef: mod.classTokenRef,
61
+ methodName: provides.methodName,
62
+ },
63
+ metadata: {},
64
+ sourceLocation: provides.sourceLocation,
65
+ });
66
+ }
67
+ // Note: transitive module imports would be expanded here in Phase 3
68
+ // For now we support flat imports only
69
+ }
70
+ }
71
+ /**
72
+ * Resolve @Inject('name') field deps by matching against @Named beans.
73
+ * Rewrites the tokenRef on matching field injections.
74
+ */
75
+ function resolveNamedQualifiers(beans, _warnings) {
76
+ // Build lookup: name → bean tokenRef
77
+ const namedBeans = new Map();
78
+ for (const bean of beans) {
79
+ if (bean.name) {
80
+ const existing = namedBeans.get(bean.name) ?? [];
81
+ existing.push(bean);
82
+ namedBeans.set(bean.name, existing);
83
+ }
84
+ }
85
+ // Rewrite field injection tokenRefs that reference a named qualifier
86
+ for (const bean of beans) {
87
+ for (const field of bean.fieldDeps) {
88
+ if (field.tokenRef.kind !== 'injection-token')
89
+ continue;
90
+ const candidates = namedBeans.get(field.tokenRef.tokenName);
91
+ if (candidates && candidates.length === 1) {
92
+ field.tokenRef = candidates[0].tokenRef;
93
+ }
94
+ else if (candidates && candidates.length > 1) {
95
+ const _ownerName = bean.tokenRef.kind === 'class'
96
+ ? bean.tokenRef.className
97
+ : bean.tokenRef.tokenName;
98
+ throw new AmbiguousProviderError(field.tokenRef.tokenName, candidates.map((c) => c.tokenRef.kind === 'class'
99
+ ? c.tokenRef.className
100
+ : c.tokenRef.tokenName), bean.sourceLocation);
101
+ }
102
+ }
103
+ }
104
+ }
105
+ /** Validate that all required dependencies have a registered provider. */
106
+ function validateProviders(beans) {
107
+ const registered = new Set();
108
+ for (const bean of beans) {
109
+ registered.add(tokenRefKey(bean.tokenRef));
110
+ }
111
+ // Build subtype map: baseTokenKey → subtypes (beans that extend that base class)
112
+ // Uses all ancestors, so C extends B extends A produces entries for both B→[C] and A→[C]
113
+ const subtypeMap = new Map();
114
+ for (const bean of beans) {
115
+ if (bean.baseTokenRefs) {
116
+ for (const baseRef of bean.baseTokenRefs) {
117
+ const baseKey = tokenRefKey(baseRef);
118
+ const existing = subtypeMap.get(baseKey) ?? [];
119
+ existing.push(bean);
120
+ subtypeMap.set(baseKey, existing);
121
+ }
122
+ }
123
+ }
124
+ // Rewrite unresolved deps via subtype map before validation
125
+ for (const bean of beans) {
126
+ for (const dep of bean.constructorDeps) {
127
+ rewriteDepViaSubtype(dep, registered, subtypeMap, bean);
128
+ }
129
+ for (const field of bean.fieldDeps) {
130
+ rewriteFieldDepViaSubtype(field, registered, subtypeMap, bean);
131
+ }
132
+ }
133
+ // Now validate all required deps have providers
134
+ for (const bean of beans) {
135
+ const ownerName = bean.tokenRef.kind === 'class'
136
+ ? bean.tokenRef.className
137
+ : bean.tokenRef.tokenName;
138
+ for (const dep of bean.constructorDeps) {
139
+ if (dep.optional)
140
+ continue;
141
+ const key = tokenRefKey(dep.tokenRef);
142
+ if (!registered.has(key)) {
143
+ const depName = dep.tokenRef.kind === 'class'
144
+ ? dep.tokenRef.className
145
+ : dep.tokenRef.tokenName;
146
+ throw new MissingProviderError(depName, ownerName, dep.sourceLocation);
147
+ }
148
+ }
149
+ for (const field of bean.fieldDeps) {
150
+ if (field.optional)
151
+ continue;
152
+ const key = tokenRefKey(field.tokenRef);
153
+ if (!registered.has(key)) {
154
+ const depName = field.tokenRef.kind === 'class'
155
+ ? field.tokenRef.className
156
+ : field.tokenRef.tokenName;
157
+ throw new MissingProviderError(depName, ownerName, bean.sourceLocation);
158
+ }
159
+ }
160
+ }
161
+ }
162
+ /**
163
+ * If a dependency has no direct provider but exactly one subtype provides it,
164
+ * rewrite the tokenRef to point at the subtype. Multiple candidates → ambiguous.
165
+ */
166
+ function rewriteDepViaSubtype(dep, registered, subtypeMap, ownerBean) {
167
+ const key = tokenRefKey(dep.tokenRef);
168
+ if (registered.has(key))
169
+ return;
170
+ const subtypes = subtypeMap.get(key);
171
+ if (!subtypes || subtypes.length === 0)
172
+ return;
173
+ if (subtypes.length === 1) {
174
+ dep.tokenRef = subtypes[0].tokenRef;
175
+ }
176
+ else {
177
+ throw new AmbiguousProviderError(dep.tokenRef.kind === 'class'
178
+ ? dep.tokenRef.className
179
+ : dep.tokenRef.tokenName, subtypes.map((s) => s.tokenRef.kind === 'class'
180
+ ? s.tokenRef.className
181
+ : s.tokenRef.tokenName), ownerBean.sourceLocation);
182
+ }
183
+ }
184
+ function rewriteFieldDepViaSubtype(field, registered, subtypeMap, ownerBean) {
185
+ const key = tokenRefKey(field.tokenRef);
186
+ if (registered.has(key))
187
+ return;
188
+ const subtypes = subtypeMap.get(key);
189
+ if (!subtypes || subtypes.length === 0)
190
+ return;
191
+ if (subtypes.length === 1) {
192
+ field.tokenRef = subtypes[0].tokenRef;
193
+ }
194
+ else {
195
+ throw new AmbiguousProviderError(field.tokenRef.kind === 'class'
196
+ ? field.tokenRef.className
197
+ : field.tokenRef.tokenName, subtypes.map((s) => s.tokenRef.kind === 'class'
198
+ ? s.tokenRef.className
199
+ : s.tokenRef.tokenName), ownerBean.sourceLocation);
200
+ }
201
+ }
202
+ // ── Topological sort with source-location-enriched cycle errors ──
203
+ function topoSort(beans) {
204
+ // Map tokenRef key → bean definition
205
+ const beanMap = new Map();
206
+ for (const bean of beans) {
207
+ beanMap.set(tokenRefKey(bean.tokenRef), bean);
208
+ }
209
+ const sorted = [];
210
+ const visited = new Set();
211
+ const visiting = new Set();
212
+ const path = [];
213
+ function visit(bean) {
214
+ const key = tokenRefKey(bean.tokenRef);
215
+ if (visited.has(key))
216
+ return;
217
+ if (visiting.has(key)) {
218
+ // Cycle detected — build the cycle path from the current stack
219
+ const name = tokenRefDisplayName(bean.tokenRef);
220
+ const cycleStart = path.indexOf(name);
221
+ const cyclePath = [...path.slice(cycleStart), name];
222
+ throw new CircularDependencyError(cyclePath, bean.sourceLocation);
223
+ }
224
+ visiting.add(key);
225
+ path.push(tokenRefDisplayName(bean.tokenRef));
226
+ // Visit all dependencies
227
+ for (const dep of getAllDependencies(bean)) {
228
+ const depKey = tokenRefKey(dep.tokenRef);
229
+ const depBean = beanMap.get(depKey);
230
+ if (depBean) {
231
+ visit(depBean);
232
+ }
233
+ // Missing optional deps are already validated — skip silently
234
+ }
235
+ path.pop();
236
+ visiting.delete(key);
237
+ visited.add(key);
238
+ sorted.push(bean);
239
+ }
240
+ for (const bean of beans) {
241
+ visit(bean);
242
+ }
243
+ return sorted;
244
+ }
245
+ /** Get all dependencies of a bean (constructor + field). */
246
+ function getAllDependencies(bean) {
247
+ return [
248
+ ...bean.constructorDeps,
249
+ ...bean.fieldDeps.map((f) => ({ tokenRef: f.tokenRef })),
250
+ ];
251
+ }
252
+ /** Stable key for a TokenRef for use in Maps/Sets. */
253
+ function tokenRefKey(ref) {
254
+ if (ref.kind === 'class') {
255
+ return `class:${ref.importPath}:${ref.className}`;
256
+ }
257
+ return `token:${ref.tokenName}:${ref.importPath ?? ''}`;
258
+ }
259
+ function tokenRefDisplayName(ref) {
260
+ if (ref.kind === 'class')
261
+ return ref.className;
262
+ return ref.tokenName;
263
+ }
264
+ //# sourceMappingURL=graph-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-builder.js","sourceRoot":"","sources":["../src/graph-builder.ts"],"names":[],"mappings":"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"}