@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/cli/main.js CHANGED
@@ -185,12 +185,12 @@ __name(extractPropsSource, "extractPropsSource");
185
185
 
186
186
  // src/emit/emit-api.ts
187
187
  import { mkdir, writeFile } from "fs/promises";
188
- import { join as join2 } from "path";
188
+ import { join as join2, relative as relative3 } from "path";
189
189
  async function emitApi(routes, outDir) {
190
190
  await mkdir(outDir, {
191
191
  recursive: true
192
192
  });
193
- const content = buildApiFile(routes);
193
+ const content = buildApiFile(routes, outDir);
194
194
  await writeFile(join2(outDir, "api.ts"), content, "utf8");
195
195
  }
196
196
  __name(emitApi, "emitApi");
@@ -263,9 +263,9 @@ function emitRouterTypeBlock(tree, indent) {
263
263
  if (node.kind === "leaf") {
264
264
  const c = node;
265
265
  const method = c.method.toUpperCase();
266
- const query = c.contractSource.query ?? "never";
267
- const body = method === "GET" ? "never" : c.contractSource.body ?? "never";
268
- const response = c.contractSource.response;
266
+ const query = c.contractSource.queryRef ? c.contractSource.queryRef.name : c.contractSource.query ?? "never";
267
+ const body = method === "GET" ? "never" : c.contractSource.bodyRef ? c.contractSource.bodyRef.name : c.contractSource.body ?? "never";
268
+ const response = c.contractSource.responseRef ? c.contractSource.responseRef.name : c.contractSource.response;
269
269
  const safeMethod = JSON.stringify(method);
270
270
  const safeUrl = JSON.stringify(c.path);
271
271
  lines.push(`${pad}${objKey}: { method: ${safeMethod}; url: ${safeUrl}; query: ${query}; body: ${body}; response: ${response} };`);
@@ -321,14 +321,43 @@ function buildRouterTypeAccess(name) {
321
321
  return `ApiRouter${segments.map((s) => `[${JSON.stringify(s)}]`).join("")}`;
322
322
  }
323
323
  __name(buildRouterTypeAccess, "buildRouterTypeAccess");
324
- function buildApiFile(routes) {
324
+ function buildApiFile(routes, outDir) {
325
325
  const contracted = routes.filter((r) => r.contract);
326
+ const importsByFile = /* @__PURE__ */ new Map();
327
+ for (const r of contracted) {
328
+ const cs = r.contract?.contractSource;
329
+ if (!cs) continue;
330
+ for (const ref of [
331
+ cs.queryRef,
332
+ cs.bodyRef,
333
+ cs.responseRef
334
+ ]) {
335
+ if (!ref) continue;
336
+ let names = importsByFile.get(ref.filePath);
337
+ if (!names) {
338
+ names = /* @__PURE__ */ new Set();
339
+ importsByFile.set(ref.filePath, names);
340
+ }
341
+ names.add(ref.name);
342
+ }
343
+ }
326
344
  const lines = [
327
345
  "// Generated by @dudousxd/nestjs-inertia-codegen. Do not edit.",
328
346
  ""
329
347
  ];
330
348
  lines.push("import { route } from './routes.js';");
331
349
  lines.push("import { createFetcher } from '@dudousxd/nestjs-inertia-client';");
350
+ if (importsByFile.size > 0 && outDir) {
351
+ lines.push("");
352
+ for (const [filePath, names] of importsByFile) {
353
+ let relPath = relative3(outDir, filePath).replace(/\.ts$/, "");
354
+ if (!relPath.startsWith(".")) relPath = `./${relPath}`;
355
+ const sortedNames = [
356
+ ...names
357
+ ].sort();
358
+ lines.push(`import type { ${sortedNames.join(", ")} } from '${relPath}';`);
359
+ }
360
+ }
332
361
  lines.push("");
333
362
  lines.push("export const fetcher = createFetcher();");
334
363
  lines.push("");
@@ -1073,6 +1102,53 @@ function resolveIdentifierToClassType(node, sourceFile, project, depth) {
1073
1102
  return name;
1074
1103
  }
1075
1104
  __name(resolveIdentifierToClassType, "resolveIdentifierToClassType");
1105
+ function tryResolveTypeRef(typeNode, sourceFile, project) {
1106
+ if (Node.isTypeReference(typeNode)) {
1107
+ const typeName = typeNode.getTypeName();
1108
+ const name = Node.isIdentifier(typeName) ? typeName.getText() : null;
1109
+ if (!name) return null;
1110
+ if (name === "Promise") {
1111
+ const typeArgs = typeNode.getTypeArguments();
1112
+ const first = typeArgs[0];
1113
+ if (first) return tryResolveTypeRef(first, sourceFile, project);
1114
+ return null;
1115
+ }
1116
+ if ([
1117
+ "string",
1118
+ "number",
1119
+ "boolean",
1120
+ "void",
1121
+ "unknown",
1122
+ "any",
1123
+ "Date",
1124
+ "Array"
1125
+ ].includes(name)) {
1126
+ return null;
1127
+ }
1128
+ const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
1129
+ if (localDecl && localDecl.isExported()) {
1130
+ return {
1131
+ name,
1132
+ filePath: sourceFile.getFilePath()
1133
+ };
1134
+ }
1135
+ const resolved = resolveImportedType(name, sourceFile, project);
1136
+ if (resolved && (resolved.kind === "class" || resolved.kind === "interface")) {
1137
+ const decl = resolved.decl;
1138
+ if (decl.isExported()) {
1139
+ return {
1140
+ name,
1141
+ filePath: resolved.file.getFilePath()
1142
+ };
1143
+ }
1144
+ }
1145
+ }
1146
+ if (Node.isArrayTypeNode(typeNode)) {
1147
+ return tryResolveTypeRef(typeNode.getElementTypeNode(), sourceFile, project);
1148
+ }
1149
+ return null;
1150
+ }
1151
+ __name(tryResolveTypeRef, "tryResolveTypeRef");
1076
1152
  function extractDtoContract(method, sourceFile, project) {
1077
1153
  const body = extractBodyType(method, sourceFile, project);
1078
1154
  const query = extractQueryType(method, sourceFile, project);
@@ -1081,11 +1157,61 @@ function extractDtoContract(method, sourceFile, project) {
1081
1157
  if (body === null && query === null && paramsType === null && response === "unknown") {
1082
1158
  return null;
1083
1159
  }
1160
+ let bodyRef = null;
1161
+ let queryRef = null;
1162
+ let responseRef = null;
1163
+ for (const param of method.getParameters()) {
1164
+ if (param.getDecorators().some((d) => d.getName() === "Body") && param.getTypeNode()) {
1165
+ bodyRef = tryResolveTypeRef(param.getTypeNode(), sourceFile, project);
1166
+ }
1167
+ if (param.getDecorators().some((d) => d.getName() === "Query") && param.getTypeNode()) {
1168
+ queryRef = tryResolveTypeRef(param.getTypeNode(), sourceFile, project);
1169
+ }
1170
+ }
1171
+ const returnTypeNode = method.getReturnTypeNode();
1172
+ if (returnTypeNode) {
1173
+ responseRef = tryResolveTypeRef(returnTypeNode, sourceFile, project);
1174
+ }
1175
+ if (!responseRef) {
1176
+ const apiResp = method.getDecorator("ApiResponse");
1177
+ if (apiResp) {
1178
+ const args = apiResp.getArguments();
1179
+ const optsArg = args[0];
1180
+ if (optsArg && Node.isObjectLiteralExpression(optsArg)) {
1181
+ for (const prop of optsArg.getProperties()) {
1182
+ if (Node.isPropertyAssignment(prop) && prop.getName() === "type") {
1183
+ const val = prop.getInitializer();
1184
+ if (val && Node.isIdentifier(val)) {
1185
+ const name = val.getText();
1186
+ const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
1187
+ if (localDecl && localDecl.isExported()) {
1188
+ responseRef = {
1189
+ name,
1190
+ filePath: sourceFile.getFilePath()
1191
+ };
1192
+ } else {
1193
+ const resolved = resolveImportedType(name, sourceFile, project);
1194
+ if (resolved && (resolved.kind === "class" || resolved.kind === "interface") && resolved.decl.isExported()) {
1195
+ responseRef = {
1196
+ name,
1197
+ filePath: resolved.file.getFilePath()
1198
+ };
1199
+ }
1200
+ }
1201
+ }
1202
+ }
1203
+ }
1204
+ }
1205
+ }
1206
+ }
1084
1207
  return {
1085
1208
  query,
1086
1209
  body,
1087
1210
  response,
1088
- params: paramsType
1211
+ params: paramsType,
1212
+ queryRef,
1213
+ bodyRef,
1214
+ responseRef
1089
1215
  };
1090
1216
  }
1091
1217
  __name(extractDtoContract, "extractDtoContract");
@@ -1224,7 +1350,10 @@ function extractFromSourceFile(sourceFile, project) {
1224
1350
  contractSource: {
1225
1351
  query: dtoContract.query,
1226
1352
  body: dtoContract.body,
1227
- response: dtoContract.response
1353
+ response: dtoContract.response,
1354
+ queryRef: dtoContract.queryRef,
1355
+ bodyRef: dtoContract.bodyRef,
1356
+ responseRef: dtoContract.responseRef
1228
1357
  }
1229
1358
  }
1230
1359
  } : {}
@@ -1397,7 +1526,7 @@ async function watch(config, onChange) {
1397
1526
  __name(watch, "watch");
1398
1527
 
1399
1528
  // src/index.ts
1400
- var VERSION = "2.0.1";
1529
+ var VERSION = "3.0.0";
1401
1530
 
1402
1531
  // src/cli/codegen.ts
1403
1532
  async function runCodegen(opts = {}) {