@dudousxd/nestjs-inertia-codegen 2.0.0 → 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/CHANGELOG.md +20 -0
- package/dist/cli/main.cjs +141 -17
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.js +142 -18
- package/dist/cli/main.js.map +1 -1
- package/dist/index.cjs +141 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +142 -18
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
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 = "
|
|
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 = "
|
|
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} };`);
|
|
@@ -305,11 +305,10 @@ function emitApiObjectBlock(tree, indent) {
|
|
|
305
305
|
const typeAccess = buildRouterTypeAccess(c.name);
|
|
306
306
|
lines.push(`${pad}${objKey}: {`);
|
|
307
307
|
lines.push(`${pad} queryKey: (query?: ${typeAccess}['query']) => query !== undefined ? [${flatName}, query] as const : [${flatName}] as const,`);
|
|
308
|
-
lines.push(`${pad} queryOptions: (query?: ${typeAccess}['query'])
|
|
309
|
-
lines.push(`${pad}
|
|
310
|
-
lines.push(`${pad}
|
|
311
|
-
lines.push(`${pad}
|
|
312
|
-
lines.push(`${pad} }),`);
|
|
308
|
+
lines.push(`${pad} queryOptions: (query?: ${typeAccess}['query']) => ({`);
|
|
309
|
+
lines.push(`${pad} queryKey: query !== undefined ? [${flatName}, query] as const : [${flatName}] as const,`);
|
|
310
|
+
lines.push(`${pad} queryFn: () => fetcher.get<${typeAccess}['response']>(route(${flatName} as never) || ${safePath}, { query }),`);
|
|
311
|
+
lines.push(`${pad} }),`);
|
|
313
312
|
lines.push(`${pad}},`);
|
|
314
313
|
} else {
|
|
315
314
|
const typeAccess = buildRouterTypeAccess(c.name);
|
|
@@ -334,18 +333,43 @@ function buildRouterTypeAccess(name) {
|
|
|
334
333
|
return `ApiRouter${segments.map((s) => `[${JSON.stringify(s)}]`).join("")}`;
|
|
335
334
|
}
|
|
336
335
|
__name(buildRouterTypeAccess, "buildRouterTypeAccess");
|
|
337
|
-
function buildApiFile(routes) {
|
|
336
|
+
function buildApiFile(routes, outDir) {
|
|
338
337
|
const contracted = routes.filter((r) => r.contract);
|
|
339
|
-
const
|
|
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
|
+
}
|
|
340
356
|
const lines = [
|
|
341
357
|
"// Generated by @dudousxd/nestjs-inertia-codegen. Do not edit.",
|
|
342
358
|
""
|
|
343
359
|
];
|
|
344
|
-
if (hasGetRoutes) {
|
|
345
|
-
lines.push("import { queryOptions } from '@tanstack/query-core';");
|
|
346
|
-
}
|
|
347
360
|
lines.push("import { route } from './routes.js';");
|
|
348
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
|
+
}
|
|
349
373
|
lines.push("");
|
|
350
374
|
lines.push("export const fetcher = createFetcher();");
|
|
351
375
|
lines.push("");
|
|
@@ -1090,6 +1114,53 @@ function resolveIdentifierToClassType(node, sourceFile, project, depth) {
|
|
|
1090
1114
|
return name;
|
|
1091
1115
|
}
|
|
1092
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");
|
|
1093
1164
|
function extractDtoContract(method, sourceFile, project) {
|
|
1094
1165
|
const body = extractBodyType(method, sourceFile, project);
|
|
1095
1166
|
const query = extractQueryType(method, sourceFile, project);
|
|
@@ -1098,11 +1169,61 @@ function extractDtoContract(method, sourceFile, project) {
|
|
|
1098
1169
|
if (body === null && query === null && paramsType === null && response === "unknown") {
|
|
1099
1170
|
return null;
|
|
1100
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
|
+
}
|
|
1101
1219
|
return {
|
|
1102
1220
|
query,
|
|
1103
1221
|
body,
|
|
1104
1222
|
response,
|
|
1105
|
-
params: paramsType
|
|
1223
|
+
params: paramsType,
|
|
1224
|
+
queryRef,
|
|
1225
|
+
bodyRef,
|
|
1226
|
+
responseRef
|
|
1106
1227
|
};
|
|
1107
1228
|
}
|
|
1108
1229
|
__name(extractDtoContract, "extractDtoContract");
|
|
@@ -1241,7 +1362,10 @@ function extractFromSourceFile(sourceFile, project) {
|
|
|
1241
1362
|
contractSource: {
|
|
1242
1363
|
query: dtoContract.query,
|
|
1243
1364
|
body: dtoContract.body,
|
|
1244
|
-
response: dtoContract.response
|
|
1365
|
+
response: dtoContract.response,
|
|
1366
|
+
queryRef: dtoContract.queryRef,
|
|
1367
|
+
bodyRef: dtoContract.bodyRef,
|
|
1368
|
+
responseRef: dtoContract.responseRef
|
|
1245
1369
|
}
|
|
1246
1370
|
}
|
|
1247
1371
|
} : {}
|
|
@@ -1414,7 +1538,7 @@ async function watch(config, onChange) {
|
|
|
1414
1538
|
__name(watch, "watch");
|
|
1415
1539
|
|
|
1416
1540
|
// src/index.ts
|
|
1417
|
-
var VERSION = "
|
|
1541
|
+
var VERSION = "3.0.0";
|
|
1418
1542
|
export {
|
|
1419
1543
|
CodegenError,
|
|
1420
1544
|
ConfigError,
|