@dudousxd/nestjs-codegen 0.15.0 → 0.16.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 +42 -0
- package/dist/cli/main.cjs +177 -55
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.js +176 -54
- package/dist/cli/main.js.map +1 -1
- package/dist/extension/index.d.cts +1 -1
- package/dist/extension/index.d.ts +1 -1
- package/dist/{index-CjIDPMsV.d.cts → index-LQNP7Ms3.d.cts} +23 -0
- package/dist/{index-CjIDPMsV.d.ts → index-LQNP7Ms3.d.ts} +23 -0
- package/dist/index.cjs +177 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +176 -54
- package/dist/index.js.map +1 -1
- package/dist/nest/index.cjs +176 -55
- package/dist/nest/index.cjs.map +1 -1
- package/dist/nest/index.d.cts +1 -1
- package/dist/nest/index.d.ts +1 -1
- package/dist/nest/index.js +175 -54
- package/dist/nest/index.js.map +1 -1
- package/package.json +1 -1
package/dist/nest/index.cjs
CHANGED
|
@@ -2272,7 +2272,7 @@ var import_chokidar = __toESM(require("chokidar"), 1);
|
|
|
2272
2272
|
// src/discovery/contracts-fast.ts
|
|
2273
2273
|
var import_node_path14 = require("path");
|
|
2274
2274
|
var import_fast_glob2 = __toESM(require("fast-glob"), 1);
|
|
2275
|
-
var
|
|
2275
|
+
var import_ts_morph10 = require("ts-morph");
|
|
2276
2276
|
|
|
2277
2277
|
// src/discovery/dto-type-resolver.ts
|
|
2278
2278
|
var import_ts_morph7 = require("ts-morph");
|
|
@@ -3251,6 +3251,12 @@ function toFilterFieldType(name, r) {
|
|
|
3251
3251
|
}
|
|
3252
3252
|
|
|
3253
3253
|
// src/discovery/filter-for.ts
|
|
3254
|
+
function resolveMixinEntityClass(mixin, project) {
|
|
3255
|
+
const entityArg = mixin?.classArgs[0];
|
|
3256
|
+
if (!entityArg) return void 0;
|
|
3257
|
+
const file = project.getSourceFile(entityArg.filePath) ?? project.addSourceFileAtPathIfExists(entityArg.filePath);
|
|
3258
|
+
return file?.getClass(entityArg.name);
|
|
3259
|
+
}
|
|
3254
3260
|
function classifyFilterForHint(typeInit) {
|
|
3255
3261
|
if (import_ts_morph6.Node.isStringLiteral(typeInit)) {
|
|
3256
3262
|
switch (typeInit.getLiteralValue()) {
|
|
@@ -3324,7 +3330,9 @@ function extractFilterForHints(classDecl, project) {
|
|
|
3324
3330
|
}
|
|
3325
3331
|
return hints;
|
|
3326
3332
|
}
|
|
3327
|
-
function extractApplyFilterInfo(method, sourceFile, project) {
|
|
3333
|
+
function extractApplyFilterInfo(method, sourceFile, project, mixin) {
|
|
3334
|
+
const declFile = method.getSourceFile();
|
|
3335
|
+
const mixinEntity = resolveMixinEntityClass(mixin, project);
|
|
3328
3336
|
for (const param of method.getParameters()) {
|
|
3329
3337
|
const filterDecorator = param.getDecorators().find((d) => d.getName() === "ApplyFilter");
|
|
3330
3338
|
if (!filterDecorator) continue;
|
|
@@ -3344,12 +3352,12 @@ function extractApplyFilterInfo(method, sourceFile, project) {
|
|
|
3344
3352
|
}
|
|
3345
3353
|
}
|
|
3346
3354
|
const filterClassName = filterClassArg.getText();
|
|
3347
|
-
const resolved = findType(filterClassName,
|
|
3348
|
-
|
|
3349
|
-
|
|
3355
|
+
const resolved = findType(filterClassName, declFile, project);
|
|
3356
|
+
const classDecl = resolved?.kind === "class" ? resolved.decl : resolveLocalClassDeclaration(filterClassArg);
|
|
3357
|
+
if (classDecl) {
|
|
3350
3358
|
let fieldTypes = extractClassPropertyTypes(classDecl, project);
|
|
3351
3359
|
if (fieldTypes.length === 0) {
|
|
3352
|
-
fieldTypes = extractFilterableEntityFields(classDecl, project);
|
|
3360
|
+
fieldTypes = extractFilterableEntityFields(classDecl, project, mixinEntity);
|
|
3353
3361
|
}
|
|
3354
3362
|
const filterForHints = extractFilterForHints(classDecl, project);
|
|
3355
3363
|
if (filterForHints.size > 0) {
|
|
@@ -3434,22 +3442,29 @@ function extractClassPropertyTypes(classDecl, project) {
|
|
|
3434
3442
|
}
|
|
3435
3443
|
return fields;
|
|
3436
3444
|
}
|
|
3437
|
-
function
|
|
3445
|
+
function resolveLocalClassDeclaration(identifier) {
|
|
3446
|
+
if (!import_ts_morph6.Node.isIdentifier(identifier)) return void 0;
|
|
3447
|
+
return identifier.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => n !== void 0 && import_ts_morph6.Node.isClassDeclaration(n));
|
|
3448
|
+
}
|
|
3449
|
+
function resolveDeclaredEntity(optionsArg, filterClass, project) {
|
|
3450
|
+
if (!import_ts_morph6.Node.isObjectLiteralExpression(optionsArg)) return void 0;
|
|
3451
|
+
const entityProp = optionsArg.getProperty("entity");
|
|
3452
|
+
if (!entityProp || !import_ts_morph6.Node.isPropertyAssignment(entityProp)) return void 0;
|
|
3453
|
+
const entityInit = entityProp.getInitializer();
|
|
3454
|
+
if (!entityInit || !import_ts_morph6.Node.isIdentifier(entityInit)) return void 0;
|
|
3455
|
+
const resolved = findType(entityInit.getText(), filterClass.getSourceFile(), project);
|
|
3456
|
+
if (!resolved || resolved.kind !== "class") return void 0;
|
|
3457
|
+
return resolved.decl;
|
|
3458
|
+
}
|
|
3459
|
+
function extractFilterableEntityFields(filterClass, project, entityOverride) {
|
|
3438
3460
|
const filterableDecorator = filterClass.getDecorators().find((d) => d.getName() === "Filterable");
|
|
3439
3461
|
if (!filterableDecorator) return [];
|
|
3440
3462
|
const args = filterableDecorator.getArguments();
|
|
3441
3463
|
if (args.length === 0) return [];
|
|
3442
3464
|
const optionsArg = args[0];
|
|
3443
3465
|
if (!import_ts_morph6.Node.isObjectLiteralExpression(optionsArg)) return [];
|
|
3444
|
-
const
|
|
3445
|
-
if (!
|
|
3446
|
-
const entityInit = entityProp.getInitializer();
|
|
3447
|
-
if (!entityInit || !import_ts_morph6.Node.isIdentifier(entityInit)) return [];
|
|
3448
|
-
const entityName = entityInit.getText();
|
|
3449
|
-
const filterSourceFile = filterClass.getSourceFile();
|
|
3450
|
-
const resolvedEntity = findType(entityName, filterSourceFile, project);
|
|
3451
|
-
if (!resolvedEntity || resolvedEntity.kind !== "class") return [];
|
|
3452
|
-
const entityDecl = resolvedEntity.decl;
|
|
3466
|
+
const entityDecl = entityOverride ?? resolveDeclaredEntity(optionsArg, filterClass, project);
|
|
3467
|
+
if (!entityDecl) return [];
|
|
3453
3468
|
const fields = collectEntityFields(
|
|
3454
3469
|
entityDecl,
|
|
3455
3470
|
entityDecl.getSourceFile(),
|
|
@@ -3874,9 +3889,9 @@ function unwrapNamedContainer(node, names) {
|
|
|
3874
3889
|
}
|
|
3875
3890
|
return node;
|
|
3876
3891
|
}
|
|
3877
|
-
function extractDtoContract(method, sourceFile, project) {
|
|
3892
|
+
function extractDtoContract(method, sourceFile, project, mixin) {
|
|
3878
3893
|
let body = extractBodyType(method, sourceFile, project);
|
|
3879
|
-
const filterInfo = extractApplyFilterInfo(method, sourceFile, project);
|
|
3894
|
+
const filterInfo = extractApplyFilterInfo(method, sourceFile, project, mixin);
|
|
3880
3895
|
const query = extractQueryType(method, sourceFile, project);
|
|
3881
3896
|
const uploads = extractUploadedFiles(method);
|
|
3882
3897
|
const multipartBody = uploads.fields ? `{ ${uploads.fields} }` : null;
|
|
@@ -3986,12 +4001,94 @@ function resolveParamClass(method, decoratorName, sourceFile, project) {
|
|
|
3986
4001
|
return null;
|
|
3987
4002
|
}
|
|
3988
4003
|
|
|
3989
|
-
// src/discovery/
|
|
4004
|
+
// src/discovery/heritage.ts
|
|
3990
4005
|
var import_ts_morph8 = require("ts-morph");
|
|
4006
|
+
function unwrapExpression(node) {
|
|
4007
|
+
let current = node;
|
|
4008
|
+
while (import_ts_morph8.Node.isAsExpression(current) || import_ts_morph8.Node.isSatisfiesExpression(current) || import_ts_morph8.Node.isParenthesizedExpression(current) || import_ts_morph8.Node.isTypeAssertion(current)) {
|
|
4009
|
+
current = current.getExpression();
|
|
4010
|
+
}
|
|
4011
|
+
return current;
|
|
4012
|
+
}
|
|
4013
|
+
function resolveReturnedClass(factoryDecl) {
|
|
4014
|
+
const body = factoryDecl.getBody();
|
|
4015
|
+
if (!body) return void 0;
|
|
4016
|
+
const returns = body.getDescendants().filter((n) => import_ts_morph8.Node.isReturnStatement(n));
|
|
4017
|
+
for (const ret of returns) {
|
|
4018
|
+
const expr = ret.getExpression();
|
|
4019
|
+
if (!expr) continue;
|
|
4020
|
+
const inner = unwrapExpression(expr);
|
|
4021
|
+
if (import_ts_morph8.Node.isClassExpression(inner)) {
|
|
4022
|
+
return inner;
|
|
4023
|
+
}
|
|
4024
|
+
if (import_ts_morph8.Node.isIdentifier(inner)) {
|
|
4025
|
+
const name = inner.getText();
|
|
4026
|
+
const decl = body.getDescendants().find((n) => import_ts_morph8.Node.isClassDeclaration(n) && n.getName() === name);
|
|
4027
|
+
if (decl) return decl;
|
|
4028
|
+
}
|
|
4029
|
+
}
|
|
4030
|
+
return void 0;
|
|
4031
|
+
}
|
|
4032
|
+
function resolveInheritedMethods(cls) {
|
|
4033
|
+
const expr = cls.getExtends()?.getExpression();
|
|
4034
|
+
if (!expr || !import_ts_morph8.Node.isCallExpression(expr)) return void 0;
|
|
4035
|
+
const callee = expr.getExpression();
|
|
4036
|
+
if (!import_ts_morph8.Node.isIdentifier(callee)) return void 0;
|
|
4037
|
+
const factoryDecl = callee.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => import_ts_morph8.Node.isFunctionDeclaration(n));
|
|
4038
|
+
if (!factoryDecl) return void 0;
|
|
4039
|
+
const returnedClass = resolveReturnedClass(factoryDecl);
|
|
4040
|
+
if (!returnedClass) return void 0;
|
|
4041
|
+
const classArgs = [];
|
|
4042
|
+
for (const arg of expr.getArguments()) {
|
|
4043
|
+
if (!import_ts_morph8.Node.isIdentifier(arg)) continue;
|
|
4044
|
+
const decl = arg.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => import_ts_morph8.Node.isClassDeclaration(n));
|
|
4045
|
+
if (decl) {
|
|
4046
|
+
classArgs.push({
|
|
4047
|
+
name: decl.getName() ?? arg.getText(),
|
|
4048
|
+
filePath: decl.getSourceFile().getFilePath()
|
|
4049
|
+
});
|
|
4050
|
+
}
|
|
4051
|
+
}
|
|
4052
|
+
return {
|
|
4053
|
+
methods: returnedClass.getMethods(),
|
|
4054
|
+
factoryName: callee.getText(),
|
|
4055
|
+
factoryFilePath: factoryDecl.getSourceFile().getFilePath(),
|
|
4056
|
+
classArgs
|
|
4057
|
+
};
|
|
4058
|
+
}
|
|
4059
|
+
var mixinTypeProject;
|
|
4060
|
+
function getMixinTypeProject() {
|
|
4061
|
+
mixinTypeProject ??= new import_ts_morph8.Project({
|
|
4062
|
+
skipAddingFilesFromTsConfig: true,
|
|
4063
|
+
compilerOptions: { strict: true }
|
|
4064
|
+
});
|
|
4065
|
+
return mixinTypeProject;
|
|
4066
|
+
}
|
|
4067
|
+
function clearMixinTypeProject() {
|
|
4068
|
+
mixinTypeProject = void 0;
|
|
4069
|
+
}
|
|
4070
|
+
function resolveInstantiatedReturnType(cls, methodName) {
|
|
4071
|
+
const filePath = cls.getSourceFile().getFilePath();
|
|
4072
|
+
const className = cls.getName();
|
|
4073
|
+
if (!className) return void 0;
|
|
4074
|
+
const project = getMixinTypeProject();
|
|
4075
|
+
const sourceFile = project.getSourceFile(filePath) ?? project.addSourceFileAtPathIfExists(filePath);
|
|
4076
|
+
const typedCls = sourceFile?.getClass(className);
|
|
4077
|
+
if (!typedCls) return void 0;
|
|
4078
|
+
const prop = typedCls.getType().getProperty(methodName);
|
|
4079
|
+
if (!prop) return void 0;
|
|
4080
|
+
const returnType = prop.getTypeAtLocation(typedCls).getCallSignatures()[0]?.getReturnType();
|
|
4081
|
+
if (!returnType) return void 0;
|
|
4082
|
+
const unwrapped = returnType.getSymbol()?.getName() === "Promise" ? returnType.getTypeArguments()[0] ?? returnType : returnType;
|
|
4083
|
+
return unwrapped.getText(typedCls);
|
|
4084
|
+
}
|
|
4085
|
+
|
|
4086
|
+
// src/discovery/zod-ast-to-ts.ts
|
|
4087
|
+
var import_ts_morph9 = require("ts-morph");
|
|
3991
4088
|
function zodAstToTs(node) {
|
|
3992
|
-
if (!
|
|
4089
|
+
if (!import_ts_morph9.Node.isCallExpression(node)) return "unknown";
|
|
3993
4090
|
const expr = node.getExpression();
|
|
3994
|
-
if (
|
|
4091
|
+
if (import_ts_morph9.Node.isPropertyAccessExpression(expr)) {
|
|
3995
4092
|
const methodName = expr.getName();
|
|
3996
4093
|
const receiver = expr.getExpression();
|
|
3997
4094
|
if (methodName === "optional") {
|
|
@@ -4015,17 +4112,17 @@ function zodAstToTs(node) {
|
|
|
4015
4112
|
case "literal": {
|
|
4016
4113
|
const lit = args[0];
|
|
4017
4114
|
if (!lit) return "unknown";
|
|
4018
|
-
if (
|
|
4019
|
-
if (
|
|
4020
|
-
if (lit.getKind() ===
|
|
4021
|
-
if (lit.getKind() ===
|
|
4115
|
+
if (import_ts_morph9.Node.isStringLiteral(lit)) return JSON.stringify(lit.getLiteralValue());
|
|
4116
|
+
if (import_ts_morph9.Node.isNumericLiteral(lit)) return lit.getLiteralValue().toString();
|
|
4117
|
+
if (lit.getKind() === import_ts_morph9.SyntaxKind.TrueKeyword) return "true";
|
|
4118
|
+
if (lit.getKind() === import_ts_morph9.SyntaxKind.FalseKeyword) return "false";
|
|
4022
4119
|
return "unknown";
|
|
4023
4120
|
}
|
|
4024
4121
|
case "enum": {
|
|
4025
4122
|
const arrArg = args[0];
|
|
4026
|
-
if (!arrArg || !
|
|
4123
|
+
if (!arrArg || !import_ts_morph9.Node.isArrayLiteralExpression(arrArg)) return "unknown";
|
|
4027
4124
|
const members = arrArg.getElements().map(
|
|
4028
|
-
(el) =>
|
|
4125
|
+
(el) => import_ts_morph9.Node.isStringLiteral(el) ? JSON.stringify(el.getLiteralValue()) : "unknown"
|
|
4029
4126
|
);
|
|
4030
4127
|
return members.join(" | ");
|
|
4031
4128
|
}
|
|
@@ -4036,10 +4133,10 @@ function zodAstToTs(node) {
|
|
|
4036
4133
|
}
|
|
4037
4134
|
case "object": {
|
|
4038
4135
|
const objArg = args[0];
|
|
4039
|
-
if (!objArg || !
|
|
4136
|
+
if (!objArg || !import_ts_morph9.Node.isObjectLiteralExpression(objArg)) return "unknown";
|
|
4040
4137
|
const lines = [];
|
|
4041
4138
|
for (const prop of objArg.getProperties()) {
|
|
4042
|
-
if (!
|
|
4139
|
+
if (!import_ts_morph9.Node.isPropertyAssignment(prop)) continue;
|
|
4043
4140
|
const key = prop.getName();
|
|
4044
4141
|
const valNode = prop.getInitializer();
|
|
4045
4142
|
if (!valNode) continue;
|
|
@@ -4051,7 +4148,7 @@ function zodAstToTs(node) {
|
|
|
4051
4148
|
}
|
|
4052
4149
|
case "union": {
|
|
4053
4150
|
const arrArg = args[0];
|
|
4054
|
-
if (!arrArg || !
|
|
4151
|
+
if (!arrArg || !import_ts_morph9.Node.isArrayLiteralExpression(arrArg)) return "unknown";
|
|
4055
4152
|
return arrArg.getElements().map(zodAstToTs).join(" | ");
|
|
4056
4153
|
}
|
|
4057
4154
|
case "record": {
|
|
@@ -4061,7 +4158,7 @@ function zodAstToTs(node) {
|
|
|
4061
4158
|
}
|
|
4062
4159
|
case "tuple": {
|
|
4063
4160
|
const arrArg = args[0];
|
|
4064
|
-
if (!arrArg || !
|
|
4161
|
+
if (!arrArg || !import_ts_morph9.Node.isArrayLiteralExpression(arrArg)) return "unknown";
|
|
4065
4162
|
return `[${arrArg.getElements().map(zodAstToTs).join(", ")}]`;
|
|
4066
4163
|
}
|
|
4067
4164
|
default:
|
|
@@ -4071,18 +4168,18 @@ function zodAstToTs(node) {
|
|
|
4071
4168
|
return "unknown";
|
|
4072
4169
|
}
|
|
4073
4170
|
function isOptionalChain(node) {
|
|
4074
|
-
if (!
|
|
4171
|
+
if (!import_ts_morph9.Node.isCallExpression(node)) return false;
|
|
4075
4172
|
const expr = node.getExpression();
|
|
4076
|
-
return
|
|
4173
|
+
return import_ts_morph9.Node.isPropertyAccessExpression(expr) && expr.getName() === "optional";
|
|
4077
4174
|
}
|
|
4078
4175
|
function parseDefineContractCall(callExpr) {
|
|
4079
|
-
if (!
|
|
4176
|
+
if (!import_ts_morph9.Node.isCallExpression(callExpr)) return null;
|
|
4080
4177
|
const callee = callExpr.getExpression();
|
|
4081
|
-
const calleeName =
|
|
4178
|
+
const calleeName = import_ts_morph9.Node.isIdentifier(callee) ? callee.getText() : import_ts_morph9.Node.isPropertyAccessExpression(callee) ? callee.getName() : "";
|
|
4082
4179
|
if (calleeName !== "defineContract") return null;
|
|
4083
4180
|
const args = callExpr.getArguments();
|
|
4084
4181
|
const optsArg = args[0];
|
|
4085
|
-
if (!optsArg || !
|
|
4182
|
+
if (!optsArg || !import_ts_morph9.Node.isObjectLiteralExpression(optsArg)) return null;
|
|
4086
4183
|
let query = null;
|
|
4087
4184
|
let body = null;
|
|
4088
4185
|
let response = "unknown";
|
|
@@ -4090,7 +4187,7 @@ function parseDefineContractCall(callExpr) {
|
|
|
4090
4187
|
let bodyZodText = null;
|
|
4091
4188
|
let queryZodText = null;
|
|
4092
4189
|
for (const prop of optsArg.getProperties()) {
|
|
4093
|
-
if (!
|
|
4190
|
+
if (!import_ts_morph9.Node.isPropertyAssignment(prop)) continue;
|
|
4094
4191
|
const propName = prop.getName();
|
|
4095
4192
|
const val = prop.getInitializer();
|
|
4096
4193
|
if (!val) continue;
|
|
@@ -4115,14 +4212,14 @@ function resolveTsconfigPath(cwd, tsconfig) {
|
|
|
4115
4212
|
}
|
|
4116
4213
|
function createDiscoveryProject(tsconfigPath) {
|
|
4117
4214
|
try {
|
|
4118
|
-
return new
|
|
4215
|
+
return new import_ts_morph10.Project({
|
|
4119
4216
|
tsConfigFilePath: tsconfigPath,
|
|
4120
4217
|
skipAddingFilesFromTsConfig: true,
|
|
4121
4218
|
skipLoadingLibFiles: true,
|
|
4122
4219
|
skipFileDependencyResolution: true
|
|
4123
4220
|
});
|
|
4124
4221
|
} catch {
|
|
4125
|
-
return new
|
|
4222
|
+
return new import_ts_morph10.Project({
|
|
4126
4223
|
skipAddingFilesFromTsConfig: true,
|
|
4127
4224
|
skipLoadingLibFiles: true,
|
|
4128
4225
|
skipFileDependencyResolution: true,
|
|
@@ -4222,15 +4319,16 @@ var PersistentDiscovery = class _PersistentDiscovery {
|
|
|
4222
4319
|
runExtraction() {
|
|
4223
4320
|
clearTypeResolutionCaches(this.project);
|
|
4224
4321
|
clearEnumCache(this.project);
|
|
4322
|
+
clearMixinTypeProject();
|
|
4225
4323
|
return extractRoutesFrom(this.project, this.controllerPaths);
|
|
4226
4324
|
}
|
|
4227
4325
|
};
|
|
4228
4326
|
function decoratorStringArg(decoratorExpr) {
|
|
4229
4327
|
if (!decoratorExpr) return void 0;
|
|
4230
|
-
if (
|
|
4231
|
-
if (
|
|
4328
|
+
if (import_ts_morph10.Node.isStringLiteral(decoratorExpr)) return decoratorExpr.getLiteralValue();
|
|
4329
|
+
if (import_ts_morph10.Node.isArrayLiteralExpression(decoratorExpr)) {
|
|
4232
4330
|
const first = decoratorExpr.getElements()[0];
|
|
4233
|
-
if (first &&
|
|
4331
|
+
if (first && import_ts_morph10.Node.isStringLiteral(first)) return first.getLiteralValue();
|
|
4234
4332
|
}
|
|
4235
4333
|
return void 0;
|
|
4236
4334
|
}
|
|
@@ -4252,7 +4350,8 @@ function joinPaths(prefix, suffix) {
|
|
|
4252
4350
|
if (!prefix && !suffix) return "/";
|
|
4253
4351
|
if (!prefix) return suffix.startsWith("/") ? suffix : `/${suffix}`;
|
|
4254
4352
|
if (!suffix) return prefix.startsWith("/") ? prefix : `/${prefix}`;
|
|
4255
|
-
const
|
|
4353
|
+
const withLeadingSlash = prefix.startsWith("/") ? prefix : `/${prefix}`;
|
|
4354
|
+
const p = withLeadingSlash.endsWith("/") ? withLeadingSlash.slice(0, -1) : withLeadingSlash;
|
|
4256
4355
|
const s = suffix.startsWith("/") ? suffix : `/${suffix}`;
|
|
4257
4356
|
const combined = p + s;
|
|
4258
4357
|
return combined === "" ? "/" : combined;
|
|
@@ -4306,7 +4405,8 @@ function buildRoute(args) {
|
|
|
4306
4405
|
methodAs,
|
|
4307
4406
|
sourceFile,
|
|
4308
4407
|
seenNames,
|
|
4309
|
-
contractSource
|
|
4408
|
+
contractSource,
|
|
4409
|
+
mixin
|
|
4310
4410
|
} = args;
|
|
4311
4411
|
const routeName = resolveRouteName(className, methodName, classAs, methodAs);
|
|
4312
4412
|
const qualifiedRef = `${className}.${methodName}`;
|
|
@@ -4322,7 +4422,12 @@ function buildRoute(args) {
|
|
|
4322
4422
|
path: combinedPath,
|
|
4323
4423
|
name: routeName,
|
|
4324
4424
|
params: extractParams(combinedPath),
|
|
4325
|
-
controllerRef: {
|
|
4425
|
+
controllerRef: {
|
|
4426
|
+
className,
|
|
4427
|
+
methodName,
|
|
4428
|
+
filePath: sourceFile.getFilePath(),
|
|
4429
|
+
...mixin ? { mixin } : {}
|
|
4430
|
+
},
|
|
4326
4431
|
contract: { contractSource }
|
|
4327
4432
|
};
|
|
4328
4433
|
}
|
|
@@ -4336,16 +4441,17 @@ function extractContractRoute(args) {
|
|
|
4336
4441
|
className,
|
|
4337
4442
|
sourceFile,
|
|
4338
4443
|
project,
|
|
4339
|
-
seenNames
|
|
4444
|
+
seenNames,
|
|
4445
|
+
mixin
|
|
4340
4446
|
} = args;
|
|
4341
4447
|
const firstDecoratorArg = applyContractDecorator.getArguments()[0];
|
|
4342
4448
|
if (!firstDecoratorArg) return null;
|
|
4343
4449
|
let contractDef = null;
|
|
4344
4450
|
let bodyZodRef = null;
|
|
4345
4451
|
let queryZodRef = null;
|
|
4346
|
-
if (
|
|
4452
|
+
if (import_ts_morph10.Node.isCallExpression(firstDecoratorArg)) {
|
|
4347
4453
|
contractDef = parseDefineContractCall(firstDecoratorArg);
|
|
4348
|
-
} else if (
|
|
4454
|
+
} else if (import_ts_morph10.Node.isIdentifier(firstDecoratorArg)) {
|
|
4349
4455
|
const identName = firstDecoratorArg.getText();
|
|
4350
4456
|
const resolvedVar = resolveImportedVariable(identName, sourceFile, project);
|
|
4351
4457
|
if (!resolvedVar) {
|
|
@@ -4388,6 +4494,7 @@ function extractContractRoute(args) {
|
|
|
4388
4494
|
methodAs,
|
|
4389
4495
|
sourceFile,
|
|
4390
4496
|
seenNames,
|
|
4497
|
+
mixin,
|
|
4391
4498
|
contractSource: {
|
|
4392
4499
|
query: contractDef.query,
|
|
4393
4500
|
body: contractDef.body,
|
|
@@ -4404,13 +4511,14 @@ function extractContractRoute(args) {
|
|
|
4404
4511
|
});
|
|
4405
4512
|
}
|
|
4406
4513
|
function extractDtoRoute(args) {
|
|
4407
|
-
const { cls, method, verb, prefix, className, sourceFile, project, seenNames } = args;
|
|
4514
|
+
const { cls, method, verb, prefix, className, sourceFile, project, seenNames, mixin } = args;
|
|
4408
4515
|
if (!verb) return null;
|
|
4409
4516
|
const combined = joinPaths(prefix, verb.handlerPath);
|
|
4410
4517
|
const methodName = method.getName();
|
|
4411
4518
|
const classAs = readAsDecorator(cls, `class ${className}`);
|
|
4412
4519
|
const methodAs = readAsDecorator(method, `${className}.${methodName}`);
|
|
4413
|
-
const dtoContract = extractDtoContract(method, sourceFile, project);
|
|
4520
|
+
const dtoContract = extractDtoContract(method, sourceFile, project, mixin);
|
|
4521
|
+
const mixinResponse = mixin ? resolveInstantiatedReturnType(cls, methodName) : void 0;
|
|
4414
4522
|
return buildRoute({
|
|
4415
4523
|
className,
|
|
4416
4524
|
methodName,
|
|
@@ -4420,10 +4528,11 @@ function extractDtoRoute(args) {
|
|
|
4420
4528
|
methodAs,
|
|
4421
4529
|
sourceFile,
|
|
4422
4530
|
seenNames,
|
|
4531
|
+
mixin,
|
|
4423
4532
|
contractSource: {
|
|
4424
4533
|
query: dtoContract?.query ?? null,
|
|
4425
4534
|
body: dtoContract?.body ?? null,
|
|
4426
|
-
response: dtoContract?.response ?? "unknown",
|
|
4535
|
+
response: mixinResponse ?? dtoContract?.response ?? "unknown",
|
|
4427
4536
|
error: dtoContract?.error ?? null,
|
|
4428
4537
|
queryRef: dtoContract?.queryRef ?? null,
|
|
4429
4538
|
bodyRef: dtoContract?.bodyRef ?? null,
|
|
@@ -4452,7 +4561,17 @@ function extractFromSourceFile(sourceFile, project) {
|
|
|
4452
4561
|
const firstArg2 = controllerDecorator.getArguments()[0];
|
|
4453
4562
|
const prefix = decoratorStringArg(firstArg2) ?? "";
|
|
4454
4563
|
const className = cls.getName() ?? "Unknown";
|
|
4455
|
-
|
|
4564
|
+
const inherited = resolveInheritedMethods(cls);
|
|
4565
|
+
const mixinBinding = inherited ? {
|
|
4566
|
+
factoryName: inherited.factoryName,
|
|
4567
|
+
factoryFilePath: inherited.factoryFilePath,
|
|
4568
|
+
classArgs: inherited.classArgs
|
|
4569
|
+
} : void 0;
|
|
4570
|
+
const methods = [
|
|
4571
|
+
...cls.getMethods().map((method) => ({ method })),
|
|
4572
|
+
...(inherited?.methods ?? []).map((method) => ({ method, mixin: mixinBinding }))
|
|
4573
|
+
];
|
|
4574
|
+
for (const { method, mixin } of methods) {
|
|
4456
4575
|
const verb = resolveVerb(method);
|
|
4457
4576
|
const applyContractDecorator = method.getDecorator("ApplyContract");
|
|
4458
4577
|
const route = applyContractDecorator ? extractContractRoute({
|
|
@@ -4464,7 +4583,8 @@ function extractFromSourceFile(sourceFile, project) {
|
|
|
4464
4583
|
className,
|
|
4465
4584
|
sourceFile,
|
|
4466
4585
|
project,
|
|
4467
|
-
seenNames
|
|
4586
|
+
seenNames,
|
|
4587
|
+
mixin
|
|
4468
4588
|
}) : extractDtoRoute({
|
|
4469
4589
|
cls,
|
|
4470
4590
|
method,
|
|
@@ -4473,7 +4593,8 @@ function extractFromSourceFile(sourceFile, project) {
|
|
|
4473
4593
|
className,
|
|
4474
4594
|
sourceFile,
|
|
4475
4595
|
project,
|
|
4476
|
-
seenNames
|
|
4596
|
+
seenNames,
|
|
4597
|
+
mixin
|
|
4477
4598
|
});
|
|
4478
4599
|
if (route) routes.push(route);
|
|
4479
4600
|
}
|
|
@@ -4674,7 +4795,7 @@ async function watch(config, onChange, options = {}) {
|
|
|
4674
4795
|
}
|
|
4675
4796
|
|
|
4676
4797
|
// src/index.ts
|
|
4677
|
-
var VERSION = "0.
|
|
4798
|
+
var VERSION = "0.16.0";
|
|
4678
4799
|
|
|
4679
4800
|
// src/generate-manifest.ts
|
|
4680
4801
|
var MANIFEST_FILE = ".codegen-manifest.json";
|