@dudousxd/nestjs-inertia-codegen 1.0.0 → 1.0.4
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 +36 -0
- package/dist/cli/main.cjs +85 -34
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.js +86 -35
- package/dist/cli/main.js.map +1 -1
- package/dist/index.cjs +85 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +86 -35
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# Changelog — @dudousxd/nestjs-inertia-codegen
|
|
2
2
|
|
|
3
|
+
## 1.0.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- fix(codegen): resolve DTOs imported from separate files — cross-file class resolution via ts-morph import following
|
|
8
|
+
|
|
9
|
+
- Updated dependencies []:
|
|
10
|
+
- @dudousxd/nestjs-inertia@1.0.4
|
|
11
|
+
|
|
12
|
+
## 1.0.3
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- [`c79cc6d`](https://github.com/DavideCarvalho/nestjs-inertia/commit/c79cc6dad64342bce17c28a705ae27911c3f4c74) - Fix React Refresh preamble in @vite directive, watcher initial pass runs full discovery, auto-sync VERSION constants
|
|
17
|
+
|
|
18
|
+
- Updated dependencies [[`c79cc6d`](https://github.com/DavideCarvalho/nestjs-inertia/commit/c79cc6dad64342bce17c28a705ae27911c3f4c74)]:
|
|
19
|
+
- @dudousxd/nestjs-inertia@1.0.3
|
|
20
|
+
|
|
21
|
+
## 1.0.2
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- [`27e0bab`](https://github.com/DavideCarvalho/nestjs-inertia/commit/27e0bab4b7f8752a4dd179cc715b4e3d64161624) - Fix: @vite directive includes React Refresh preamble, watcher initial pass runs full route+contract discovery from DTOs
|
|
26
|
+
|
|
27
|
+
- Updated dependencies [[`27e0bab`](https://github.com/DavideCarvalho/nestjs-inertia/commit/27e0bab4b7f8752a4dd179cc715b4e3d64161624)]:
|
|
28
|
+
- @dudousxd/nestjs-inertia@1.0.2
|
|
29
|
+
|
|
30
|
+
## 1.0.1
|
|
31
|
+
|
|
32
|
+
### Patch Changes
|
|
33
|
+
|
|
34
|
+
- [`a33c81b`](https://github.com/DavideCarvalho/nestjs-inertia/commit/a33c81b0a53077559b1f9433824cfaee1b01c80c) - Fix: @vite directive includes React Refresh preamble in dev, watcher initial pass runs full route+contract discovery
|
|
35
|
+
|
|
36
|
+
- Updated dependencies [[`a33c81b`](https://github.com/DavideCarvalho/nestjs-inertia/commit/a33c81b0a53077559b1f9433824cfaee1b01c80c)]:
|
|
37
|
+
- @dudousxd/nestjs-inertia@1.0.1
|
|
38
|
+
|
|
3
39
|
## 1.0.0
|
|
4
40
|
|
|
5
41
|
### Minor Changes
|
package/dist/cli/main.cjs
CHANGED
|
@@ -713,7 +713,7 @@ async function discoverContractsFast(opts) {
|
|
|
713
713
|
}
|
|
714
714
|
const routes = [];
|
|
715
715
|
for (const sourceFile of project.getSourceFiles()) {
|
|
716
|
-
routes.push(...extractFromSourceFile(sourceFile));
|
|
716
|
+
routes.push(...extractFromSourceFile(sourceFile, project));
|
|
717
717
|
}
|
|
718
718
|
return routes;
|
|
719
719
|
}
|
|
@@ -878,11 +878,50 @@ function extractParams(path) {
|
|
|
878
878
|
}));
|
|
879
879
|
}
|
|
880
880
|
__name(extractParams, "extractParams");
|
|
881
|
-
function
|
|
881
|
+
function resolveImportedClass(name, sourceFile, project) {
|
|
882
|
+
for (const importDecl of sourceFile.getImportDeclarations()) {
|
|
883
|
+
const namedImport = importDecl.getNamedImports().find((n) => n.getName() === name);
|
|
884
|
+
if (!namedImport) continue;
|
|
885
|
+
const moduleSpecifier = importDecl.getModuleSpecifierValue();
|
|
886
|
+
if (!moduleSpecifier.startsWith(".")) return null;
|
|
887
|
+
const dir = (0, import_node_path8.dirname)(sourceFile.getFilePath());
|
|
888
|
+
const candidates = [
|
|
889
|
+
(0, import_node_path8.resolve)(dir, `${moduleSpecifier}.ts`),
|
|
890
|
+
(0, import_node_path8.resolve)(dir, moduleSpecifier, "index.ts")
|
|
891
|
+
];
|
|
892
|
+
for (const candidate of candidates) {
|
|
893
|
+
let importedFile = project.getSourceFile(candidate);
|
|
894
|
+
if (!importedFile) {
|
|
895
|
+
try {
|
|
896
|
+
importedFile = project.addSourceFileAtPath(candidate);
|
|
897
|
+
} catch {
|
|
898
|
+
continue;
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
const cls = importedFile.getClass(name);
|
|
902
|
+
if (cls) return {
|
|
903
|
+
cls,
|
|
904
|
+
file: importedFile
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
return null;
|
|
909
|
+
}
|
|
910
|
+
__name(resolveImportedClass, "resolveImportedClass");
|
|
911
|
+
function findClass(name, sourceFile, project) {
|
|
912
|
+
const local = sourceFile.getClass(name);
|
|
913
|
+
if (local) return {
|
|
914
|
+
cls: local,
|
|
915
|
+
file: sourceFile
|
|
916
|
+
};
|
|
917
|
+
return resolveImportedClass(name, sourceFile, project);
|
|
918
|
+
}
|
|
919
|
+
__name(findClass, "findClass");
|
|
920
|
+
function resolveTypeNodeToString(typeNode, sourceFile, project, depth) {
|
|
882
921
|
if (depth <= 0) return "unknown";
|
|
883
922
|
if (import_ts_morph.Node.isArrayTypeNode(typeNode)) {
|
|
884
923
|
const elementType = typeNode.getElementTypeNode();
|
|
885
|
-
return `Array<${resolveTypeNodeToString(elementType, sourceFile, depth)}>`;
|
|
924
|
+
return `Array<${resolveTypeNodeToString(elementType, sourceFile, project, depth)}>`;
|
|
886
925
|
}
|
|
887
926
|
if (import_ts_morph.Node.isTypeReference(typeNode)) {
|
|
888
927
|
const typeName = typeNode.getTypeName();
|
|
@@ -894,7 +933,7 @@ function resolveTypeNodeToString(typeNode, sourceFile, depth) {
|
|
|
894
933
|
const typeArgs = typeNode.getTypeArguments();
|
|
895
934
|
const firstTypeArg = typeArgs[0];
|
|
896
935
|
if (typeArgs.length > 0 && firstTypeArg !== void 0) {
|
|
897
|
-
return `Array<${resolveTypeNodeToString(firstTypeArg, sourceFile, depth)}>`;
|
|
936
|
+
return `Array<${resolveTypeNodeToString(firstTypeArg, sourceFile, project, depth)}>`;
|
|
898
937
|
}
|
|
899
938
|
return "Array<unknown>";
|
|
900
939
|
}
|
|
@@ -902,13 +941,13 @@ function resolveTypeNodeToString(typeNode, sourceFile, depth) {
|
|
|
902
941
|
const typeArgs = typeNode.getTypeArguments();
|
|
903
942
|
const firstTypeArg = typeArgs[0];
|
|
904
943
|
if (typeArgs.length > 0 && firstTypeArg !== void 0) {
|
|
905
|
-
return resolveTypeNodeToString(firstTypeArg, sourceFile, depth);
|
|
944
|
+
return resolveTypeNodeToString(firstTypeArg, sourceFile, project, depth);
|
|
906
945
|
}
|
|
907
946
|
return "unknown";
|
|
908
947
|
}
|
|
909
|
-
const
|
|
910
|
-
if (
|
|
911
|
-
return resolveClassDeclaration(
|
|
948
|
+
const resolved = findClass(name, sourceFile, project);
|
|
949
|
+
if (resolved) {
|
|
950
|
+
return resolveClassDeclaration(resolved.cls, resolved.file, project, depth - 1);
|
|
912
951
|
}
|
|
913
952
|
return name;
|
|
914
953
|
}
|
|
@@ -921,7 +960,7 @@ function resolveTypeNodeToString(typeNode, sourceFile, depth) {
|
|
|
921
960
|
return typeNode.getText();
|
|
922
961
|
}
|
|
923
962
|
__name(resolveTypeNodeToString, "resolveTypeNodeToString");
|
|
924
|
-
function resolveClassDeclaration(cls, sourceFile, depth) {
|
|
963
|
+
function resolveClassDeclaration(cls, sourceFile, project, depth) {
|
|
925
964
|
if (depth < 0) return "unknown";
|
|
926
965
|
const lines = [];
|
|
927
966
|
for (const prop of cls.getProperties()) {
|
|
@@ -930,14 +969,14 @@ function resolveClassDeclaration(cls, sourceFile, depth) {
|
|
|
930
969
|
const propTypeNode = prop.getTypeNode();
|
|
931
970
|
let propType = "unknown";
|
|
932
971
|
if (propTypeNode) {
|
|
933
|
-
propType = resolveTypeNodeToString(propTypeNode, sourceFile, depth);
|
|
972
|
+
propType = resolveTypeNodeToString(propTypeNode, sourceFile, project, depth);
|
|
934
973
|
}
|
|
935
974
|
lines.push(`${propName}${isOptional ? "?" : ""}: ${propType}`);
|
|
936
975
|
}
|
|
937
976
|
return `{ ${lines.join("; ")} }`;
|
|
938
977
|
}
|
|
939
978
|
__name(resolveClassDeclaration, "resolveClassDeclaration");
|
|
940
|
-
function extractBodyType(method, sourceFile) {
|
|
979
|
+
function extractBodyType(method, sourceFile, project) {
|
|
941
980
|
for (const param of method.getParameters()) {
|
|
942
981
|
const bodyDecorator = param.getDecorators().find((d) => d.getName() === "Body");
|
|
943
982
|
if (!bodyDecorator) continue;
|
|
@@ -945,13 +984,13 @@ function extractBodyType(method, sourceFile) {
|
|
|
945
984
|
if (bodyArgs.length > 0) continue;
|
|
946
985
|
const typeNode = param.getTypeNode();
|
|
947
986
|
if (typeNode) {
|
|
948
|
-
return resolveTypeNodeToString(typeNode, sourceFile, 3);
|
|
987
|
+
return resolveTypeNodeToString(typeNode, sourceFile, project, 3);
|
|
949
988
|
}
|
|
950
989
|
}
|
|
951
990
|
return null;
|
|
952
991
|
}
|
|
953
992
|
__name(extractBodyType, "extractBodyType");
|
|
954
|
-
function extractQueryType(method, sourceFile) {
|
|
993
|
+
function extractQueryType(method, sourceFile, project) {
|
|
955
994
|
for (const param of method.getParameters()) {
|
|
956
995
|
const queryDecorator = param.getDecorators().find((d) => d.getName() === "Query");
|
|
957
996
|
if (!queryDecorator) continue;
|
|
@@ -959,13 +998,13 @@ function extractQueryType(method, sourceFile) {
|
|
|
959
998
|
if (queryArgs.length > 0) continue;
|
|
960
999
|
const typeNode = param.getTypeNode();
|
|
961
1000
|
if (typeNode) {
|
|
962
|
-
return resolveTypeNodeToString(typeNode, sourceFile, 3);
|
|
1001
|
+
return resolveTypeNodeToString(typeNode, sourceFile, project, 3);
|
|
963
1002
|
}
|
|
964
1003
|
}
|
|
965
1004
|
return null;
|
|
966
1005
|
}
|
|
967
1006
|
__name(extractQueryType, "extractQueryType");
|
|
968
|
-
function extractParamsType(method, sourceFile) {
|
|
1007
|
+
function extractParamsType(method, sourceFile, project) {
|
|
969
1008
|
const entries = [];
|
|
970
1009
|
for (const param of method.getParameters()) {
|
|
971
1010
|
const paramDecorator = param.getDecorators().find((d) => d.getName() === "Param");
|
|
@@ -976,13 +1015,13 @@ function extractParamsType(method, sourceFile) {
|
|
|
976
1015
|
if (!import_ts_morph.Node.isStringLiteral(nameArg)) continue;
|
|
977
1016
|
const paramName = nameArg.getLiteralValue();
|
|
978
1017
|
const typeNode = param.getTypeNode();
|
|
979
|
-
const paramType = typeNode ? resolveTypeNodeToString(typeNode, sourceFile, 3) : "string";
|
|
1018
|
+
const paramType = typeNode ? resolveTypeNodeToString(typeNode, sourceFile, project, 3) : "string";
|
|
980
1019
|
entries.push(`${paramName}: ${paramType}`);
|
|
981
1020
|
}
|
|
982
1021
|
return entries.length > 0 ? `{ ${entries.join("; ")} }` : null;
|
|
983
1022
|
}
|
|
984
1023
|
__name(extractParamsType, "extractParamsType");
|
|
985
|
-
function extractResponseType(method, sourceFile) {
|
|
1024
|
+
function extractResponseType(method, sourceFile, project) {
|
|
986
1025
|
const apiResponseDecorator = method.getDecorator("ApiResponse");
|
|
987
1026
|
if (apiResponseDecorator) {
|
|
988
1027
|
const args = apiResponseDecorator.getArguments();
|
|
@@ -997,37 +1036,37 @@ function extractResponseType(method, sourceFile) {
|
|
|
997
1036
|
const elements = val.getElements();
|
|
998
1037
|
const firstEl = elements[0];
|
|
999
1038
|
if (elements.length > 0 && firstEl !== void 0) {
|
|
1000
|
-
const innerType = resolveIdentifierToClassType(firstEl, sourceFile, 3);
|
|
1039
|
+
const innerType = resolveIdentifierToClassType(firstEl, sourceFile, project, 3);
|
|
1001
1040
|
return `Array<${innerType}>`;
|
|
1002
1041
|
}
|
|
1003
1042
|
return "Array<unknown>";
|
|
1004
1043
|
}
|
|
1005
|
-
return resolveIdentifierToClassType(val, sourceFile, 3);
|
|
1044
|
+
return resolveIdentifierToClassType(val, sourceFile, project, 3);
|
|
1006
1045
|
}
|
|
1007
1046
|
}
|
|
1008
1047
|
}
|
|
1009
1048
|
const returnTypeNode = method.getReturnTypeNode();
|
|
1010
1049
|
if (returnTypeNode) {
|
|
1011
|
-
return resolveTypeNodeToString(returnTypeNode, sourceFile, 3);
|
|
1050
|
+
return resolveTypeNodeToString(returnTypeNode, sourceFile, project, 3);
|
|
1012
1051
|
}
|
|
1013
1052
|
return "unknown";
|
|
1014
1053
|
}
|
|
1015
1054
|
__name(extractResponseType, "extractResponseType");
|
|
1016
|
-
function resolveIdentifierToClassType(node, sourceFile, depth) {
|
|
1055
|
+
function resolveIdentifierToClassType(node, sourceFile, project, depth) {
|
|
1017
1056
|
if (!import_ts_morph.Node.isIdentifier(node)) return "unknown";
|
|
1018
1057
|
const name = node.getText();
|
|
1019
|
-
const
|
|
1020
|
-
if (
|
|
1021
|
-
return resolveClassDeclaration(
|
|
1058
|
+
const resolved = findClass(name, sourceFile, project);
|
|
1059
|
+
if (resolved) {
|
|
1060
|
+
return resolveClassDeclaration(resolved.cls, resolved.file, project, depth - 1);
|
|
1022
1061
|
}
|
|
1023
1062
|
return name;
|
|
1024
1063
|
}
|
|
1025
1064
|
__name(resolveIdentifierToClassType, "resolveIdentifierToClassType");
|
|
1026
|
-
function extractDtoContract(method, sourceFile) {
|
|
1027
|
-
const body = extractBodyType(method, sourceFile);
|
|
1028
|
-
const query = extractQueryType(method, sourceFile);
|
|
1029
|
-
const paramsType = extractParamsType(method, sourceFile);
|
|
1030
|
-
const response = extractResponseType(method, sourceFile);
|
|
1065
|
+
function extractDtoContract(method, sourceFile, project) {
|
|
1066
|
+
const body = extractBodyType(method, sourceFile, project);
|
|
1067
|
+
const query = extractQueryType(method, sourceFile, project);
|
|
1068
|
+
const paramsType = extractParamsType(method, sourceFile, project);
|
|
1069
|
+
const response = extractResponseType(method, sourceFile, project);
|
|
1031
1070
|
if (body === null && query === null && paramsType === null && response === "unknown") {
|
|
1032
1071
|
return null;
|
|
1033
1072
|
}
|
|
@@ -1049,7 +1088,7 @@ var HTTP_METHOD_DECORATORS = {
|
|
|
1049
1088
|
Head: "HEAD",
|
|
1050
1089
|
All: "ALL"
|
|
1051
1090
|
};
|
|
1052
|
-
function extractFromSourceFile(sourceFile) {
|
|
1091
|
+
function extractFromSourceFile(sourceFile, project) {
|
|
1053
1092
|
const routes = [];
|
|
1054
1093
|
const seenNames = /* @__PURE__ */ new Map();
|
|
1055
1094
|
const classes = sourceFile.getClasses();
|
|
@@ -1148,7 +1187,7 @@ function extractFromSourceFile(sourceFile) {
|
|
|
1148
1187
|
const params = extractParams(combined);
|
|
1149
1188
|
const methodName = method.getName();
|
|
1150
1189
|
const routeName = `${className}.${methodName}`;
|
|
1151
|
-
const dtoContract = extractDtoContract(method, sourceFile);
|
|
1190
|
+
const dtoContract = extractDtoContract(method, sourceFile, project);
|
|
1152
1191
|
routes.push({
|
|
1153
1192
|
method: httpMethod,
|
|
1154
1193
|
path: combined,
|
|
@@ -1235,8 +1274,20 @@ async function watch(config, onChange) {
|
|
|
1235
1274
|
return NO_OP_WATCHER;
|
|
1236
1275
|
}
|
|
1237
1276
|
try {
|
|
1238
|
-
await
|
|
1239
|
-
|
|
1277
|
+
const initialRoutes = await discoverContractsFast({
|
|
1278
|
+
cwd: config.codegen.cwd,
|
|
1279
|
+
glob: config.contracts.glob,
|
|
1280
|
+
...config.app?.tsconfig ? {
|
|
1281
|
+
tsconfig: config.app.tsconfig
|
|
1282
|
+
} : {}
|
|
1283
|
+
});
|
|
1284
|
+
await generate(config, initialRoutes);
|
|
1285
|
+
} catch (err) {
|
|
1286
|
+
console.warn(`[nestjs-inertia-codegen] Initial route discovery failed, falling back to pages-only: ${err instanceof Error ? err.message : String(err)}`);
|
|
1287
|
+
try {
|
|
1288
|
+
await generate(config);
|
|
1289
|
+
} catch {
|
|
1290
|
+
}
|
|
1240
1291
|
}
|
|
1241
1292
|
let pagesDebounceTimer;
|
|
1242
1293
|
const pagesWatcher = import_chokidar.default.watch((0, import_node_path10.join)(config.codegen.cwd, config.pages.glob), {
|
|
@@ -1321,7 +1372,7 @@ async function watch(config, onChange) {
|
|
|
1321
1372
|
__name(watch, "watch");
|
|
1322
1373
|
|
|
1323
1374
|
// src/index.ts
|
|
1324
|
-
var VERSION = "1.0.
|
|
1375
|
+
var VERSION = "1.0.4";
|
|
1325
1376
|
|
|
1326
1377
|
// src/cli/codegen.ts
|
|
1327
1378
|
async function runCodegen(opts = {}) {
|