@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.
@@ -0,0 +1,386 @@
1
+ import { SyntaxKind, } from 'ts-morph';
2
+ import { InvalidDecoratorUsageError } from './transformer-errors.js';
3
+ /** Names of decorators we recognize from @goodie-ts/decorators. */
4
+ const DECORATOR_NAMES = {
5
+ Injectable: 'Injectable',
6
+ Singleton: 'Singleton',
7
+ Named: 'Named',
8
+ Eager: 'Eager',
9
+ Module: 'Module',
10
+ Provides: 'Provides',
11
+ Inject: 'Inject',
12
+ Optional: 'Optional',
13
+ PreDestroy: 'PreDestroy',
14
+ };
15
+ /** Scan a ts-morph Project for decorated classes. */
16
+ export function scan(project) {
17
+ const beans = [];
18
+ const modules = [];
19
+ const warnings = [];
20
+ for (const sourceFile of project.getSourceFiles()) {
21
+ for (const cls of sourceFile.getClasses()) {
22
+ const decorators = cls.getDecorators();
23
+ if (decorators.length === 0)
24
+ continue;
25
+ const isModule = hasDecorator(decorators, DECORATOR_NAMES.Module);
26
+ const isInjectable = hasDecorator(decorators, DECORATOR_NAMES.Injectable);
27
+ const isSingleton = hasDecorator(decorators, DECORATOR_NAMES.Singleton);
28
+ if ((isModule || isInjectable || isSingleton) && cls.isAbstract()) {
29
+ const decoratorName = isModule
30
+ ? 'Module'
31
+ : isSingleton
32
+ ? 'Singleton'
33
+ : 'Injectable';
34
+ throw new InvalidDecoratorUsageError(decoratorName, `Cannot apply @${decoratorName}() to abstract class "${cls.getName()}". Abstract classes cannot be instantiated. Remove the decorator or make the class concrete.`, getSourceLocation(cls, sourceFile));
35
+ }
36
+ if (isModule) {
37
+ const scannedModule = scanModule(cls, decorators, sourceFile);
38
+ if (scannedModule)
39
+ modules.push(scannedModule);
40
+ }
41
+ else if (isInjectable || isSingleton) {
42
+ const scannedBean = scanBean(cls, decorators, sourceFile, isSingleton);
43
+ if (scannedBean)
44
+ beans.push(scannedBean);
45
+ }
46
+ }
47
+ }
48
+ return { beans, modules, warnings };
49
+ }
50
+ function scanBean(cls, decorators, sourceFile, isSingleton) {
51
+ const className = cls.getName();
52
+ if (!className)
53
+ return undefined;
54
+ const scope = isSingleton ? 'singleton' : 'prototype';
55
+ const eager = hasDecorator(decorators, DECORATOR_NAMES.Eager);
56
+ const name = getNamedValue(decorators);
57
+ const constructorParams = scanConstructorParams(cls);
58
+ const fieldInjections = scanFieldInjections(cls);
59
+ const preDestroyMethods = scanPreDestroyMethods(cls);
60
+ const baseClasses = extractBaseClassChain(cls);
61
+ return {
62
+ classDeclaration: cls,
63
+ classTokenRef: {
64
+ kind: 'class',
65
+ className,
66
+ importPath: sourceFile.getFilePath(),
67
+ },
68
+ scope,
69
+ eager,
70
+ name,
71
+ constructorParams,
72
+ fieldInjections,
73
+ preDestroyMethods,
74
+ baseClasses,
75
+ sourceLocation: getSourceLocation(cls, sourceFile),
76
+ };
77
+ }
78
+ function scanModule(cls, decorators, sourceFile) {
79
+ const className = cls.getName();
80
+ if (!className)
81
+ return undefined;
82
+ const moduleDecorator = findDecorator(decorators, DECORATOR_NAMES.Module);
83
+ const imports = getModuleImports(moduleDecorator);
84
+ const provides = scanProvidesMethods(cls, sourceFile);
85
+ return {
86
+ classDeclaration: cls,
87
+ classTokenRef: {
88
+ kind: 'class',
89
+ className,
90
+ importPath: sourceFile.getFilePath(),
91
+ },
92
+ imports,
93
+ provides,
94
+ sourceLocation: getSourceLocation(cls, sourceFile),
95
+ };
96
+ }
97
+ function scanConstructorParams(cls) {
98
+ const ctor = cls.getConstructors()[0];
99
+ if (!ctor)
100
+ return [];
101
+ return ctor.getParameters().map((param) => {
102
+ const typeNode = param.getTypeNode();
103
+ let typeName;
104
+ let typeSourceFile;
105
+ let typeArguments = [];
106
+ let resolvedBaseTypeName;
107
+ if (typeNode) {
108
+ typeName = typeNode.getText();
109
+ const paramType = param.getType();
110
+ const typeSymbol = paramType.getSymbol();
111
+ if (typeSymbol) {
112
+ const decls = typeSymbol.getDeclarations();
113
+ if (decls.length > 0) {
114
+ typeSourceFile = decls[0].getSourceFile();
115
+ }
116
+ resolvedBaseTypeName = typeSymbol.getName();
117
+ }
118
+ typeArguments = extractTypeArguments(paramType);
119
+ }
120
+ return {
121
+ paramName: param.getName(),
122
+ typeName,
123
+ typeSourceFile,
124
+ typeArguments,
125
+ resolvedBaseTypeName,
126
+ sourceLocation: getSourceLocation(param, param.getSourceFile()),
127
+ };
128
+ });
129
+ }
130
+ function scanFieldInjections(cls) {
131
+ const results = [];
132
+ for (const prop of cls.getProperties()) {
133
+ const decorators = prop.getDecorators();
134
+ const injectDec = findDecorator(decorators, DECORATOR_NAMES.Inject);
135
+ const optionalDec = findDecorator(decorators, DECORATOR_NAMES.Optional);
136
+ if (!injectDec && !optionalDec)
137
+ continue;
138
+ const hasAccessor = prop.hasAccessorKeyword?.() ?? false;
139
+ if (!hasAccessor && !injectDec && !optionalDec)
140
+ continue;
141
+ let qualifier;
142
+ if (injectDec) {
143
+ const args = injectDec.getArguments();
144
+ if (args.length > 0) {
145
+ const argText = args[0].getText();
146
+ // String literal: 'name' or "name"
147
+ if ((argText.startsWith("'") && argText.endsWith("'")) ||
148
+ (argText.startsWith('"') && argText.endsWith('"'))) {
149
+ qualifier = argText.slice(1, -1);
150
+ }
151
+ else {
152
+ // InjectionToken variable reference — store the identifier text
153
+ qualifier = argText;
154
+ }
155
+ }
156
+ }
157
+ const typeNode = prop.getTypeNode();
158
+ let typeName;
159
+ let typeSourceFile;
160
+ let typeArguments = [];
161
+ let resolvedBaseTypeName;
162
+ if (typeNode) {
163
+ typeName = typeNode.getText();
164
+ const propType = prop.getType();
165
+ const typeSymbol = propType.getSymbol();
166
+ if (typeSymbol) {
167
+ const decls = typeSymbol.getDeclarations();
168
+ if (decls.length > 0) {
169
+ typeSourceFile = decls[0].getSourceFile();
170
+ }
171
+ resolvedBaseTypeName = typeSymbol.getName();
172
+ }
173
+ typeArguments = extractTypeArguments(propType);
174
+ }
175
+ results.push({
176
+ fieldName: String(prop.getName()),
177
+ qualifier,
178
+ optional: optionalDec !== undefined,
179
+ typeName,
180
+ typeSourceFile,
181
+ typeArguments,
182
+ resolvedBaseTypeName,
183
+ sourceLocation: getSourceLocation(prop, prop.getSourceFile()),
184
+ });
185
+ }
186
+ return results;
187
+ }
188
+ function scanProvidesMethods(cls, sourceFile) {
189
+ const results = [];
190
+ for (const method of cls.getMethods()) {
191
+ const decorators = method.getDecorators();
192
+ if (!hasDecorator(decorators, DECORATOR_NAMES.Provides))
193
+ continue;
194
+ const returnTypeNode = method.getReturnTypeNode();
195
+ let returnTypeName;
196
+ let returnTypeSourceFile;
197
+ let returnTypeArguments = [];
198
+ let returnResolvedBaseTypeName;
199
+ if (returnTypeNode) {
200
+ returnTypeName = returnTypeNode.getText();
201
+ const returnType = method.getReturnType();
202
+ const typeSymbol = returnType.getSymbol();
203
+ if (typeSymbol) {
204
+ const decls = typeSymbol.getDeclarations();
205
+ if (decls.length > 0) {
206
+ returnTypeSourceFile = decls[0].getSourceFile();
207
+ }
208
+ returnResolvedBaseTypeName = typeSymbol.getName();
209
+ }
210
+ returnTypeArguments = extractTypeArguments(returnType);
211
+ }
212
+ const params = method.getParameters().map((param) => {
213
+ const typeNode = param.getTypeNode();
214
+ let typeName;
215
+ let typeSourceFile;
216
+ let typeArguments = [];
217
+ let resolvedBaseTypeName;
218
+ if (typeNode) {
219
+ typeName = typeNode.getText();
220
+ const paramType = param.getType();
221
+ const typeSymbol = paramType.getSymbol();
222
+ if (typeSymbol) {
223
+ const decls = typeSymbol.getDeclarations();
224
+ if (decls.length > 0) {
225
+ typeSourceFile = decls[0].getSourceFile();
226
+ }
227
+ resolvedBaseTypeName = typeSymbol.getName();
228
+ }
229
+ typeArguments = extractTypeArguments(paramType);
230
+ }
231
+ return {
232
+ paramName: param.getName(),
233
+ typeName,
234
+ typeSourceFile,
235
+ typeArguments,
236
+ resolvedBaseTypeName,
237
+ sourceLocation: getSourceLocation(param, param.getSourceFile()),
238
+ };
239
+ });
240
+ results.push({
241
+ methodName: method.getName(),
242
+ returnTypeName,
243
+ returnTypeSourceFile,
244
+ returnTypeArguments,
245
+ returnResolvedBaseTypeName,
246
+ params,
247
+ sourceLocation: getSourceLocation(method, sourceFile),
248
+ });
249
+ }
250
+ return results;
251
+ }
252
+ // ── @PreDestroy scanning ──
253
+ function scanPreDestroyMethods(cls) {
254
+ const methods = [];
255
+ for (const method of cls.getMethods()) {
256
+ const decorators = method.getDecorators();
257
+ if (hasDecorator(decorators, DECORATOR_NAMES.PreDestroy)) {
258
+ methods.push(method.getName());
259
+ }
260
+ }
261
+ return methods;
262
+ }
263
+ // ── Base class extraction ──
264
+ /**
265
+ * Walk the full inheritance chain and return all ancestor classes
266
+ * (direct parent first, root last).
267
+ */
268
+ function extractBaseClassChain(cls) {
269
+ const result = [];
270
+ const seen = new Set();
271
+ let current = cls;
272
+ while (current) {
273
+ const extendsExpr = current.getExtends();
274
+ if (!extendsExpr)
275
+ break;
276
+ const baseType = extendsExpr.getType();
277
+ const symbol = baseType.getSymbol();
278
+ if (!symbol)
279
+ break;
280
+ const className = symbol.getName();
281
+ if (seen.has(className))
282
+ break; // guard against cycles
283
+ seen.add(className);
284
+ let sourceFile;
285
+ const decls = symbol.getDeclarations();
286
+ if (decls.length > 0) {
287
+ sourceFile = decls[0].getSourceFile();
288
+ }
289
+ result.push({ className, sourceFile });
290
+ // Try to get the ClassDeclaration for the parent to continue walking
291
+ const parentDecl = decls.find((d) => d.getKindName() === 'ClassDeclaration');
292
+ current = parentDecl;
293
+ }
294
+ return result;
295
+ }
296
+ // ── Generic type helpers ──
297
+ /** Extract type arguments from a ts-morph Type, recursively for nested generics. */
298
+ function extractTypeArguments(type) {
299
+ const typeArgs = type.getTypeArguments();
300
+ if (typeArgs.length === 0)
301
+ return [];
302
+ return typeArgs.map((arg) => {
303
+ const symbol = arg.getSymbol();
304
+ let typeSourceFile;
305
+ if (symbol) {
306
+ const decls = symbol.getDeclarations();
307
+ if (decls.length > 0) {
308
+ typeSourceFile = decls[0].getSourceFile();
309
+ }
310
+ }
311
+ return {
312
+ typeName: symbol?.getName() ?? arg.getText(),
313
+ typeSourceFile,
314
+ typeArguments: extractTypeArguments(arg),
315
+ };
316
+ });
317
+ }
318
+ // ── Decorator helpers ──
319
+ function hasDecorator(decorators, name) {
320
+ return findDecorator(decorators, name) !== undefined;
321
+ }
322
+ function findDecorator(decorators, name) {
323
+ return decorators.find((d) => d.getName() === name);
324
+ }
325
+ function getNamedValue(decorators) {
326
+ const dec = findDecorator(decorators, DECORATOR_NAMES.Named);
327
+ if (!dec)
328
+ return undefined;
329
+ const args = dec.getArguments();
330
+ if (args.length === 0)
331
+ return undefined;
332
+ const text = args[0].getText();
333
+ if ((text.startsWith("'") && text.endsWith("'")) ||
334
+ (text.startsWith('"') && text.endsWith('"'))) {
335
+ return text.slice(1, -1);
336
+ }
337
+ return text;
338
+ }
339
+ function getModuleImports(decorator) {
340
+ const args = decorator.getArguments();
341
+ if (args.length === 0)
342
+ return [];
343
+ const arg = args[0];
344
+ // The argument should be an object literal: { imports: [A, B] }
345
+ if (arg.getKind() !== SyntaxKind.ObjectLiteralExpression)
346
+ return [];
347
+ const objLiteral = arg.asKind(SyntaxKind.ObjectLiteralExpression);
348
+ if (!objLiteral)
349
+ return [];
350
+ const importsProp = objLiteral.getProperty('imports');
351
+ if (!importsProp)
352
+ return [];
353
+ const initializer = importsProp
354
+ .asKind(SyntaxKind.PropertyAssignment)
355
+ ?.getInitializer();
356
+ if (!initializer ||
357
+ initializer.getKind() !== SyntaxKind.ArrayLiteralExpression)
358
+ return [];
359
+ const arrayLiteral = initializer.asKind(SyntaxKind.ArrayLiteralExpression);
360
+ if (!arrayLiteral)
361
+ return [];
362
+ return arrayLiteral.getElements().map((element) => {
363
+ const text = element.getText();
364
+ const symbol = element.getType().getSymbol();
365
+ let sourceFile;
366
+ if (symbol) {
367
+ const decls = symbol.getDeclarations();
368
+ if (decls.length > 0) {
369
+ sourceFile = decls[0].getSourceFile();
370
+ }
371
+ }
372
+ return { className: text, sourceFile };
373
+ });
374
+ }
375
+ // ── Source location ──
376
+ function getSourceLocation(node, sourceFile) {
377
+ const line = node.getStartLineNumber();
378
+ const start = node.getStart();
379
+ const { column } = sourceFile.getLineAndColumnAtPos(start);
380
+ return {
381
+ filePath: sourceFile.getFilePath(),
382
+ line,
383
+ column,
384
+ };
385
+ }
386
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { Project } from 'ts-morph';
2
+ import type { TransformOptions, TransformResult } from './options.js';
3
+ /**
4
+ * Run the full compile-time transform pipeline:
5
+ * Source Files → Scanner → Resolver → Graph Builder → Code Generator → output file
6
+ */
7
+ export declare function transform(options: TransformOptions): TransformResult;
8
+ /**
9
+ * Run the pipeline in-memory without writing to disk.
10
+ * Useful for testing and tooling integration.
11
+ */
12
+ export declare function transformInMemory(project: Project, outputPath: string): TransformResult;
13
+ //# sourceMappingURL=transform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../src/transform.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAGnC,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAStE;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,eAAe,CAqCpE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,GACjB,eAAe,CAejB"}
@@ -0,0 +1,65 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { Project } from 'ts-morph';
5
+ import { generateCode } from './codegen.js';
6
+ import { buildGraph } from './graph-builder.js';
7
+ import { resolve } from './resolver.js';
8
+ import { scan } from './scanner.js';
9
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
+ const PKG_VERSION = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../package.json'), 'utf-8')).version;
11
+ /**
12
+ * Run the full compile-time transform pipeline:
13
+ * Source Files → Scanner → Resolver → Graph Builder → Code Generator → output file
14
+ */
15
+ export function transform(options) {
16
+ // 1. Create ts-morph Project
17
+ const project = new Project({
18
+ tsConfigFilePath: options.tsConfigFilePath,
19
+ });
20
+ // If include patterns are specified, filter source files
21
+ if (options.include && options.include.length > 0) {
22
+ project.addSourceFilesAtPaths(options.include);
23
+ }
24
+ // 2. Scan
25
+ const scanResult = scan(project);
26
+ // 3. Resolve
27
+ const resolveResult = resolve(scanResult);
28
+ // 4. Build graph (validate + topo sort)
29
+ const graphResult = buildGraph(resolveResult);
30
+ // 5. Generate code
31
+ const code = generateCode(graphResult.beans, {
32
+ outputPath: options.outputPath,
33
+ version: PKG_VERSION,
34
+ });
35
+ // 6. Write output
36
+ const outputDir = path.dirname(options.outputPath);
37
+ fs.mkdirSync(outputDir, { recursive: true });
38
+ fs.writeFileSync(options.outputPath, code, 'utf-8');
39
+ return {
40
+ code,
41
+ outputPath: options.outputPath,
42
+ beans: graphResult.beans,
43
+ warnings: graphResult.warnings,
44
+ };
45
+ }
46
+ /**
47
+ * Run the pipeline in-memory without writing to disk.
48
+ * Useful for testing and tooling integration.
49
+ */
50
+ export function transformInMemory(project, outputPath) {
51
+ const scanResult = scan(project);
52
+ const resolveResult = resolve(scanResult);
53
+ const graphResult = buildGraph(resolveResult);
54
+ const code = generateCode(graphResult.beans, {
55
+ outputPath,
56
+ version: PKG_VERSION,
57
+ });
58
+ return {
59
+ code,
60
+ outputPath,
61
+ beans: graphResult.beans,
62
+ warnings: graphResult.warnings,
63
+ };
64
+ }
65
+ //# sourceMappingURL=transform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform.js","sourceRoot":"","sources":["../src/transform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEpC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,MAAM,WAAW,GAAW,IAAI,CAAC,KAAK,CACpC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CACrE,CAAC,OAAO,CAAC;AAEV;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,OAAyB;IACjD,6BAA6B;IAC7B,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC;QAC1B,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;KAC3C,CAAC,CAAC;IAEH,yDAAyD;IACzD,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClD,OAAO,CAAC,qBAAqB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC;IAED,UAAU;IACV,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;IAEjC,aAAa;IACb,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAE1C,wCAAwC;IACxC,MAAM,WAAW,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;IAE9C,mBAAmB;IACnB,MAAM,IAAI,GAAG,YAAY,CAAC,WAAW,CAAC,KAAK,EAAE;QAC3C,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,OAAO,EAAE,WAAW;KACrB,CAAC,CAAC;IAEH,kBAAkB;IAClB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACnD,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAEpD,OAAO;QACL,IAAI;QACJ,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,KAAK,EAAE,WAAW,CAAC,KAAK;QACxB,QAAQ,EAAE,WAAW,CAAC,QAAQ;KAC/B,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAgB,EAChB,UAAkB;IAElB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;IACjC,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,YAAY,CAAC,WAAW,CAAC,KAAK,EAAE;QAC3C,UAAU;QACV,OAAO,EAAE,WAAW;KACrB,CAAC,CAAC;IAEH,OAAO;QACL,IAAI;QACJ,UAAU;QACV,KAAK,EAAE,WAAW,CAAC,KAAK;QACxB,QAAQ,EAAE,WAAW,CAAC,QAAQ;KAC/B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,42 @@
1
+ import type { SourceLocation } from './ir.js';
2
+ /** Base error for all compile-time transformer failures. */
3
+ export declare class TransformerError extends Error {
4
+ readonly sourceLocation: SourceLocation;
5
+ readonly hint: string | undefined;
6
+ constructor(message: string, sourceLocation: SourceLocation, hint: string | undefined);
7
+ }
8
+ /** A required dependency has no registered provider. */
9
+ export declare class MissingProviderError extends TransformerError {
10
+ readonly tokenDescription: string;
11
+ readonly requiredBy: string;
12
+ constructor(tokenDescription: string, requiredBy: string, sourceLocation: SourceLocation);
13
+ }
14
+ /** Multiple providers match a dependency and no qualifier disambiguates. */
15
+ export declare class AmbiguousProviderError extends TransformerError {
16
+ readonly tokenDescription: string;
17
+ readonly candidates: string[];
18
+ constructor(tokenDescription: string, candidates: string[], sourceLocation: SourceLocation);
19
+ }
20
+ /** A constructor parameter or field type cannot be resolved at compile time. */
21
+ export declare class UnresolvableTypeError extends TransformerError {
22
+ readonly typeDescription: string;
23
+ constructor(typeDescription: string, sourceLocation: SourceLocation);
24
+ }
25
+ /** A decorator is used in an unsupported position or combination. */
26
+ export declare class InvalidDecoratorUsageError extends TransformerError {
27
+ readonly decoratorName: string;
28
+ readonly reason: string;
29
+ constructor(decoratorName: string, reason: string, sourceLocation: SourceLocation);
30
+ }
31
+ /** A generic type could not be resolved to a canonical form. */
32
+ export declare class GenericTypeResolutionError extends TransformerError {
33
+ readonly typeName: string;
34
+ readonly reason: string;
35
+ constructor(typeName: string, reason: string, sourceLocation: SourceLocation);
36
+ }
37
+ /** Circular dependency detected at compile time with full cycle path. */
38
+ export declare class CircularDependencyError extends TransformerError {
39
+ readonly cyclePath: string[];
40
+ constructor(cyclePath: string[], sourceLocation: SourceLocation);
41
+ }
42
+ //# sourceMappingURL=transformer-errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transformer-errors.d.ts","sourceRoot":"","sources":["../src/transformer-errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAM9C,4DAA4D;AAC5D,qBAAa,gBAAiB,SAAQ,KAAK;IAGvC,QAAQ,CAAC,cAAc,EAAE,cAAc;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS;gBAFjC,OAAO,EAAE,MAAM,EACN,cAAc,EAAE,cAAc,EAC9B,IAAI,EAAE,MAAM,GAAG,SAAS;CASpC;AAED,wDAAwD;AACxD,qBAAa,oBAAqB,SAAQ,gBAAgB;IAEtD,QAAQ,CAAC,gBAAgB,EAAE,MAAM;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM;gBADlB,gBAAgB,EAAE,MAAM,EACxB,UAAU,EAAE,MAAM,EAC3B,cAAc,EAAE,cAAc;CASjC;AAED,4EAA4E;AAC5E,qBAAa,sBAAuB,SAAQ,gBAAgB;IAExD,QAAQ,CAAC,gBAAgB,EAAE,MAAM;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE;gBADpB,gBAAgB,EAAE,MAAM,EACxB,UAAU,EAAE,MAAM,EAAE,EAC7B,cAAc,EAAE,cAAc;CASjC;AAED,gFAAgF;AAChF,qBAAa,qBAAsB,SAAQ,gBAAgB;IAEvD,QAAQ,CAAC,eAAe,EAAE,MAAM;gBAAvB,eAAe,EAAE,MAAM,EAChC,cAAc,EAAE,cAAc;CASjC;AAED,qEAAqE;AACrE,qBAAa,0BAA2B,SAAQ,gBAAgB;IAE5D,QAAQ,CAAC,aAAa,EAAE,MAAM;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM;gBADd,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,EACvB,cAAc,EAAE,cAAc;CASjC;AAED,gEAAgE;AAChE,qBAAa,0BAA2B,SAAQ,gBAAgB;IAE5D,QAAQ,CAAC,QAAQ,EAAE,MAAM;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM;gBADd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACvB,cAAc,EAAE,cAAc;CASjC;AAED,yEAAyE;AACzE,qBAAa,uBAAwB,SAAQ,gBAAgB;IAEzD,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE;gBAAnB,SAAS,EAAE,MAAM,EAAE,EAC5B,cAAc,EAAE,cAAc;CASjC"}
@@ -0,0 +1,81 @@
1
+ function formatLocation(loc) {
2
+ return `${loc.filePath}:${loc.line}:${loc.column}`;
3
+ }
4
+ /** Base error for all compile-time transformer failures. */
5
+ export class TransformerError extends Error {
6
+ sourceLocation;
7
+ hint;
8
+ constructor(message, sourceLocation, hint) {
9
+ const parts = [message, '', ` ${formatLocation(sourceLocation)}`];
10
+ if (hint) {
11
+ parts.push('', ` ${hint}`);
12
+ }
13
+ super(parts.join('\n'));
14
+ this.sourceLocation = sourceLocation;
15
+ this.hint = hint;
16
+ this.name = 'TransformerError';
17
+ }
18
+ }
19
+ /** A required dependency has no registered provider. */
20
+ export class MissingProviderError extends TransformerError {
21
+ tokenDescription;
22
+ requiredBy;
23
+ constructor(tokenDescription, requiredBy, sourceLocation) {
24
+ super(`No provider found for "${tokenDescription}" (required by ${requiredBy})`, sourceLocation, 'Ensure the dependency is decorated with @Injectable(), @Singleton(), or provided by a @Module.');
25
+ this.tokenDescription = tokenDescription;
26
+ this.requiredBy = requiredBy;
27
+ this.name = 'MissingProviderError';
28
+ }
29
+ }
30
+ /** Multiple providers match a dependency and no qualifier disambiguates. */
31
+ export class AmbiguousProviderError extends TransformerError {
32
+ tokenDescription;
33
+ candidates;
34
+ constructor(tokenDescription, candidates, sourceLocation) {
35
+ super(`Ambiguous provider for "${tokenDescription}": found ${candidates.join(', ')}`, sourceLocation, 'Use @Named() on the providers and @Inject(name) on the injection point to disambiguate.');
36
+ this.tokenDescription = tokenDescription;
37
+ this.candidates = candidates;
38
+ this.name = 'AmbiguousProviderError';
39
+ }
40
+ }
41
+ /** A constructor parameter or field type cannot be resolved at compile time. */
42
+ export class UnresolvableTypeError extends TransformerError {
43
+ typeDescription;
44
+ constructor(typeDescription, sourceLocation) {
45
+ super(`Cannot resolve type "${typeDescription}" at compile time`, sourceLocation, 'Use a concrete class type, or use @Inject(token) on an accessor field for interfaces/primitives.');
46
+ this.typeDescription = typeDescription;
47
+ this.name = 'UnresolvableTypeError';
48
+ }
49
+ }
50
+ /** A decorator is used in an unsupported position or combination. */
51
+ export class InvalidDecoratorUsageError extends TransformerError {
52
+ decoratorName;
53
+ reason;
54
+ constructor(decoratorName, reason, sourceLocation) {
55
+ super(`Invalid usage of @${decoratorName}: ${reason}`, sourceLocation, undefined);
56
+ this.decoratorName = decoratorName;
57
+ this.reason = reason;
58
+ this.name = 'InvalidDecoratorUsageError';
59
+ }
60
+ }
61
+ /** A generic type could not be resolved to a canonical form. */
62
+ export class GenericTypeResolutionError extends TransformerError {
63
+ typeName;
64
+ reason;
65
+ constructor(typeName, reason, sourceLocation) {
66
+ super(`Cannot resolve generic type "${typeName}": ${reason}`, sourceLocation, 'Ensure the generic type has concrete type arguments and the base class is importable.');
67
+ this.typeName = typeName;
68
+ this.reason = reason;
69
+ this.name = 'GenericTypeResolutionError';
70
+ }
71
+ }
72
+ /** Circular dependency detected at compile time with full cycle path. */
73
+ export class CircularDependencyError extends TransformerError {
74
+ cyclePath;
75
+ constructor(cyclePath, sourceLocation) {
76
+ super(`Circular dependency detected: ${cyclePath.join(' → ')}`, sourceLocation, 'Break the cycle by using @Optional() on an accessor field or restructuring your dependencies.');
77
+ this.cyclePath = cyclePath;
78
+ this.name = 'CircularDependencyError';
79
+ }
80
+ }
81
+ //# sourceMappingURL=transformer-errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transformer-errors.js","sourceRoot":"","sources":["../src/transformer-errors.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@goodie-ts/transformer",
3
+ "version": "0.1.0",
4
+ "description": "Compile-time TypeScript transformer for goodie-ts dependency injection",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/GOOD-Code-ApS/goodie.git",
10
+ "directory": "packages/transformer"
11
+ },
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
15
+ "main": "dist/index.js",
16
+ "types": "dist/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "import": "./dist/index.js"
21
+ }
22
+ },
23
+ "dependencies": {
24
+ "ts-morph": "^24.0.0",
25
+ "@goodie-ts/core": "0.1.0"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^22.0.0"
29
+ },
30
+ "files": [
31
+ "dist"
32
+ ],
33
+ "scripts": {
34
+ "build": "tsc",
35
+ "clean": "rm -rf dist *.tsbuildinfo"
36
+ }
37
+ }