@dudousxd/nestjs-inertia-codegen 2.0.1 → 3.0.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/dist/index.d.cts CHANGED
@@ -62,10 +62,17 @@ declare class CodegenError extends Error {
62
62
  constructor(message: string, options?: ErrorOptions);
63
63
  }
64
64
 
65
+ interface TypeRef {
66
+ name: string;
67
+ filePath: string;
68
+ }
65
69
  interface ContractSource {
66
70
  query: string | null;
67
71
  body: string | null;
68
72
  response: string;
73
+ queryRef?: TypeRef | null;
74
+ bodyRef?: TypeRef | null;
75
+ responseRef?: TypeRef | null;
69
76
  }
70
77
  interface ContractDescriptor {
71
78
  contractSource: ContractSource;
@@ -120,6 +127,6 @@ declare function acquireLock(outDir: string): Promise<{
120
127
  release: () => Promise<void>;
121
128
  } | null>;
122
129
 
123
- declare const VERSION = "2.0.1";
130
+ declare const VERSION = "3.0.0";
124
131
 
125
132
  export { CodegenError, ConfigError, type ResolvedConfig, type ScopeConfig, type UserConfig, VERSION, type Watcher, acquireLock, defineConfig, generate, loadConfig, watch };
package/dist/index.d.ts CHANGED
@@ -62,10 +62,17 @@ declare class CodegenError extends Error {
62
62
  constructor(message: string, options?: ErrorOptions);
63
63
  }
64
64
 
65
+ interface TypeRef {
66
+ name: string;
67
+ filePath: string;
68
+ }
65
69
  interface ContractSource {
66
70
  query: string | null;
67
71
  body: string | null;
68
72
  response: string;
73
+ queryRef?: TypeRef | null;
74
+ bodyRef?: TypeRef | null;
75
+ responseRef?: TypeRef | null;
69
76
  }
70
77
  interface ContractDescriptor {
71
78
  contractSource: ContractSource;
@@ -120,6 +127,6 @@ declare function acquireLock(outDir: string): Promise<{
120
127
  release: () => Promise<void>;
121
128
  } | null>;
122
129
 
123
- declare const VERSION = "2.0.1";
130
+ declare const VERSION = "3.0.0";
124
131
 
125
132
  export { CodegenError, ConfigError, type ResolvedConfig, type ScopeConfig, type UserConfig, VERSION, type Watcher, acquireLock, defineConfig, generate, loadConfig, watch };
package/dist/index.js CHANGED
@@ -197,12 +197,12 @@ __name(extractPropsSource, "extractPropsSource");
197
197
 
198
198
  // src/emit/emit-api.ts
199
199
  import { mkdir, writeFile } from "fs/promises";
200
- import { join as join2 } from "path";
200
+ import { join as join2, relative as relative3 } from "path";
201
201
  async function emitApi(routes, outDir) {
202
202
  await mkdir(outDir, {
203
203
  recursive: true
204
204
  });
205
- const content = buildApiFile(routes);
205
+ const content = buildApiFile(routes, outDir);
206
206
  await writeFile(join2(outDir, "api.ts"), content, "utf8");
207
207
  }
208
208
  __name(emitApi, "emitApi");
@@ -275,9 +275,9 @@ function emitRouterTypeBlock(tree, indent) {
275
275
  if (node.kind === "leaf") {
276
276
  const c = node;
277
277
  const method = c.method.toUpperCase();
278
- const query = c.contractSource.query ?? "never";
279
- const body = method === "GET" ? "never" : c.contractSource.body ?? "never";
280
- const response = c.contractSource.response;
278
+ const query = c.contractSource.queryRef ? c.contractSource.queryRef.name : c.contractSource.query ?? "never";
279
+ const body = method === "GET" ? "never" : c.contractSource.bodyRef ? c.contractSource.bodyRef.name : c.contractSource.body ?? "never";
280
+ const response = c.contractSource.responseRef ? c.contractSource.responseRef.name : c.contractSource.response;
281
281
  const safeMethod = JSON.stringify(method);
282
282
  const safeUrl = JSON.stringify(c.path);
283
283
  lines.push(`${pad}${objKey}: { method: ${safeMethod}; url: ${safeUrl}; query: ${query}; body: ${body}; response: ${response} };`);
@@ -333,14 +333,43 @@ function buildRouterTypeAccess(name) {
333
333
  return `ApiRouter${segments.map((s) => `[${JSON.stringify(s)}]`).join("")}`;
334
334
  }
335
335
  __name(buildRouterTypeAccess, "buildRouterTypeAccess");
336
- function buildApiFile(routes) {
336
+ function buildApiFile(routes, outDir) {
337
337
  const contracted = routes.filter((r) => r.contract);
338
+ const importsByFile = /* @__PURE__ */ new Map();
339
+ for (const r of contracted) {
340
+ const cs = r.contract?.contractSource;
341
+ if (!cs) continue;
342
+ for (const ref of [
343
+ cs.queryRef,
344
+ cs.bodyRef,
345
+ cs.responseRef
346
+ ]) {
347
+ if (!ref) continue;
348
+ let names = importsByFile.get(ref.filePath);
349
+ if (!names) {
350
+ names = /* @__PURE__ */ new Set();
351
+ importsByFile.set(ref.filePath, names);
352
+ }
353
+ names.add(ref.name);
354
+ }
355
+ }
338
356
  const lines = [
339
357
  "// Generated by @dudousxd/nestjs-inertia-codegen. Do not edit.",
340
358
  ""
341
359
  ];
342
360
  lines.push("import { route } from './routes.js';");
343
361
  lines.push("import { createFetcher } from '@dudousxd/nestjs-inertia-client';");
362
+ if (importsByFile.size > 0 && outDir) {
363
+ lines.push("");
364
+ for (const [filePath, names] of importsByFile) {
365
+ let relPath = relative3(outDir, filePath).replace(/\.ts$/, "");
366
+ if (!relPath.startsWith(".")) relPath = `./${relPath}`;
367
+ const sortedNames = [
368
+ ...names
369
+ ].sort();
370
+ lines.push(`import type { ${sortedNames.join(", ")} } from '${relPath}';`);
371
+ }
372
+ }
344
373
  lines.push("");
345
374
  lines.push("export const fetcher = createFetcher();");
346
375
  lines.push("");
@@ -1085,6 +1114,53 @@ function resolveIdentifierToClassType(node, sourceFile, project, depth) {
1085
1114
  return name;
1086
1115
  }
1087
1116
  __name(resolveIdentifierToClassType, "resolveIdentifierToClassType");
1117
+ function tryResolveTypeRef(typeNode, sourceFile, project) {
1118
+ if (Node.isTypeReference(typeNode)) {
1119
+ const typeName = typeNode.getTypeName();
1120
+ const name = Node.isIdentifier(typeName) ? typeName.getText() : null;
1121
+ if (!name) return null;
1122
+ if (name === "Promise") {
1123
+ const typeArgs = typeNode.getTypeArguments();
1124
+ const first = typeArgs[0];
1125
+ if (first) return tryResolveTypeRef(first, sourceFile, project);
1126
+ return null;
1127
+ }
1128
+ if ([
1129
+ "string",
1130
+ "number",
1131
+ "boolean",
1132
+ "void",
1133
+ "unknown",
1134
+ "any",
1135
+ "Date",
1136
+ "Array"
1137
+ ].includes(name)) {
1138
+ return null;
1139
+ }
1140
+ const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
1141
+ if (localDecl && localDecl.isExported()) {
1142
+ return {
1143
+ name,
1144
+ filePath: sourceFile.getFilePath()
1145
+ };
1146
+ }
1147
+ const resolved = resolveImportedType(name, sourceFile, project);
1148
+ if (resolved && (resolved.kind === "class" || resolved.kind === "interface")) {
1149
+ const decl = resolved.decl;
1150
+ if (decl.isExported()) {
1151
+ return {
1152
+ name,
1153
+ filePath: resolved.file.getFilePath()
1154
+ };
1155
+ }
1156
+ }
1157
+ }
1158
+ if (Node.isArrayTypeNode(typeNode)) {
1159
+ return tryResolveTypeRef(typeNode.getElementTypeNode(), sourceFile, project);
1160
+ }
1161
+ return null;
1162
+ }
1163
+ __name(tryResolveTypeRef, "tryResolveTypeRef");
1088
1164
  function extractDtoContract(method, sourceFile, project) {
1089
1165
  const body = extractBodyType(method, sourceFile, project);
1090
1166
  const query = extractQueryType(method, sourceFile, project);
@@ -1093,11 +1169,61 @@ function extractDtoContract(method, sourceFile, project) {
1093
1169
  if (body === null && query === null && paramsType === null && response === "unknown") {
1094
1170
  return null;
1095
1171
  }
1172
+ let bodyRef = null;
1173
+ let queryRef = null;
1174
+ let responseRef = null;
1175
+ for (const param of method.getParameters()) {
1176
+ if (param.getDecorators().some((d) => d.getName() === "Body") && param.getTypeNode()) {
1177
+ bodyRef = tryResolveTypeRef(param.getTypeNode(), sourceFile, project);
1178
+ }
1179
+ if (param.getDecorators().some((d) => d.getName() === "Query") && param.getTypeNode()) {
1180
+ queryRef = tryResolveTypeRef(param.getTypeNode(), sourceFile, project);
1181
+ }
1182
+ }
1183
+ const returnTypeNode = method.getReturnTypeNode();
1184
+ if (returnTypeNode) {
1185
+ responseRef = tryResolveTypeRef(returnTypeNode, sourceFile, project);
1186
+ }
1187
+ if (!responseRef) {
1188
+ const apiResp = method.getDecorator("ApiResponse");
1189
+ if (apiResp) {
1190
+ const args = apiResp.getArguments();
1191
+ const optsArg = args[0];
1192
+ if (optsArg && Node.isObjectLiteralExpression(optsArg)) {
1193
+ for (const prop of optsArg.getProperties()) {
1194
+ if (Node.isPropertyAssignment(prop) && prop.getName() === "type") {
1195
+ const val = prop.getInitializer();
1196
+ if (val && Node.isIdentifier(val)) {
1197
+ const name = val.getText();
1198
+ const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
1199
+ if (localDecl && localDecl.isExported()) {
1200
+ responseRef = {
1201
+ name,
1202
+ filePath: sourceFile.getFilePath()
1203
+ };
1204
+ } else {
1205
+ const resolved = resolveImportedType(name, sourceFile, project);
1206
+ if (resolved && (resolved.kind === "class" || resolved.kind === "interface") && resolved.decl.isExported()) {
1207
+ responseRef = {
1208
+ name,
1209
+ filePath: resolved.file.getFilePath()
1210
+ };
1211
+ }
1212
+ }
1213
+ }
1214
+ }
1215
+ }
1216
+ }
1217
+ }
1218
+ }
1096
1219
  return {
1097
1220
  query,
1098
1221
  body,
1099
1222
  response,
1100
- params: paramsType
1223
+ params: paramsType,
1224
+ queryRef,
1225
+ bodyRef,
1226
+ responseRef
1101
1227
  };
1102
1228
  }
1103
1229
  __name(extractDtoContract, "extractDtoContract");
@@ -1236,7 +1362,10 @@ function extractFromSourceFile(sourceFile, project) {
1236
1362
  contractSource: {
1237
1363
  query: dtoContract.query,
1238
1364
  body: dtoContract.body,
1239
- response: dtoContract.response
1365
+ response: dtoContract.response,
1366
+ queryRef: dtoContract.queryRef,
1367
+ bodyRef: dtoContract.bodyRef,
1368
+ responseRef: dtoContract.responseRef
1240
1369
  }
1241
1370
  }
1242
1371
  } : {}
@@ -1409,7 +1538,7 @@ async function watch(config, onChange) {
1409
1538
  __name(watch, "watch");
1410
1539
 
1411
1540
  // src/index.ts
1412
- var VERSION = "2.0.1";
1541
+ var VERSION = "3.0.0";
1413
1542
  export {
1414
1543
  CodegenError,
1415
1544
  ConfigError,