nestjs-trpc 1.3.1 → 1.3.3

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.
@@ -1,8 +1,7 @@
1
- import { Decorator, SourceFile, Project } from 'ts-morph';
1
+ import { Decorator, Project, SourceFile } from 'ts-morph';
2
2
  import { DecoratorGeneratorMetadata } from '../interfaces/generator.interface';
3
3
  export declare class DecoratorGenerator {
4
4
  private readonly consoleLogger;
5
5
  serializeProcedureDecorators(decorators: Decorator[], sourceFile: SourceFile, project: Project): Array<DecoratorGeneratorMetadata>;
6
- private buildSourceFileImportsMap;
7
6
  }
8
7
  //# sourceMappingURL=decorator.generator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"decorator.generator.d.ts","sourceRoot":"","sources":["../../lib/generators/decorator.generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EACL,0BAA0B,EAE3B,MAAM,mCAAmC,CAAC;AAK3C,qBACa,kBAAkB;IAE7B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAiB;IAExC,4BAA4B,CACjC,UAAU,EAAE,SAAS,EAAE,EACvB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,OAAO,GACf,KAAK,CAAC,0BAA0B,CAAC;IA6CpC,OAAO,CAAC,yBAAyB;CAmClC"}
1
+ {"version":3,"file":"decorator.generator.d.ts","sourceRoot":"","sources":["../../lib/generators/decorator.generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAI/E,qBACa,kBAAkB;IAE7B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAiB;IAExC,4BAA4B,CACjC,UAAU,EAAE,SAAS,EAAE,EACvB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,OAAO,GACf,KAAK,CAAC,0BAA0B,CAAC;CAqCrC"}
@@ -4,15 +4,13 @@ exports.DecoratorGenerator = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const file_util_1 = require("../utils/file.util");
6
6
  const common_1 = require("@nestjs/common");
7
- const path = require("node:path");
8
7
  let DecoratorGenerator = class DecoratorGenerator {
9
8
  serializeProcedureDecorators(decorators, sourceFile, project) {
10
- const sourceFileImportsMap = this.buildSourceFileImportsMap(sourceFile, project);
11
- const decoratorsArray = decorators.reduce((array, decorator) => {
9
+ return decorators.reduce((array, decorator) => {
12
10
  const decoratorName = decorator.getName();
13
11
  if (decoratorName === 'Query' || decoratorName === 'Mutation') {
14
- const input = (0, file_util_1.getDecoratorPropertyValue)(decorator, 'input', sourceFile, sourceFileImportsMap);
15
- const output = (0, file_util_1.getDecoratorPropertyValue)(decorator, 'output', sourceFile, sourceFileImportsMap);
12
+ const input = (0, file_util_1.getDecoratorPropertyValue)(decorator, 'input', sourceFile, project);
13
+ const output = (0, file_util_1.getDecoratorPropertyValue)(decorator, 'output', sourceFile, project);
16
14
  array.push({
17
15
  name: decoratorName,
18
16
  arguments: {
@@ -29,33 +27,6 @@ let DecoratorGenerator = class DecoratorGenerator {
29
27
  }
30
28
  return array;
31
29
  }, []);
32
- return decoratorsArray;
33
- }
34
- buildSourceFileImportsMap(sourceFile, project) {
35
- const sourceFileImportsMap = new Map();
36
- const importDeclarations = sourceFile.getImportDeclarations();
37
- for (const importDeclaration of importDeclarations) {
38
- const namedImports = importDeclaration.getNamedImports();
39
- for (const namedImport of namedImports) {
40
- const name = namedImport.getName();
41
- const moduleSpecifier = importDeclaration.getModuleSpecifierValue();
42
- const resolvedPath = path.resolve(path.dirname(sourceFile.getFilePath()), moduleSpecifier + '.ts');
43
- const importedSourceFile = project.addSourceFileAtPathIfExists(resolvedPath);
44
- if (!importedSourceFile)
45
- continue;
46
- const schemaVariable = importedSourceFile.getVariableDeclaration(name);
47
- if (schemaVariable) {
48
- const initializer = schemaVariable.getInitializer();
49
- if (initializer) {
50
- sourceFileImportsMap.set(name, {
51
- initializer,
52
- sourceFile: importedSourceFile,
53
- });
54
- }
55
- }
56
- }
57
- }
58
- return sourceFileImportsMap;
59
30
  }
60
31
  };
61
32
  exports.DecoratorGenerator = DecoratorGenerator;
@@ -1,6 +1,5 @@
1
- import { SourceFile, Decorator } from 'ts-morph';
2
- import { SourceFileImportsMap } from '../interfaces/generator.interface';
1
+ import { SourceFile, Decorator, Project } from 'ts-morph';
3
2
  export declare function generateStaticDeclaration(sourceFile: SourceFile): void;
4
3
  export declare function saveOrOverrideFile(sourceFile: SourceFile): Promise<void>;
5
- export declare function getDecoratorPropertyValue(decorator: Decorator, propertyName: string, sourceFile: SourceFile, importsMap: Map<string, SourceFileImportsMap>): string | null;
4
+ export declare function getDecoratorPropertyValue(decorator: Decorator, propertyName: string, sourceFile: SourceFile, project: Project): string | null;
6
5
  //# sourceMappingURL=file.util.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"file.util.d.ts","sourceRoot":"","sources":["../../lib/utils/file.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAwE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEvH,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAGzE,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAsBtE;AAED,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9E;AAED,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,UAAU,EACtB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,GAC5C,MAAM,GAAG,IAAI,CAkBf"}
1
+ {"version":3,"file":"file.util.d.ts","sourceRoot":"","sources":["../../lib/utils/file.util.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EAKV,SAAS,EACT,OAAO,EACR,MAAM,UAAU,CAAC;AAGlB,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAsBtE;AAED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,OAAO,GACf,MAAM,GAAG,IAAI,CAyBf"}
@@ -31,7 +31,7 @@ async function saveOrOverrideFile(sourceFile) {
31
31
  sourceFile.formatText({ indentSize: 2 });
32
32
  await sourceFile.save();
33
33
  }
34
- function getDecoratorPropertyValue(decorator, propertyName, sourceFile, importsMap) {
34
+ function getDecoratorPropertyValue(decorator, propertyName, sourceFile, project) {
35
35
  const args = decorator.getArguments();
36
36
  for (const arg of args) {
37
37
  if (arg.getKind() === ts_morph_1.SyntaxKind.ObjectLiteralExpression) {
@@ -41,7 +41,7 @@ function getDecoratorPropertyValue(decorator, propertyName, sourceFile, importsM
41
41
  return null;
42
42
  }
43
43
  const propertyInitializer = property.getInitializer();
44
- return (0, type_util_1.flattenZodSchema)(propertyInitializer, importsMap, sourceFile, propertyInitializer.getText());
44
+ return (0, type_util_1.flattenZodSchema)(propertyInitializer, sourceFile, project, propertyInitializer.getText());
45
45
  }
46
46
  }
47
47
  return null;
@@ -1,6 +1,6 @@
1
- import { Node, SourceFile, Type } from 'ts-morph';
2
- import { ProcedureGeneratorMetadata, SourceFileImportsMap } from '../interfaces/generator.interface';
1
+ import { Node, Project, SourceFile, Type } from 'ts-morph';
2
+ import { ProcedureGeneratorMetadata } from '../interfaces/generator.interface';
3
3
  export declare function findCtxOutProperty(type: Type): string | undefined;
4
4
  export declare function generateProcedureString(procedure: ProcedureGeneratorMetadata): string;
5
- export declare function flattenZodSchema(node: Node, importsMap: Map<string, SourceFileImportsMap>, sourceFile: SourceFile, schema: string): string;
5
+ export declare function flattenZodSchema(node: Node, sourceFile: SourceFile, project: Project, schema: string): string;
6
6
  //# sourceMappingURL=type.util.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"type.util.d.ts","sourceRoot":"","sources":["../../lib/utils/type.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAErG,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAKjE;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,0BAA0B,GAAG,MAAM,CAarF;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,EAC7C,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,MAAM,GACb,MAAM,CA2FR"}
1
+ {"version":3,"file":"type.util.d.ts","sourceRoot":"","sources":["../../lib/utils/type.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EACL,0BAA0B,EAE3B,MAAM,mCAAmC,CAAC;AAE3C,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAKjE;AAED,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,0BAA0B,GACpC,MAAM,CAeR;AA2FD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,GACb,MAAM,CAiGR"}
@@ -11,7 +11,7 @@ function findCtxOutProperty(type) {
11
11
  }
12
12
  function generateProcedureString(procedure) {
13
13
  const { name, decorators } = procedure;
14
- const decorator = decorators.find(d => d.name === 'Mutation' || d.name === 'Query');
14
+ const decorator = decorators.find((decorator) => decorator.name === 'Mutation' || decorator.name === 'Query');
15
15
  if (!decorator) {
16
16
  return '';
17
17
  }
@@ -20,14 +20,85 @@ function generateProcedureString(procedure) {
20
20
  .join('');
21
21
  return `${name}: publicProcedure${decoratorArgumentsArray}.${decorator.name.toLowerCase()}(async () => "PLACEHOLDER_DO_NOT_REMOVE" as any )`;
22
22
  }
23
- function flattenZodSchema(node, importsMap, sourceFile, schema) {
23
+ /**
24
+ * https://github.com/dsherret/ts-morph/issues/327
25
+ * Note that if the module resolution of the compiler is Classic then it won't resolve those implicit index.ts module specifiers.
26
+ * So for example, if the moduleResolution compiler option isn't explicitly set then setting the module
27
+ * compiler option to anything but ModuleKind.CommonJS will cause the module resolution kind to resolve to Classic.
28
+ * Additionally, if moduleResolution and the module compiler option isn't set,
29
+ * then a script target of ES2015 and above will also use Classic module resolution.
30
+ */
31
+ function resolveBarrelFileImport(barrelSourceFile, name, project) {
32
+ // Traverse through export declarations to find the actual source of the named import
33
+ for (const exportDeclaration of barrelSourceFile.getExportDeclarations()) {
34
+ const exportedSourceFile = exportDeclaration.getModuleSpecifierSourceFile();
35
+ if (exportedSourceFile == null)
36
+ continue;
37
+ // Check if the named export is explicitly re-exported
38
+ const namedExports = exportDeclaration.getNamedExports();
39
+ if (namedExports.length > 0) {
40
+ const matchingExport = namedExports.find((e) => e.getName() === name);
41
+ if (matchingExport) {
42
+ return exportedSourceFile;
43
+ }
44
+ }
45
+ else {
46
+ // Handle `export * from ...` case: recursively resolve the export
47
+ const schemaVariable = exportedSourceFile.getVariableDeclaration(name);
48
+ if (schemaVariable) {
49
+ return exportedSourceFile;
50
+ }
51
+ else {
52
+ // Continue resolving if it's another barrel file
53
+ const baseSourceFile = resolveBarrelFileImport(exportedSourceFile, name, project);
54
+ if (baseSourceFile)
55
+ return baseSourceFile;
56
+ }
57
+ }
58
+ }
59
+ return undefined;
60
+ }
61
+ function buildSourceFileImportsMap(sourceFile, project) {
62
+ const sourceFileImportsMap = new Map();
63
+ const importDeclarations = sourceFile.getImportDeclarations();
64
+ for (const importDeclaration of importDeclarations) {
65
+ const namedImports = importDeclaration.getNamedImports();
66
+ for (const namedImport of namedImports) {
67
+ const name = namedImport.getName();
68
+ const importedSourceFile = importDeclaration.getModuleSpecifierSourceFile();
69
+ if (importedSourceFile == null) {
70
+ continue;
71
+ }
72
+ const resolvedSourceFile = importedSourceFile.getFilePath().endsWith('index.ts') &&
73
+ importedSourceFile.getVariableDeclaration(name) == null
74
+ ? resolveBarrelFileImport(importedSourceFile, name, project)
75
+ : importedSourceFile;
76
+ if (resolvedSourceFile == null) {
77
+ continue;
78
+ }
79
+ const schemaVariable = resolvedSourceFile.getVariableDeclaration(name);
80
+ if (schemaVariable != null) {
81
+ const initializer = schemaVariable.getInitializer();
82
+ if (initializer) {
83
+ sourceFileImportsMap.set(name, {
84
+ initializer,
85
+ sourceFile: resolvedSourceFile,
86
+ });
87
+ }
88
+ }
89
+ }
90
+ }
91
+ return sourceFileImportsMap;
92
+ }
93
+ function flattenZodSchema(node, sourceFile, project, schema) {
94
+ const importsMap = buildSourceFileImportsMap(sourceFile, project);
24
95
  if (ts_morph_1.Node.isIdentifier(node)) {
25
96
  const identifierName = node.getText();
26
97
  const identifierDeclaration = sourceFile.getVariableDeclaration(identifierName);
27
98
  if (identifierDeclaration != null) {
28
99
  const identifierInitializer = identifierDeclaration.getInitializer();
29
100
  if (identifierInitializer != null) {
30
- const identifierSchema = flattenZodSchema(identifierInitializer, importsMap, sourceFile, identifierInitializer.getText());
101
+ const identifierSchema = flattenZodSchema(identifierInitializer, sourceFile, project, identifierInitializer.getText());
31
102
  schema = schema.replace(identifierName, identifierSchema);
32
103
  }
33
104
  }
@@ -35,7 +106,7 @@ function flattenZodSchema(node, importsMap, sourceFile, schema) {
35
106
  const importedIdentifier = importsMap.get(identifierName);
36
107
  if (importedIdentifier != null) {
37
108
  const { initializer } = importedIdentifier;
38
- const identifierSchema = flattenZodSchema(initializer, importsMap, importedIdentifier.sourceFile, initializer.getText());
109
+ const identifierSchema = flattenZodSchema(initializer, importedIdentifier.sourceFile, project, initializer.getText());
39
110
  schema = schema.replace(identifierName, identifierSchema);
40
111
  }
41
112
  }
@@ -46,7 +117,7 @@ function flattenZodSchema(node, importsMap, sourceFile, schema) {
46
117
  const propertyText = property.getText();
47
118
  const propertyInitializer = property.getInitializer();
48
119
  if (propertyInitializer != null) {
49
- schema = schema.replace(propertyText, flattenZodSchema(propertyInitializer, importsMap, sourceFile, propertyText));
120
+ schema = schema.replace(propertyText, flattenZodSchema(propertyInitializer, sourceFile, project, propertyText));
50
121
  }
51
122
  }
52
123
  }
@@ -54,23 +125,24 @@ function flattenZodSchema(node, importsMap, sourceFile, schema) {
54
125
  else if (ts_morph_1.Node.isArrayLiteralExpression(node)) {
55
126
  for (const element of node.getElements()) {
56
127
  const elementText = element.getText();
57
- schema = schema.replace(elementText, flattenZodSchema(element, importsMap, sourceFile, elementText));
128
+ schema = schema.replace(elementText, flattenZodSchema(element, sourceFile, project, elementText));
58
129
  }
59
130
  }
60
131
  else if (ts_morph_1.Node.isCallExpression(node)) {
61
132
  const expression = node.getExpression();
62
- if (ts_morph_1.Node.isPropertyAccessExpression(expression) && !expression.getText().startsWith("z")) {
63
- const baseSchema = flattenZodSchema(expression, importsMap, sourceFile, expression.getText());
133
+ if (ts_morph_1.Node.isPropertyAccessExpression(expression) &&
134
+ !expression.getText().startsWith('z')) {
135
+ const baseSchema = flattenZodSchema(expression, sourceFile, project, expression.getText());
64
136
  const propertyName = expression.getName();
65
137
  schema = schema.replace(expression.getText(), `${baseSchema}.${propertyName}`);
66
138
  }
67
139
  for (const arg of node.getArguments()) {
68
140
  const argText = arg.getText();
69
- schema = schema.replace(argText, flattenZodSchema(arg, importsMap, sourceFile, argText));
141
+ schema = schema.replace(argText, flattenZodSchema(arg, sourceFile, project, argText));
70
142
  }
71
143
  }
72
144
  else if (ts_morph_1.Node.isPropertyAccessExpression(node)) {
73
- schema = flattenZodSchema(node.getExpression(), importsMap, sourceFile, node.getExpression().getText());
145
+ schema = flattenZodSchema(node.getExpression(), sourceFile, project, node.getExpression().getText());
74
146
  }
75
147
  return schema;
76
148
  }
@@ -1,11 +1,7 @@
1
- import { Decorator, SourceFile, Project } from 'ts-morph';
2
- import {
3
- DecoratorGeneratorMetadata,
4
- SourceFileImportsMap,
5
- } from '../interfaces/generator.interface';
1
+ import { Decorator, Project, SourceFile } from 'ts-morph';
2
+ import { DecoratorGeneratorMetadata } from '../interfaces/generator.interface';
6
3
  import { getDecoratorPropertyValue } from '../utils/file.util';
7
4
  import { ConsoleLogger, Inject, Injectable } from '@nestjs/common';
8
- import * as path from 'node:path';
9
5
 
10
6
  @Injectable()
11
7
  export class DecoratorGenerator {
@@ -17,12 +13,7 @@ export class DecoratorGenerator {
17
13
  sourceFile: SourceFile,
18
14
  project: Project,
19
15
  ): Array<DecoratorGeneratorMetadata> {
20
- const sourceFileImportsMap = this.buildSourceFileImportsMap(
21
- sourceFile,
22
- project,
23
- );
24
-
25
- const decoratorsArray = decorators.reduce<DecoratorGeneratorMetadata[]>(
16
+ return decorators.reduce<DecoratorGeneratorMetadata[]>(
26
17
  (array, decorator) => {
27
18
  const decoratorName = decorator.getName();
28
19
 
@@ -31,13 +22,13 @@ export class DecoratorGenerator {
31
22
  decorator,
32
23
  'input',
33
24
  sourceFile,
34
- sourceFileImportsMap,
25
+ project,
35
26
  );
36
27
  const output = getDecoratorPropertyValue(
37
28
  decorator,
38
29
  'output',
39
30
  sourceFile,
40
- sourceFileImportsMap,
31
+ project,
41
32
  );
42
33
 
43
34
  array.push({
@@ -57,43 +48,5 @@ export class DecoratorGenerator {
57
48
  },
58
49
  [],
59
50
  );
60
-
61
- return decoratorsArray;
62
- }
63
-
64
- private buildSourceFileImportsMap(
65
- sourceFile: SourceFile,
66
- project: Project,
67
- ): Map<string, SourceFileImportsMap> {
68
- const sourceFileImportsMap = new Map<string, SourceFileImportsMap>();
69
- const importDeclarations = sourceFile.getImportDeclarations();
70
-
71
- for (const importDeclaration of importDeclarations) {
72
- const namedImports = importDeclaration.getNamedImports();
73
- for (const namedImport of namedImports) {
74
- const name = namedImport.getName();
75
- const moduleSpecifier = importDeclaration.getModuleSpecifierValue();
76
- const resolvedPath = path.resolve(
77
- path.dirname(sourceFile.getFilePath()),
78
- moduleSpecifier + '.ts',
79
- );
80
- const importedSourceFile =
81
- project.addSourceFileAtPathIfExists(resolvedPath);
82
- if (!importedSourceFile) continue;
83
-
84
- const schemaVariable = importedSourceFile.getVariableDeclaration(name);
85
- if (schemaVariable) {
86
- const initializer = schemaVariable.getInitializer();
87
- if (initializer) {
88
- sourceFileImportsMap.set(name, {
89
- initializer,
90
- sourceFile: importedSourceFile,
91
- });
92
- }
93
- }
94
- }
95
- }
96
-
97
- return sourceFileImportsMap;
98
51
  }
99
52
  }
@@ -1,6 +1,12 @@
1
- import { SourceFile, StructureKind, VariableDeclarationKind, Expression, SyntaxKind, Node, Decorator } from 'ts-morph';
2
- import * as path from 'node:path';
3
- import { SourceFileImportsMap } from '../interfaces/generator.interface';
1
+ import {
2
+ SourceFile,
3
+ StructureKind,
4
+ VariableDeclarationKind,
5
+ Expression,
6
+ SyntaxKind,
7
+ Decorator,
8
+ Project,
9
+ } from 'ts-morph';
4
10
  import { flattenZodSchema } from './type.util';
5
11
 
6
12
  export function generateStaticDeclaration(sourceFile: SourceFile): void {
@@ -27,7 +33,9 @@ export function generateStaticDeclaration(sourceFile: SourceFile): void {
27
33
  ]);
28
34
  }
29
35
 
30
- export async function saveOrOverrideFile(sourceFile: SourceFile): Promise<void> {
36
+ export async function saveOrOverrideFile(
37
+ sourceFile: SourceFile,
38
+ ): Promise<void> {
31
39
  sourceFile.formatText({ indentSize: 2 });
32
40
  await sourceFile.save();
33
41
  }
@@ -36,23 +44,30 @@ export function getDecoratorPropertyValue(
36
44
  decorator: Decorator,
37
45
  propertyName: string,
38
46
  sourceFile: SourceFile,
39
- importsMap: Map<string, SourceFileImportsMap>,
47
+ project: Project,
40
48
  ): string | null {
41
49
  const args = decorator.getArguments();
42
50
 
43
51
  for (const arg of args) {
44
52
  if (arg.getKind() === SyntaxKind.ObjectLiteralExpression) {
45
53
  const properties = (arg as any).getProperties();
46
- const property = properties.find((p: any) => p.getName() === propertyName);
54
+ const property = properties.find(
55
+ (p: any) => p.getName() === propertyName,
56
+ );
47
57
 
48
58
  if (!property) {
49
59
  return null;
50
60
  }
51
61
 
52
62
  const propertyInitializer: Expression = property.getInitializer();
53
- return flattenZodSchema(propertyInitializer, importsMap, sourceFile, propertyInitializer.getText());
63
+ return flattenZodSchema(
64
+ propertyInitializer,
65
+ sourceFile,
66
+ project,
67
+ propertyInitializer.getText(),
68
+ );
54
69
  }
55
70
  }
56
71
 
57
72
  return null;
58
- }
73
+ }
@@ -1,4 +1,4 @@
1
- import { Node, SourceFile, Type } from 'ts-morph';
1
+ import { Node, Project, SourceFile, Type } from 'ts-morph';
2
2
  import {
3
3
  ProcedureGeneratorMetadata,
4
4
  SourceFileImportsMap,
@@ -16,7 +16,7 @@ export function generateProcedureString(
16
16
  ): string {
17
17
  const { name, decorators } = procedure;
18
18
  const decorator = decorators.find(
19
- (d) => d.name === 'Mutation' || d.name === 'Query',
19
+ (decorator) => decorator.name === 'Mutation' || decorator.name === 'Query',
20
20
  );
21
21
 
22
22
  if (!decorator) {
@@ -30,12 +30,102 @@ export function generateProcedureString(
30
30
  return `${name}: publicProcedure${decoratorArgumentsArray}.${decorator.name.toLowerCase()}(async () => "PLACEHOLDER_DO_NOT_REMOVE" as any )`;
31
31
  }
32
32
 
33
+ /**
34
+ * https://github.com/dsherret/ts-morph/issues/327
35
+ * Note that if the module resolution of the compiler is Classic then it won't resolve those implicit index.ts module specifiers.
36
+ * So for example, if the moduleResolution compiler option isn't explicitly set then setting the module
37
+ * compiler option to anything but ModuleKind.CommonJS will cause the module resolution kind to resolve to Classic.
38
+ * Additionally, if moduleResolution and the module compiler option isn't set,
39
+ * then a script target of ES2015 and above will also use Classic module resolution.
40
+ */
41
+ function resolveBarrelFileImport(
42
+ barrelSourceFile: SourceFile,
43
+ name: string,
44
+ project: Project,
45
+ ): SourceFile | undefined {
46
+ // Traverse through export declarations to find the actual source of the named import
47
+ for (const exportDeclaration of barrelSourceFile.getExportDeclarations()) {
48
+ const exportedSourceFile = exportDeclaration.getModuleSpecifierSourceFile();
49
+ if (exportedSourceFile == null) continue;
50
+
51
+ // Check if the named export is explicitly re-exported
52
+ const namedExports = exportDeclaration.getNamedExports();
53
+ if (namedExports.length > 0) {
54
+ const matchingExport = namedExports.find((e) => e.getName() === name);
55
+ if (matchingExport) {
56
+ return exportedSourceFile;
57
+ }
58
+ } else {
59
+ // Handle `export * from ...` case: recursively resolve the export
60
+ const schemaVariable = exportedSourceFile.getVariableDeclaration(name);
61
+ if (schemaVariable) {
62
+ return exportedSourceFile;
63
+ } else {
64
+ // Continue resolving if it's another barrel file
65
+ const baseSourceFile = resolveBarrelFileImport(
66
+ exportedSourceFile,
67
+ name,
68
+ project,
69
+ );
70
+ if (baseSourceFile) return baseSourceFile;
71
+ }
72
+ }
73
+ }
74
+
75
+ return undefined;
76
+ }
77
+
78
+ function buildSourceFileImportsMap(
79
+ sourceFile: SourceFile,
80
+ project: Project,
81
+ ): Map<string, SourceFileImportsMap> {
82
+ const sourceFileImportsMap = new Map<string, SourceFileImportsMap>();
83
+ const importDeclarations = sourceFile.getImportDeclarations();
84
+
85
+ for (const importDeclaration of importDeclarations) {
86
+ const namedImports = importDeclaration.getNamedImports();
87
+ for (const namedImport of namedImports) {
88
+ const name = namedImport.getName();
89
+ const importedSourceFile =
90
+ importDeclaration.getModuleSpecifierSourceFile();
91
+
92
+ if (importedSourceFile == null) {
93
+ continue;
94
+ }
95
+
96
+ const resolvedSourceFile =
97
+ importedSourceFile.getFilePath().endsWith('index.ts') &&
98
+ importedSourceFile.getVariableDeclaration(name) == null
99
+ ? resolveBarrelFileImport(importedSourceFile, name, project)
100
+ : importedSourceFile;
101
+
102
+ if (resolvedSourceFile == null) {
103
+ continue;
104
+ }
105
+
106
+ const schemaVariable = resolvedSourceFile.getVariableDeclaration(name);
107
+ if (schemaVariable != null) {
108
+ const initializer = schemaVariable.getInitializer();
109
+ if (initializer) {
110
+ sourceFileImportsMap.set(name, {
111
+ initializer,
112
+ sourceFile: resolvedSourceFile,
113
+ });
114
+ }
115
+ }
116
+ }
117
+ }
118
+
119
+ return sourceFileImportsMap;
120
+ }
121
+
33
122
  export function flattenZodSchema(
34
123
  node: Node,
35
- importsMap: Map<string, SourceFileImportsMap>,
36
124
  sourceFile: SourceFile,
125
+ project: Project,
37
126
  schema: string,
38
127
  ): string {
128
+ const importsMap = buildSourceFileImportsMap(sourceFile, project);
39
129
  if (Node.isIdentifier(node)) {
40
130
  const identifierName = node.getText();
41
131
  const identifierDeclaration =
@@ -47,8 +137,8 @@ export function flattenZodSchema(
47
137
  if (identifierInitializer != null) {
48
138
  const identifierSchema = flattenZodSchema(
49
139
  identifierInitializer,
50
- importsMap,
51
140
  sourceFile,
141
+ project,
52
142
  identifierInitializer.getText(),
53
143
  );
54
144
 
@@ -61,8 +151,8 @@ export function flattenZodSchema(
61
151
  const { initializer } = importedIdentifier;
62
152
  const identifierSchema = flattenZodSchema(
63
153
  initializer,
64
- importsMap,
65
154
  importedIdentifier.sourceFile,
155
+ project,
66
156
  initializer.getText(),
67
157
  );
68
158
 
@@ -80,8 +170,8 @@ export function flattenZodSchema(
80
170
  propertyText,
81
171
  flattenZodSchema(
82
172
  propertyInitializer,
83
- importsMap,
84
173
  sourceFile,
174
+ project,
85
175
  propertyText,
86
176
  ),
87
177
  );
@@ -93,7 +183,7 @@ export function flattenZodSchema(
93
183
  const elementText = element.getText();
94
184
  schema = schema.replace(
95
185
  elementText,
96
- flattenZodSchema(element, importsMap, sourceFile, elementText),
186
+ flattenZodSchema(element, sourceFile, project, elementText),
97
187
  );
98
188
  }
99
189
  } else if (Node.isCallExpression(node)) {
@@ -104,8 +194,8 @@ export function flattenZodSchema(
104
194
  ) {
105
195
  const baseSchema = flattenZodSchema(
106
196
  expression,
107
- importsMap,
108
197
  sourceFile,
198
+ project,
109
199
  expression.getText(),
110
200
  );
111
201
  const propertyName = expression.getName();
@@ -118,14 +208,14 @@ export function flattenZodSchema(
118
208
  const argText = arg.getText();
119
209
  schema = schema.replace(
120
210
  argText,
121
- flattenZodSchema(arg, importsMap, sourceFile, argText),
211
+ flattenZodSchema(arg, sourceFile, project, argText),
122
212
  );
123
213
  }
124
214
  } else if (Node.isPropertyAccessExpression(node)) {
125
215
  schema = flattenZodSchema(
126
216
  node.getExpression(),
127
- importsMap,
128
217
  sourceFile,
218
+ project,
129
219
  node.getExpression().getText(),
130
220
  );
131
221
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nestjs-trpc",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "homepage": "https://nestjs-trpc.io",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./lib/index.ts",
@@ -42,7 +42,7 @@
42
42
  "peerDependencies": {
43
43
  "@nestjs/common": "^9.3.8 || ^10.0.0",
44
44
  "@nestjs/core": "^9.3.8 || ^10.0.0",
45
- "@trpc/server": "^10.18.0",
45
+ "@trpc/server": "^10.0.0",
46
46
  "reflect-metadata": "^0.1.13 || ^0.2.0",
47
47
  "rxjs": "7.8.1",
48
48
  "zod": "^3.14.0"
@@ -64,7 +64,7 @@
64
64
  "tsconfig-paths": "^4.2.0",
65
65
  "type-fest": "^4.21.0",
66
66
  "typescript": "5.5.3",
67
- "zod": "^3.14.0"
67
+ "zod": "^3.14.4"
68
68
  },
69
69
  "dependencies": {
70
70
  "func-loc": "^0.1.16",