@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.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _nestjs_common from '@nestjs/common';
|
|
2
2
|
import { DynamicModule, OnApplicationBootstrap, OnModuleDestroy, ExecutionContext } from '@nestjs/common';
|
|
3
|
-
import { U as UserConfig } from '../index-
|
|
3
|
+
import { U as UserConfig } from '../index-LQNP7Ms3.cjs';
|
|
4
4
|
import 'ts-morph';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/nest/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _nestjs_common from '@nestjs/common';
|
|
2
2
|
import { DynamicModule, OnApplicationBootstrap, OnModuleDestroy, ExecutionContext } from '@nestjs/common';
|
|
3
|
-
import { U as UserConfig } from '../index-
|
|
3
|
+
import { U as UserConfig } from '../index-LQNP7Ms3.js';
|
|
4
4
|
import 'ts-morph';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/nest/index.js
CHANGED
|
@@ -2234,8 +2234,8 @@ import chokidar from "chokidar";
|
|
|
2234
2234
|
import { join as join13, resolve as resolve3 } from "path";
|
|
2235
2235
|
import fg2 from "fast-glob";
|
|
2236
2236
|
import {
|
|
2237
|
-
Node as
|
|
2238
|
-
Project as
|
|
2237
|
+
Node as Node9,
|
|
2238
|
+
Project as Project4
|
|
2239
2239
|
} from "ts-morph";
|
|
2240
2240
|
|
|
2241
2241
|
// src/discovery/dto-type-resolver.ts
|
|
@@ -3227,6 +3227,12 @@ function toFilterFieldType(name, r) {
|
|
|
3227
3227
|
}
|
|
3228
3228
|
|
|
3229
3229
|
// src/discovery/filter-for.ts
|
|
3230
|
+
function resolveMixinEntityClass(mixin, project) {
|
|
3231
|
+
const entityArg = mixin?.classArgs[0];
|
|
3232
|
+
if (!entityArg) return void 0;
|
|
3233
|
+
const file = project.getSourceFile(entityArg.filePath) ?? project.addSourceFileAtPathIfExists(entityArg.filePath);
|
|
3234
|
+
return file?.getClass(entityArg.name);
|
|
3235
|
+
}
|
|
3230
3236
|
function classifyFilterForHint(typeInit) {
|
|
3231
3237
|
if (Node5.isStringLiteral(typeInit)) {
|
|
3232
3238
|
switch (typeInit.getLiteralValue()) {
|
|
@@ -3300,7 +3306,9 @@ function extractFilterForHints(classDecl, project) {
|
|
|
3300
3306
|
}
|
|
3301
3307
|
return hints;
|
|
3302
3308
|
}
|
|
3303
|
-
function extractApplyFilterInfo(method, sourceFile, project) {
|
|
3309
|
+
function extractApplyFilterInfo(method, sourceFile, project, mixin) {
|
|
3310
|
+
const declFile = method.getSourceFile();
|
|
3311
|
+
const mixinEntity = resolveMixinEntityClass(mixin, project);
|
|
3304
3312
|
for (const param of method.getParameters()) {
|
|
3305
3313
|
const filterDecorator = param.getDecorators().find((d) => d.getName() === "ApplyFilter");
|
|
3306
3314
|
if (!filterDecorator) continue;
|
|
@@ -3320,12 +3328,12 @@ function extractApplyFilterInfo(method, sourceFile, project) {
|
|
|
3320
3328
|
}
|
|
3321
3329
|
}
|
|
3322
3330
|
const filterClassName = filterClassArg.getText();
|
|
3323
|
-
const resolved = findType(filterClassName,
|
|
3324
|
-
|
|
3325
|
-
|
|
3331
|
+
const resolved = findType(filterClassName, declFile, project);
|
|
3332
|
+
const classDecl = resolved?.kind === "class" ? resolved.decl : resolveLocalClassDeclaration(filterClassArg);
|
|
3333
|
+
if (classDecl) {
|
|
3326
3334
|
let fieldTypes = extractClassPropertyTypes(classDecl, project);
|
|
3327
3335
|
if (fieldTypes.length === 0) {
|
|
3328
|
-
fieldTypes = extractFilterableEntityFields(classDecl, project);
|
|
3336
|
+
fieldTypes = extractFilterableEntityFields(classDecl, project, mixinEntity);
|
|
3329
3337
|
}
|
|
3330
3338
|
const filterForHints = extractFilterForHints(classDecl, project);
|
|
3331
3339
|
if (filterForHints.size > 0) {
|
|
@@ -3410,22 +3418,29 @@ function extractClassPropertyTypes(classDecl, project) {
|
|
|
3410
3418
|
}
|
|
3411
3419
|
return fields;
|
|
3412
3420
|
}
|
|
3413
|
-
function
|
|
3421
|
+
function resolveLocalClassDeclaration(identifier) {
|
|
3422
|
+
if (!Node5.isIdentifier(identifier)) return void 0;
|
|
3423
|
+
return identifier.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => n !== void 0 && Node5.isClassDeclaration(n));
|
|
3424
|
+
}
|
|
3425
|
+
function resolveDeclaredEntity(optionsArg, filterClass, project) {
|
|
3426
|
+
if (!Node5.isObjectLiteralExpression(optionsArg)) return void 0;
|
|
3427
|
+
const entityProp = optionsArg.getProperty("entity");
|
|
3428
|
+
if (!entityProp || !Node5.isPropertyAssignment(entityProp)) return void 0;
|
|
3429
|
+
const entityInit = entityProp.getInitializer();
|
|
3430
|
+
if (!entityInit || !Node5.isIdentifier(entityInit)) return void 0;
|
|
3431
|
+
const resolved = findType(entityInit.getText(), filterClass.getSourceFile(), project);
|
|
3432
|
+
if (!resolved || resolved.kind !== "class") return void 0;
|
|
3433
|
+
return resolved.decl;
|
|
3434
|
+
}
|
|
3435
|
+
function extractFilterableEntityFields(filterClass, project, entityOverride) {
|
|
3414
3436
|
const filterableDecorator = filterClass.getDecorators().find((d) => d.getName() === "Filterable");
|
|
3415
3437
|
if (!filterableDecorator) return [];
|
|
3416
3438
|
const args = filterableDecorator.getArguments();
|
|
3417
3439
|
if (args.length === 0) return [];
|
|
3418
3440
|
const optionsArg = args[0];
|
|
3419
3441
|
if (!Node5.isObjectLiteralExpression(optionsArg)) return [];
|
|
3420
|
-
const
|
|
3421
|
-
if (!
|
|
3422
|
-
const entityInit = entityProp.getInitializer();
|
|
3423
|
-
if (!entityInit || !Node5.isIdentifier(entityInit)) return [];
|
|
3424
|
-
const entityName = entityInit.getText();
|
|
3425
|
-
const filterSourceFile = filterClass.getSourceFile();
|
|
3426
|
-
const resolvedEntity = findType(entityName, filterSourceFile, project);
|
|
3427
|
-
if (!resolvedEntity || resolvedEntity.kind !== "class") return [];
|
|
3428
|
-
const entityDecl = resolvedEntity.decl;
|
|
3442
|
+
const entityDecl = entityOverride ?? resolveDeclaredEntity(optionsArg, filterClass, project);
|
|
3443
|
+
if (!entityDecl) return [];
|
|
3429
3444
|
const fields = collectEntityFields(
|
|
3430
3445
|
entityDecl,
|
|
3431
3446
|
entityDecl.getSourceFile(),
|
|
@@ -3850,9 +3865,9 @@ function unwrapNamedContainer(node, names) {
|
|
|
3850
3865
|
}
|
|
3851
3866
|
return node;
|
|
3852
3867
|
}
|
|
3853
|
-
function extractDtoContract(method, sourceFile, project) {
|
|
3868
|
+
function extractDtoContract(method, sourceFile, project, mixin) {
|
|
3854
3869
|
let body = extractBodyType(method, sourceFile, project);
|
|
3855
|
-
const filterInfo = extractApplyFilterInfo(method, sourceFile, project);
|
|
3870
|
+
const filterInfo = extractApplyFilterInfo(method, sourceFile, project, mixin);
|
|
3856
3871
|
const query = extractQueryType(method, sourceFile, project);
|
|
3857
3872
|
const uploads = extractUploadedFiles(method);
|
|
3858
3873
|
const multipartBody = uploads.fields ? `{ ${uploads.fields} }` : null;
|
|
@@ -3962,12 +3977,94 @@ function resolveParamClass(method, decoratorName, sourceFile, project) {
|
|
|
3962
3977
|
return null;
|
|
3963
3978
|
}
|
|
3964
3979
|
|
|
3980
|
+
// src/discovery/heritage.ts
|
|
3981
|
+
import { Node as Node7, Project as Project3 } from "ts-morph";
|
|
3982
|
+
function unwrapExpression(node) {
|
|
3983
|
+
let current = node;
|
|
3984
|
+
while (Node7.isAsExpression(current) || Node7.isSatisfiesExpression(current) || Node7.isParenthesizedExpression(current) || Node7.isTypeAssertion(current)) {
|
|
3985
|
+
current = current.getExpression();
|
|
3986
|
+
}
|
|
3987
|
+
return current;
|
|
3988
|
+
}
|
|
3989
|
+
function resolveReturnedClass(factoryDecl) {
|
|
3990
|
+
const body = factoryDecl.getBody();
|
|
3991
|
+
if (!body) return void 0;
|
|
3992
|
+
const returns = body.getDescendants().filter((n) => Node7.isReturnStatement(n));
|
|
3993
|
+
for (const ret of returns) {
|
|
3994
|
+
const expr = ret.getExpression();
|
|
3995
|
+
if (!expr) continue;
|
|
3996
|
+
const inner = unwrapExpression(expr);
|
|
3997
|
+
if (Node7.isClassExpression(inner)) {
|
|
3998
|
+
return inner;
|
|
3999
|
+
}
|
|
4000
|
+
if (Node7.isIdentifier(inner)) {
|
|
4001
|
+
const name = inner.getText();
|
|
4002
|
+
const decl = body.getDescendants().find((n) => Node7.isClassDeclaration(n) && n.getName() === name);
|
|
4003
|
+
if (decl) return decl;
|
|
4004
|
+
}
|
|
4005
|
+
}
|
|
4006
|
+
return void 0;
|
|
4007
|
+
}
|
|
4008
|
+
function resolveInheritedMethods(cls) {
|
|
4009
|
+
const expr = cls.getExtends()?.getExpression();
|
|
4010
|
+
if (!expr || !Node7.isCallExpression(expr)) return void 0;
|
|
4011
|
+
const callee = expr.getExpression();
|
|
4012
|
+
if (!Node7.isIdentifier(callee)) return void 0;
|
|
4013
|
+
const factoryDecl = callee.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => Node7.isFunctionDeclaration(n));
|
|
4014
|
+
if (!factoryDecl) return void 0;
|
|
4015
|
+
const returnedClass = resolveReturnedClass(factoryDecl);
|
|
4016
|
+
if (!returnedClass) return void 0;
|
|
4017
|
+
const classArgs = [];
|
|
4018
|
+
for (const arg of expr.getArguments()) {
|
|
4019
|
+
if (!Node7.isIdentifier(arg)) continue;
|
|
4020
|
+
const decl = arg.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => Node7.isClassDeclaration(n));
|
|
4021
|
+
if (decl) {
|
|
4022
|
+
classArgs.push({
|
|
4023
|
+
name: decl.getName() ?? arg.getText(),
|
|
4024
|
+
filePath: decl.getSourceFile().getFilePath()
|
|
4025
|
+
});
|
|
4026
|
+
}
|
|
4027
|
+
}
|
|
4028
|
+
return {
|
|
4029
|
+
methods: returnedClass.getMethods(),
|
|
4030
|
+
factoryName: callee.getText(),
|
|
4031
|
+
factoryFilePath: factoryDecl.getSourceFile().getFilePath(),
|
|
4032
|
+
classArgs
|
|
4033
|
+
};
|
|
4034
|
+
}
|
|
4035
|
+
var mixinTypeProject;
|
|
4036
|
+
function getMixinTypeProject() {
|
|
4037
|
+
mixinTypeProject ??= new Project3({
|
|
4038
|
+
skipAddingFilesFromTsConfig: true,
|
|
4039
|
+
compilerOptions: { strict: true }
|
|
4040
|
+
});
|
|
4041
|
+
return mixinTypeProject;
|
|
4042
|
+
}
|
|
4043
|
+
function clearMixinTypeProject() {
|
|
4044
|
+
mixinTypeProject = void 0;
|
|
4045
|
+
}
|
|
4046
|
+
function resolveInstantiatedReturnType(cls, methodName) {
|
|
4047
|
+
const filePath = cls.getSourceFile().getFilePath();
|
|
4048
|
+
const className = cls.getName();
|
|
4049
|
+
if (!className) return void 0;
|
|
4050
|
+
const project = getMixinTypeProject();
|
|
4051
|
+
const sourceFile = project.getSourceFile(filePath) ?? project.addSourceFileAtPathIfExists(filePath);
|
|
4052
|
+
const typedCls = sourceFile?.getClass(className);
|
|
4053
|
+
if (!typedCls) return void 0;
|
|
4054
|
+
const prop = typedCls.getType().getProperty(methodName);
|
|
4055
|
+
if (!prop) return void 0;
|
|
4056
|
+
const returnType = prop.getTypeAtLocation(typedCls).getCallSignatures()[0]?.getReturnType();
|
|
4057
|
+
if (!returnType) return void 0;
|
|
4058
|
+
const unwrapped = returnType.getSymbol()?.getName() === "Promise" ? returnType.getTypeArguments()[0] ?? returnType : returnType;
|
|
4059
|
+
return unwrapped.getText(typedCls);
|
|
4060
|
+
}
|
|
4061
|
+
|
|
3965
4062
|
// src/discovery/zod-ast-to-ts.ts
|
|
3966
|
-
import { Node as
|
|
4063
|
+
import { Node as Node8, SyntaxKind as SyntaxKind4 } from "ts-morph";
|
|
3967
4064
|
function zodAstToTs(node) {
|
|
3968
|
-
if (!
|
|
4065
|
+
if (!Node8.isCallExpression(node)) return "unknown";
|
|
3969
4066
|
const expr = node.getExpression();
|
|
3970
|
-
if (
|
|
4067
|
+
if (Node8.isPropertyAccessExpression(expr)) {
|
|
3971
4068
|
const methodName = expr.getName();
|
|
3972
4069
|
const receiver = expr.getExpression();
|
|
3973
4070
|
if (methodName === "optional") {
|
|
@@ -3991,17 +4088,17 @@ function zodAstToTs(node) {
|
|
|
3991
4088
|
case "literal": {
|
|
3992
4089
|
const lit = args[0];
|
|
3993
4090
|
if (!lit) return "unknown";
|
|
3994
|
-
if (
|
|
3995
|
-
if (
|
|
4091
|
+
if (Node8.isStringLiteral(lit)) return JSON.stringify(lit.getLiteralValue());
|
|
4092
|
+
if (Node8.isNumericLiteral(lit)) return lit.getLiteralValue().toString();
|
|
3996
4093
|
if (lit.getKind() === SyntaxKind4.TrueKeyword) return "true";
|
|
3997
4094
|
if (lit.getKind() === SyntaxKind4.FalseKeyword) return "false";
|
|
3998
4095
|
return "unknown";
|
|
3999
4096
|
}
|
|
4000
4097
|
case "enum": {
|
|
4001
4098
|
const arrArg = args[0];
|
|
4002
|
-
if (!arrArg || !
|
|
4099
|
+
if (!arrArg || !Node8.isArrayLiteralExpression(arrArg)) return "unknown";
|
|
4003
4100
|
const members = arrArg.getElements().map(
|
|
4004
|
-
(el) =>
|
|
4101
|
+
(el) => Node8.isStringLiteral(el) ? JSON.stringify(el.getLiteralValue()) : "unknown"
|
|
4005
4102
|
);
|
|
4006
4103
|
return members.join(" | ");
|
|
4007
4104
|
}
|
|
@@ -4012,10 +4109,10 @@ function zodAstToTs(node) {
|
|
|
4012
4109
|
}
|
|
4013
4110
|
case "object": {
|
|
4014
4111
|
const objArg = args[0];
|
|
4015
|
-
if (!objArg || !
|
|
4112
|
+
if (!objArg || !Node8.isObjectLiteralExpression(objArg)) return "unknown";
|
|
4016
4113
|
const lines = [];
|
|
4017
4114
|
for (const prop of objArg.getProperties()) {
|
|
4018
|
-
if (!
|
|
4115
|
+
if (!Node8.isPropertyAssignment(prop)) continue;
|
|
4019
4116
|
const key = prop.getName();
|
|
4020
4117
|
const valNode = prop.getInitializer();
|
|
4021
4118
|
if (!valNode) continue;
|
|
@@ -4027,7 +4124,7 @@ function zodAstToTs(node) {
|
|
|
4027
4124
|
}
|
|
4028
4125
|
case "union": {
|
|
4029
4126
|
const arrArg = args[0];
|
|
4030
|
-
if (!arrArg || !
|
|
4127
|
+
if (!arrArg || !Node8.isArrayLiteralExpression(arrArg)) return "unknown";
|
|
4031
4128
|
return arrArg.getElements().map(zodAstToTs).join(" | ");
|
|
4032
4129
|
}
|
|
4033
4130
|
case "record": {
|
|
@@ -4037,7 +4134,7 @@ function zodAstToTs(node) {
|
|
|
4037
4134
|
}
|
|
4038
4135
|
case "tuple": {
|
|
4039
4136
|
const arrArg = args[0];
|
|
4040
|
-
if (!arrArg || !
|
|
4137
|
+
if (!arrArg || !Node8.isArrayLiteralExpression(arrArg)) return "unknown";
|
|
4041
4138
|
return `[${arrArg.getElements().map(zodAstToTs).join(", ")}]`;
|
|
4042
4139
|
}
|
|
4043
4140
|
default:
|
|
@@ -4047,18 +4144,18 @@ function zodAstToTs(node) {
|
|
|
4047
4144
|
return "unknown";
|
|
4048
4145
|
}
|
|
4049
4146
|
function isOptionalChain(node) {
|
|
4050
|
-
if (!
|
|
4147
|
+
if (!Node8.isCallExpression(node)) return false;
|
|
4051
4148
|
const expr = node.getExpression();
|
|
4052
|
-
return
|
|
4149
|
+
return Node8.isPropertyAccessExpression(expr) && expr.getName() === "optional";
|
|
4053
4150
|
}
|
|
4054
4151
|
function parseDefineContractCall(callExpr) {
|
|
4055
|
-
if (!
|
|
4152
|
+
if (!Node8.isCallExpression(callExpr)) return null;
|
|
4056
4153
|
const callee = callExpr.getExpression();
|
|
4057
|
-
const calleeName =
|
|
4154
|
+
const calleeName = Node8.isIdentifier(callee) ? callee.getText() : Node8.isPropertyAccessExpression(callee) ? callee.getName() : "";
|
|
4058
4155
|
if (calleeName !== "defineContract") return null;
|
|
4059
4156
|
const args = callExpr.getArguments();
|
|
4060
4157
|
const optsArg = args[0];
|
|
4061
|
-
if (!optsArg || !
|
|
4158
|
+
if (!optsArg || !Node8.isObjectLiteralExpression(optsArg)) return null;
|
|
4062
4159
|
let query = null;
|
|
4063
4160
|
let body = null;
|
|
4064
4161
|
let response = "unknown";
|
|
@@ -4066,7 +4163,7 @@ function parseDefineContractCall(callExpr) {
|
|
|
4066
4163
|
let bodyZodText = null;
|
|
4067
4164
|
let queryZodText = null;
|
|
4068
4165
|
for (const prop of optsArg.getProperties()) {
|
|
4069
|
-
if (!
|
|
4166
|
+
if (!Node8.isPropertyAssignment(prop)) continue;
|
|
4070
4167
|
const propName = prop.getName();
|
|
4071
4168
|
const val = prop.getInitializer();
|
|
4072
4169
|
if (!val) continue;
|
|
@@ -4091,14 +4188,14 @@ function resolveTsconfigPath(cwd, tsconfig) {
|
|
|
4091
4188
|
}
|
|
4092
4189
|
function createDiscoveryProject(tsconfigPath) {
|
|
4093
4190
|
try {
|
|
4094
|
-
return new
|
|
4191
|
+
return new Project4({
|
|
4095
4192
|
tsConfigFilePath: tsconfigPath,
|
|
4096
4193
|
skipAddingFilesFromTsConfig: true,
|
|
4097
4194
|
skipLoadingLibFiles: true,
|
|
4098
4195
|
skipFileDependencyResolution: true
|
|
4099
4196
|
});
|
|
4100
4197
|
} catch {
|
|
4101
|
-
return new
|
|
4198
|
+
return new Project4({
|
|
4102
4199
|
skipAddingFilesFromTsConfig: true,
|
|
4103
4200
|
skipLoadingLibFiles: true,
|
|
4104
4201
|
skipFileDependencyResolution: true,
|
|
@@ -4198,15 +4295,16 @@ var PersistentDiscovery = class _PersistentDiscovery {
|
|
|
4198
4295
|
runExtraction() {
|
|
4199
4296
|
clearTypeResolutionCaches(this.project);
|
|
4200
4297
|
clearEnumCache(this.project);
|
|
4298
|
+
clearMixinTypeProject();
|
|
4201
4299
|
return extractRoutesFrom(this.project, this.controllerPaths);
|
|
4202
4300
|
}
|
|
4203
4301
|
};
|
|
4204
4302
|
function decoratorStringArg(decoratorExpr) {
|
|
4205
4303
|
if (!decoratorExpr) return void 0;
|
|
4206
|
-
if (
|
|
4207
|
-
if (
|
|
4304
|
+
if (Node9.isStringLiteral(decoratorExpr)) return decoratorExpr.getLiteralValue();
|
|
4305
|
+
if (Node9.isArrayLiteralExpression(decoratorExpr)) {
|
|
4208
4306
|
const first = decoratorExpr.getElements()[0];
|
|
4209
|
-
if (first &&
|
|
4307
|
+
if (first && Node9.isStringLiteral(first)) return first.getLiteralValue();
|
|
4210
4308
|
}
|
|
4211
4309
|
return void 0;
|
|
4212
4310
|
}
|
|
@@ -4228,7 +4326,8 @@ function joinPaths(prefix, suffix) {
|
|
|
4228
4326
|
if (!prefix && !suffix) return "/";
|
|
4229
4327
|
if (!prefix) return suffix.startsWith("/") ? suffix : `/${suffix}`;
|
|
4230
4328
|
if (!suffix) return prefix.startsWith("/") ? prefix : `/${prefix}`;
|
|
4231
|
-
const
|
|
4329
|
+
const withLeadingSlash = prefix.startsWith("/") ? prefix : `/${prefix}`;
|
|
4330
|
+
const p = withLeadingSlash.endsWith("/") ? withLeadingSlash.slice(0, -1) : withLeadingSlash;
|
|
4232
4331
|
const s = suffix.startsWith("/") ? suffix : `/${suffix}`;
|
|
4233
4332
|
const combined = p + s;
|
|
4234
4333
|
return combined === "" ? "/" : combined;
|
|
@@ -4282,7 +4381,8 @@ function buildRoute(args) {
|
|
|
4282
4381
|
methodAs,
|
|
4283
4382
|
sourceFile,
|
|
4284
4383
|
seenNames,
|
|
4285
|
-
contractSource
|
|
4384
|
+
contractSource,
|
|
4385
|
+
mixin
|
|
4286
4386
|
} = args;
|
|
4287
4387
|
const routeName = resolveRouteName(className, methodName, classAs, methodAs);
|
|
4288
4388
|
const qualifiedRef = `${className}.${methodName}`;
|
|
@@ -4298,7 +4398,12 @@ function buildRoute(args) {
|
|
|
4298
4398
|
path: combinedPath,
|
|
4299
4399
|
name: routeName,
|
|
4300
4400
|
params: extractParams(combinedPath),
|
|
4301
|
-
controllerRef: {
|
|
4401
|
+
controllerRef: {
|
|
4402
|
+
className,
|
|
4403
|
+
methodName,
|
|
4404
|
+
filePath: sourceFile.getFilePath(),
|
|
4405
|
+
...mixin ? { mixin } : {}
|
|
4406
|
+
},
|
|
4302
4407
|
contract: { contractSource }
|
|
4303
4408
|
};
|
|
4304
4409
|
}
|
|
@@ -4312,16 +4417,17 @@ function extractContractRoute(args) {
|
|
|
4312
4417
|
className,
|
|
4313
4418
|
sourceFile,
|
|
4314
4419
|
project,
|
|
4315
|
-
seenNames
|
|
4420
|
+
seenNames,
|
|
4421
|
+
mixin
|
|
4316
4422
|
} = args;
|
|
4317
4423
|
const firstDecoratorArg = applyContractDecorator.getArguments()[0];
|
|
4318
4424
|
if (!firstDecoratorArg) return null;
|
|
4319
4425
|
let contractDef = null;
|
|
4320
4426
|
let bodyZodRef = null;
|
|
4321
4427
|
let queryZodRef = null;
|
|
4322
|
-
if (
|
|
4428
|
+
if (Node9.isCallExpression(firstDecoratorArg)) {
|
|
4323
4429
|
contractDef = parseDefineContractCall(firstDecoratorArg);
|
|
4324
|
-
} else if (
|
|
4430
|
+
} else if (Node9.isIdentifier(firstDecoratorArg)) {
|
|
4325
4431
|
const identName = firstDecoratorArg.getText();
|
|
4326
4432
|
const resolvedVar = resolveImportedVariable(identName, sourceFile, project);
|
|
4327
4433
|
if (!resolvedVar) {
|
|
@@ -4364,6 +4470,7 @@ function extractContractRoute(args) {
|
|
|
4364
4470
|
methodAs,
|
|
4365
4471
|
sourceFile,
|
|
4366
4472
|
seenNames,
|
|
4473
|
+
mixin,
|
|
4367
4474
|
contractSource: {
|
|
4368
4475
|
query: contractDef.query,
|
|
4369
4476
|
body: contractDef.body,
|
|
@@ -4380,13 +4487,14 @@ function extractContractRoute(args) {
|
|
|
4380
4487
|
});
|
|
4381
4488
|
}
|
|
4382
4489
|
function extractDtoRoute(args) {
|
|
4383
|
-
const { cls, method, verb, prefix, className, sourceFile, project, seenNames } = args;
|
|
4490
|
+
const { cls, method, verb, prefix, className, sourceFile, project, seenNames, mixin } = args;
|
|
4384
4491
|
if (!verb) return null;
|
|
4385
4492
|
const combined = joinPaths(prefix, verb.handlerPath);
|
|
4386
4493
|
const methodName = method.getName();
|
|
4387
4494
|
const classAs = readAsDecorator(cls, `class ${className}`);
|
|
4388
4495
|
const methodAs = readAsDecorator(method, `${className}.${methodName}`);
|
|
4389
|
-
const dtoContract = extractDtoContract(method, sourceFile, project);
|
|
4496
|
+
const dtoContract = extractDtoContract(method, sourceFile, project, mixin);
|
|
4497
|
+
const mixinResponse = mixin ? resolveInstantiatedReturnType(cls, methodName) : void 0;
|
|
4390
4498
|
return buildRoute({
|
|
4391
4499
|
className,
|
|
4392
4500
|
methodName,
|
|
@@ -4396,10 +4504,11 @@ function extractDtoRoute(args) {
|
|
|
4396
4504
|
methodAs,
|
|
4397
4505
|
sourceFile,
|
|
4398
4506
|
seenNames,
|
|
4507
|
+
mixin,
|
|
4399
4508
|
contractSource: {
|
|
4400
4509
|
query: dtoContract?.query ?? null,
|
|
4401
4510
|
body: dtoContract?.body ?? null,
|
|
4402
|
-
response: dtoContract?.response ?? "unknown",
|
|
4511
|
+
response: mixinResponse ?? dtoContract?.response ?? "unknown",
|
|
4403
4512
|
error: dtoContract?.error ?? null,
|
|
4404
4513
|
queryRef: dtoContract?.queryRef ?? null,
|
|
4405
4514
|
bodyRef: dtoContract?.bodyRef ?? null,
|
|
@@ -4428,7 +4537,17 @@ function extractFromSourceFile(sourceFile, project) {
|
|
|
4428
4537
|
const firstArg2 = controllerDecorator.getArguments()[0];
|
|
4429
4538
|
const prefix = decoratorStringArg(firstArg2) ?? "";
|
|
4430
4539
|
const className = cls.getName() ?? "Unknown";
|
|
4431
|
-
|
|
4540
|
+
const inherited = resolveInheritedMethods(cls);
|
|
4541
|
+
const mixinBinding = inherited ? {
|
|
4542
|
+
factoryName: inherited.factoryName,
|
|
4543
|
+
factoryFilePath: inherited.factoryFilePath,
|
|
4544
|
+
classArgs: inherited.classArgs
|
|
4545
|
+
} : void 0;
|
|
4546
|
+
const methods = [
|
|
4547
|
+
...cls.getMethods().map((method) => ({ method })),
|
|
4548
|
+
...(inherited?.methods ?? []).map((method) => ({ method, mixin: mixinBinding }))
|
|
4549
|
+
];
|
|
4550
|
+
for (const { method, mixin } of methods) {
|
|
4432
4551
|
const verb = resolveVerb(method);
|
|
4433
4552
|
const applyContractDecorator = method.getDecorator("ApplyContract");
|
|
4434
4553
|
const route = applyContractDecorator ? extractContractRoute({
|
|
@@ -4440,7 +4559,8 @@ function extractFromSourceFile(sourceFile, project) {
|
|
|
4440
4559
|
className,
|
|
4441
4560
|
sourceFile,
|
|
4442
4561
|
project,
|
|
4443
|
-
seenNames
|
|
4562
|
+
seenNames,
|
|
4563
|
+
mixin
|
|
4444
4564
|
}) : extractDtoRoute({
|
|
4445
4565
|
cls,
|
|
4446
4566
|
method,
|
|
@@ -4449,7 +4569,8 @@ function extractFromSourceFile(sourceFile, project) {
|
|
|
4449
4569
|
className,
|
|
4450
4570
|
sourceFile,
|
|
4451
4571
|
project,
|
|
4452
|
-
seenNames
|
|
4572
|
+
seenNames,
|
|
4573
|
+
mixin
|
|
4453
4574
|
});
|
|
4454
4575
|
if (route) routes.push(route);
|
|
4455
4576
|
}
|
|
@@ -4650,7 +4771,7 @@ async function watch(config, onChange, options = {}) {
|
|
|
4650
4771
|
}
|
|
4651
4772
|
|
|
4652
4773
|
// src/index.ts
|
|
4653
|
-
var VERSION = "0.
|
|
4774
|
+
var VERSION = "0.16.0";
|
|
4654
4775
|
|
|
4655
4776
|
// src/generate-manifest.ts
|
|
4656
4777
|
var MANIFEST_FILE = ".codegen-manifest.json";
|