@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/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { U as UserConfig, R as ResolvedConfig, a as RouteDescriptor, S as SchemaNode, b as RenderContext, c as SchemaModule, d as RenderedModule, e as ResolvedFormsConfig, V as ValidationAdapter, C as CodegenExtension, E as ExtensionContext, f as SerializationMode } from './index-
|
|
2
|
-
export { A as AdapterUsage, g as ContractDescriptor, h as ContractSource, i as ControllerRef, N as NumberCheck, j as ScopeConfig, k as StringCheck, T as TypeRef, l as ValidationOption, r as resolveAdapter } from './index-
|
|
1
|
+
import { U as UserConfig, R as ResolvedConfig, a as RouteDescriptor, S as SchemaNode, b as RenderContext, c as SchemaModule, d as RenderedModule, e as ResolvedFormsConfig, V as ValidationAdapter, C as CodegenExtension, E as ExtensionContext, f as SerializationMode } from './index-LQNP7Ms3.cjs';
|
|
2
|
+
export { A as AdapterUsage, g as ContractDescriptor, h as ContractSource, i as ControllerRef, N as NumberCheck, j as ScopeConfig, k as StringCheck, T as TypeRef, l as ValidationOption, r as resolveAdapter } from './index-LQNP7Ms3.cjs';
|
|
3
3
|
import { ClassDeclaration, SourceFile, Project } from 'ts-morph';
|
|
4
4
|
|
|
5
5
|
declare function defineConfig(c: UserConfig): UserConfig;
|
|
@@ -373,6 +373,6 @@ interface FastDiscoveryOptions {
|
|
|
373
373
|
}
|
|
374
374
|
declare function discoverContractsFast(opts: FastDiscoveryOptions): Promise<RouteDescriptor[]>;
|
|
375
375
|
|
|
376
|
-
declare const VERSION = "0.
|
|
376
|
+
declare const VERSION = "0.16.0";
|
|
377
377
|
|
|
378
378
|
export { type ChainModuleRendererOptions, CodegenError, type CodegenManifest, ConfigError, DriftGuardError, type EntryPoint, type FastDiscoveryOptions, type JsonSchema, type MocksEmitOptions, type OpenApiDocument, type OpenApiEmitOptions, type OpenApiInfo, RenderContext, RenderedModule, ResolvedConfig, RouteDescriptor, SchemaModule, SchemaNode, type TsTypeContext, UserConfig, VERSION, ValidationAdapter, type WatchOptions, type Watcher, acquireLock, buildMocksFile, buildOpenApiSpec, createChainModuleRenderer, defineConfig, discoverContractsFast, emitApi, emitForms, emitMocks, emitOpenApi, emitRoutes, extractSchemaFromDto, generate, loadConfig, renderTsType, resolveConfig, schemaModuleToJsonSchema, schemaNodeToJsonSchema, toObjectKey, typeNameFor, watch };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { U as UserConfig, R as ResolvedConfig, a as RouteDescriptor, S as SchemaNode, b as RenderContext, c as SchemaModule, d as RenderedModule, e as ResolvedFormsConfig, V as ValidationAdapter, C as CodegenExtension, E as ExtensionContext, f as SerializationMode } from './index-
|
|
2
|
-
export { A as AdapterUsage, g as ContractDescriptor, h as ContractSource, i as ControllerRef, N as NumberCheck, j as ScopeConfig, k as StringCheck, T as TypeRef, l as ValidationOption, r as resolveAdapter } from './index-
|
|
1
|
+
import { U as UserConfig, R as ResolvedConfig, a as RouteDescriptor, S as SchemaNode, b as RenderContext, c as SchemaModule, d as RenderedModule, e as ResolvedFormsConfig, V as ValidationAdapter, C as CodegenExtension, E as ExtensionContext, f as SerializationMode } from './index-LQNP7Ms3.js';
|
|
2
|
+
export { A as AdapterUsage, g as ContractDescriptor, h as ContractSource, i as ControllerRef, N as NumberCheck, j as ScopeConfig, k as StringCheck, T as TypeRef, l as ValidationOption, r as resolveAdapter } from './index-LQNP7Ms3.js';
|
|
3
3
|
import { ClassDeclaration, SourceFile, Project } from 'ts-morph';
|
|
4
4
|
|
|
5
5
|
declare function defineConfig(c: UserConfig): UserConfig;
|
|
@@ -373,6 +373,6 @@ interface FastDiscoveryOptions {
|
|
|
373
373
|
}
|
|
374
374
|
declare function discoverContractsFast(opts: FastDiscoveryOptions): Promise<RouteDescriptor[]>;
|
|
375
375
|
|
|
376
|
-
declare const VERSION = "0.
|
|
376
|
+
declare const VERSION = "0.16.0";
|
|
377
377
|
|
|
378
378
|
export { type ChainModuleRendererOptions, CodegenError, type CodegenManifest, ConfigError, DriftGuardError, type EntryPoint, type FastDiscoveryOptions, type JsonSchema, type MocksEmitOptions, type OpenApiDocument, type OpenApiEmitOptions, type OpenApiInfo, RenderContext, RenderedModule, ResolvedConfig, RouteDescriptor, SchemaModule, SchemaNode, type TsTypeContext, UserConfig, VERSION, ValidationAdapter, type WatchOptions, type Watcher, acquireLock, buildMocksFile, buildOpenApiSpec, createChainModuleRenderer, defineConfig, discoverContractsFast, emitApi, emitForms, emitMocks, emitOpenApi, emitRoutes, extractSchemaFromDto, generate, loadConfig, renderTsType, resolveConfig, schemaModuleToJsonSchema, schemaNodeToJsonSchema, toObjectKey, typeNameFor, watch };
|
package/dist/index.js
CHANGED
|
@@ -2417,8 +2417,8 @@ import chokidar from "chokidar";
|
|
|
2417
2417
|
import { join as join14, resolve as resolve3 } from "path";
|
|
2418
2418
|
import fg3 from "fast-glob";
|
|
2419
2419
|
import {
|
|
2420
|
-
Node as
|
|
2421
|
-
Project as
|
|
2420
|
+
Node as Node9,
|
|
2421
|
+
Project as Project4
|
|
2422
2422
|
} from "ts-morph";
|
|
2423
2423
|
|
|
2424
2424
|
// src/discovery/dto-type-resolver.ts
|
|
@@ -3410,6 +3410,12 @@ function toFilterFieldType(name, r) {
|
|
|
3410
3410
|
}
|
|
3411
3411
|
|
|
3412
3412
|
// src/discovery/filter-for.ts
|
|
3413
|
+
function resolveMixinEntityClass(mixin, project) {
|
|
3414
|
+
const entityArg = mixin?.classArgs[0];
|
|
3415
|
+
if (!entityArg) return void 0;
|
|
3416
|
+
const file = project.getSourceFile(entityArg.filePath) ?? project.addSourceFileAtPathIfExists(entityArg.filePath);
|
|
3417
|
+
return file?.getClass(entityArg.name);
|
|
3418
|
+
}
|
|
3413
3419
|
function classifyFilterForHint(typeInit) {
|
|
3414
3420
|
if (Node5.isStringLiteral(typeInit)) {
|
|
3415
3421
|
switch (typeInit.getLiteralValue()) {
|
|
@@ -3483,7 +3489,9 @@ function extractFilterForHints(classDecl, project) {
|
|
|
3483
3489
|
}
|
|
3484
3490
|
return hints;
|
|
3485
3491
|
}
|
|
3486
|
-
function extractApplyFilterInfo(method, sourceFile, project) {
|
|
3492
|
+
function extractApplyFilterInfo(method, sourceFile, project, mixin) {
|
|
3493
|
+
const declFile = method.getSourceFile();
|
|
3494
|
+
const mixinEntity = resolveMixinEntityClass(mixin, project);
|
|
3487
3495
|
for (const param of method.getParameters()) {
|
|
3488
3496
|
const filterDecorator = param.getDecorators().find((d) => d.getName() === "ApplyFilter");
|
|
3489
3497
|
if (!filterDecorator) continue;
|
|
@@ -3503,12 +3511,12 @@ function extractApplyFilterInfo(method, sourceFile, project) {
|
|
|
3503
3511
|
}
|
|
3504
3512
|
}
|
|
3505
3513
|
const filterClassName = filterClassArg.getText();
|
|
3506
|
-
const resolved = findType(filterClassName,
|
|
3507
|
-
|
|
3508
|
-
|
|
3514
|
+
const resolved = findType(filterClassName, declFile, project);
|
|
3515
|
+
const classDecl = resolved?.kind === "class" ? resolved.decl : resolveLocalClassDeclaration(filterClassArg);
|
|
3516
|
+
if (classDecl) {
|
|
3509
3517
|
let fieldTypes = extractClassPropertyTypes(classDecl, project);
|
|
3510
3518
|
if (fieldTypes.length === 0) {
|
|
3511
|
-
fieldTypes = extractFilterableEntityFields(classDecl, project);
|
|
3519
|
+
fieldTypes = extractFilterableEntityFields(classDecl, project, mixinEntity);
|
|
3512
3520
|
}
|
|
3513
3521
|
const filterForHints = extractFilterForHints(classDecl, project);
|
|
3514
3522
|
if (filterForHints.size > 0) {
|
|
@@ -3593,22 +3601,29 @@ function extractClassPropertyTypes(classDecl, project) {
|
|
|
3593
3601
|
}
|
|
3594
3602
|
return fields;
|
|
3595
3603
|
}
|
|
3596
|
-
function
|
|
3604
|
+
function resolveLocalClassDeclaration(identifier) {
|
|
3605
|
+
if (!Node5.isIdentifier(identifier)) return void 0;
|
|
3606
|
+
return identifier.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => n !== void 0 && Node5.isClassDeclaration(n));
|
|
3607
|
+
}
|
|
3608
|
+
function resolveDeclaredEntity(optionsArg, filterClass, project) {
|
|
3609
|
+
if (!Node5.isObjectLiteralExpression(optionsArg)) return void 0;
|
|
3610
|
+
const entityProp = optionsArg.getProperty("entity");
|
|
3611
|
+
if (!entityProp || !Node5.isPropertyAssignment(entityProp)) return void 0;
|
|
3612
|
+
const entityInit = entityProp.getInitializer();
|
|
3613
|
+
if (!entityInit || !Node5.isIdentifier(entityInit)) return void 0;
|
|
3614
|
+
const resolved = findType(entityInit.getText(), filterClass.getSourceFile(), project);
|
|
3615
|
+
if (!resolved || resolved.kind !== "class") return void 0;
|
|
3616
|
+
return resolved.decl;
|
|
3617
|
+
}
|
|
3618
|
+
function extractFilterableEntityFields(filterClass, project, entityOverride) {
|
|
3597
3619
|
const filterableDecorator = filterClass.getDecorators().find((d) => d.getName() === "Filterable");
|
|
3598
3620
|
if (!filterableDecorator) return [];
|
|
3599
3621
|
const args = filterableDecorator.getArguments();
|
|
3600
3622
|
if (args.length === 0) return [];
|
|
3601
3623
|
const optionsArg = args[0];
|
|
3602
3624
|
if (!Node5.isObjectLiteralExpression(optionsArg)) return [];
|
|
3603
|
-
const
|
|
3604
|
-
if (!
|
|
3605
|
-
const entityInit = entityProp.getInitializer();
|
|
3606
|
-
if (!entityInit || !Node5.isIdentifier(entityInit)) return [];
|
|
3607
|
-
const entityName = entityInit.getText();
|
|
3608
|
-
const filterSourceFile = filterClass.getSourceFile();
|
|
3609
|
-
const resolvedEntity = findType(entityName, filterSourceFile, project);
|
|
3610
|
-
if (!resolvedEntity || resolvedEntity.kind !== "class") return [];
|
|
3611
|
-
const entityDecl = resolvedEntity.decl;
|
|
3625
|
+
const entityDecl = entityOverride ?? resolveDeclaredEntity(optionsArg, filterClass, project);
|
|
3626
|
+
if (!entityDecl) return [];
|
|
3612
3627
|
const fields = collectEntityFields(
|
|
3613
3628
|
entityDecl,
|
|
3614
3629
|
entityDecl.getSourceFile(),
|
|
@@ -4033,9 +4048,9 @@ function unwrapNamedContainer(node, names) {
|
|
|
4033
4048
|
}
|
|
4034
4049
|
return node;
|
|
4035
4050
|
}
|
|
4036
|
-
function extractDtoContract(method, sourceFile, project) {
|
|
4051
|
+
function extractDtoContract(method, sourceFile, project, mixin) {
|
|
4037
4052
|
let body = extractBodyType(method, sourceFile, project);
|
|
4038
|
-
const filterInfo = extractApplyFilterInfo(method, sourceFile, project);
|
|
4053
|
+
const filterInfo = extractApplyFilterInfo(method, sourceFile, project, mixin);
|
|
4039
4054
|
const query = extractQueryType(method, sourceFile, project);
|
|
4040
4055
|
const uploads = extractUploadedFiles(method);
|
|
4041
4056
|
const multipartBody = uploads.fields ? `{ ${uploads.fields} }` : null;
|
|
@@ -4145,12 +4160,94 @@ function resolveParamClass(method, decoratorName, sourceFile, project) {
|
|
|
4145
4160
|
return null;
|
|
4146
4161
|
}
|
|
4147
4162
|
|
|
4163
|
+
// src/discovery/heritage.ts
|
|
4164
|
+
import { Node as Node7, Project as Project3 } from "ts-morph";
|
|
4165
|
+
function unwrapExpression(node) {
|
|
4166
|
+
let current = node;
|
|
4167
|
+
while (Node7.isAsExpression(current) || Node7.isSatisfiesExpression(current) || Node7.isParenthesizedExpression(current) || Node7.isTypeAssertion(current)) {
|
|
4168
|
+
current = current.getExpression();
|
|
4169
|
+
}
|
|
4170
|
+
return current;
|
|
4171
|
+
}
|
|
4172
|
+
function resolveReturnedClass(factoryDecl) {
|
|
4173
|
+
const body = factoryDecl.getBody();
|
|
4174
|
+
if (!body) return void 0;
|
|
4175
|
+
const returns = body.getDescendants().filter((n) => Node7.isReturnStatement(n));
|
|
4176
|
+
for (const ret of returns) {
|
|
4177
|
+
const expr = ret.getExpression();
|
|
4178
|
+
if (!expr) continue;
|
|
4179
|
+
const inner = unwrapExpression(expr);
|
|
4180
|
+
if (Node7.isClassExpression(inner)) {
|
|
4181
|
+
return inner;
|
|
4182
|
+
}
|
|
4183
|
+
if (Node7.isIdentifier(inner)) {
|
|
4184
|
+
const name = inner.getText();
|
|
4185
|
+
const decl = body.getDescendants().find((n) => Node7.isClassDeclaration(n) && n.getName() === name);
|
|
4186
|
+
if (decl) return decl;
|
|
4187
|
+
}
|
|
4188
|
+
}
|
|
4189
|
+
return void 0;
|
|
4190
|
+
}
|
|
4191
|
+
function resolveInheritedMethods(cls) {
|
|
4192
|
+
const expr = cls.getExtends()?.getExpression();
|
|
4193
|
+
if (!expr || !Node7.isCallExpression(expr)) return void 0;
|
|
4194
|
+
const callee = expr.getExpression();
|
|
4195
|
+
if (!Node7.isIdentifier(callee)) return void 0;
|
|
4196
|
+
const factoryDecl = callee.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => Node7.isFunctionDeclaration(n));
|
|
4197
|
+
if (!factoryDecl) return void 0;
|
|
4198
|
+
const returnedClass = resolveReturnedClass(factoryDecl);
|
|
4199
|
+
if (!returnedClass) return void 0;
|
|
4200
|
+
const classArgs = [];
|
|
4201
|
+
for (const arg of expr.getArguments()) {
|
|
4202
|
+
if (!Node7.isIdentifier(arg)) continue;
|
|
4203
|
+
const decl = arg.getDefinitions().map((d) => d.getDeclarationNode()).find((n) => Node7.isClassDeclaration(n));
|
|
4204
|
+
if (decl) {
|
|
4205
|
+
classArgs.push({
|
|
4206
|
+
name: decl.getName() ?? arg.getText(),
|
|
4207
|
+
filePath: decl.getSourceFile().getFilePath()
|
|
4208
|
+
});
|
|
4209
|
+
}
|
|
4210
|
+
}
|
|
4211
|
+
return {
|
|
4212
|
+
methods: returnedClass.getMethods(),
|
|
4213
|
+
factoryName: callee.getText(),
|
|
4214
|
+
factoryFilePath: factoryDecl.getSourceFile().getFilePath(),
|
|
4215
|
+
classArgs
|
|
4216
|
+
};
|
|
4217
|
+
}
|
|
4218
|
+
var mixinTypeProject;
|
|
4219
|
+
function getMixinTypeProject() {
|
|
4220
|
+
mixinTypeProject ??= new Project3({
|
|
4221
|
+
skipAddingFilesFromTsConfig: true,
|
|
4222
|
+
compilerOptions: { strict: true }
|
|
4223
|
+
});
|
|
4224
|
+
return mixinTypeProject;
|
|
4225
|
+
}
|
|
4226
|
+
function clearMixinTypeProject() {
|
|
4227
|
+
mixinTypeProject = void 0;
|
|
4228
|
+
}
|
|
4229
|
+
function resolveInstantiatedReturnType(cls, methodName) {
|
|
4230
|
+
const filePath = cls.getSourceFile().getFilePath();
|
|
4231
|
+
const className = cls.getName();
|
|
4232
|
+
if (!className) return void 0;
|
|
4233
|
+
const project = getMixinTypeProject();
|
|
4234
|
+
const sourceFile = project.getSourceFile(filePath) ?? project.addSourceFileAtPathIfExists(filePath);
|
|
4235
|
+
const typedCls = sourceFile?.getClass(className);
|
|
4236
|
+
if (!typedCls) return void 0;
|
|
4237
|
+
const prop = typedCls.getType().getProperty(methodName);
|
|
4238
|
+
if (!prop) return void 0;
|
|
4239
|
+
const returnType = prop.getTypeAtLocation(typedCls).getCallSignatures()[0]?.getReturnType();
|
|
4240
|
+
if (!returnType) return void 0;
|
|
4241
|
+
const unwrapped = returnType.getSymbol()?.getName() === "Promise" ? returnType.getTypeArguments()[0] ?? returnType : returnType;
|
|
4242
|
+
return unwrapped.getText(typedCls);
|
|
4243
|
+
}
|
|
4244
|
+
|
|
4148
4245
|
// src/discovery/zod-ast-to-ts.ts
|
|
4149
|
-
import { Node as
|
|
4246
|
+
import { Node as Node8, SyntaxKind as SyntaxKind4 } from "ts-morph";
|
|
4150
4247
|
function zodAstToTs(node) {
|
|
4151
|
-
if (!
|
|
4248
|
+
if (!Node8.isCallExpression(node)) return "unknown";
|
|
4152
4249
|
const expr = node.getExpression();
|
|
4153
|
-
if (
|
|
4250
|
+
if (Node8.isPropertyAccessExpression(expr)) {
|
|
4154
4251
|
const methodName = expr.getName();
|
|
4155
4252
|
const receiver = expr.getExpression();
|
|
4156
4253
|
if (methodName === "optional") {
|
|
@@ -4174,17 +4271,17 @@ function zodAstToTs(node) {
|
|
|
4174
4271
|
case "literal": {
|
|
4175
4272
|
const lit = args[0];
|
|
4176
4273
|
if (!lit) return "unknown";
|
|
4177
|
-
if (
|
|
4178
|
-
if (
|
|
4274
|
+
if (Node8.isStringLiteral(lit)) return JSON.stringify(lit.getLiteralValue());
|
|
4275
|
+
if (Node8.isNumericLiteral(lit)) return lit.getLiteralValue().toString();
|
|
4179
4276
|
if (lit.getKind() === SyntaxKind4.TrueKeyword) return "true";
|
|
4180
4277
|
if (lit.getKind() === SyntaxKind4.FalseKeyword) return "false";
|
|
4181
4278
|
return "unknown";
|
|
4182
4279
|
}
|
|
4183
4280
|
case "enum": {
|
|
4184
4281
|
const arrArg = args[0];
|
|
4185
|
-
if (!arrArg || !
|
|
4282
|
+
if (!arrArg || !Node8.isArrayLiteralExpression(arrArg)) return "unknown";
|
|
4186
4283
|
const members = arrArg.getElements().map(
|
|
4187
|
-
(el) =>
|
|
4284
|
+
(el) => Node8.isStringLiteral(el) ? JSON.stringify(el.getLiteralValue()) : "unknown"
|
|
4188
4285
|
);
|
|
4189
4286
|
return members.join(" | ");
|
|
4190
4287
|
}
|
|
@@ -4195,10 +4292,10 @@ function zodAstToTs(node) {
|
|
|
4195
4292
|
}
|
|
4196
4293
|
case "object": {
|
|
4197
4294
|
const objArg = args[0];
|
|
4198
|
-
if (!objArg || !
|
|
4295
|
+
if (!objArg || !Node8.isObjectLiteralExpression(objArg)) return "unknown";
|
|
4199
4296
|
const lines = [];
|
|
4200
4297
|
for (const prop of objArg.getProperties()) {
|
|
4201
|
-
if (!
|
|
4298
|
+
if (!Node8.isPropertyAssignment(prop)) continue;
|
|
4202
4299
|
const key = prop.getName();
|
|
4203
4300
|
const valNode = prop.getInitializer();
|
|
4204
4301
|
if (!valNode) continue;
|
|
@@ -4210,7 +4307,7 @@ function zodAstToTs(node) {
|
|
|
4210
4307
|
}
|
|
4211
4308
|
case "union": {
|
|
4212
4309
|
const arrArg = args[0];
|
|
4213
|
-
if (!arrArg || !
|
|
4310
|
+
if (!arrArg || !Node8.isArrayLiteralExpression(arrArg)) return "unknown";
|
|
4214
4311
|
return arrArg.getElements().map(zodAstToTs).join(" | ");
|
|
4215
4312
|
}
|
|
4216
4313
|
case "record": {
|
|
@@ -4220,7 +4317,7 @@ function zodAstToTs(node) {
|
|
|
4220
4317
|
}
|
|
4221
4318
|
case "tuple": {
|
|
4222
4319
|
const arrArg = args[0];
|
|
4223
|
-
if (!arrArg || !
|
|
4320
|
+
if (!arrArg || !Node8.isArrayLiteralExpression(arrArg)) return "unknown";
|
|
4224
4321
|
return `[${arrArg.getElements().map(zodAstToTs).join(", ")}]`;
|
|
4225
4322
|
}
|
|
4226
4323
|
default:
|
|
@@ -4230,18 +4327,18 @@ function zodAstToTs(node) {
|
|
|
4230
4327
|
return "unknown";
|
|
4231
4328
|
}
|
|
4232
4329
|
function isOptionalChain(node) {
|
|
4233
|
-
if (!
|
|
4330
|
+
if (!Node8.isCallExpression(node)) return false;
|
|
4234
4331
|
const expr = node.getExpression();
|
|
4235
|
-
return
|
|
4332
|
+
return Node8.isPropertyAccessExpression(expr) && expr.getName() === "optional";
|
|
4236
4333
|
}
|
|
4237
4334
|
function parseDefineContractCall(callExpr) {
|
|
4238
|
-
if (!
|
|
4335
|
+
if (!Node8.isCallExpression(callExpr)) return null;
|
|
4239
4336
|
const callee = callExpr.getExpression();
|
|
4240
|
-
const calleeName =
|
|
4337
|
+
const calleeName = Node8.isIdentifier(callee) ? callee.getText() : Node8.isPropertyAccessExpression(callee) ? callee.getName() : "";
|
|
4241
4338
|
if (calleeName !== "defineContract") return null;
|
|
4242
4339
|
const args = callExpr.getArguments();
|
|
4243
4340
|
const optsArg = args[0];
|
|
4244
|
-
if (!optsArg || !
|
|
4341
|
+
if (!optsArg || !Node8.isObjectLiteralExpression(optsArg)) return null;
|
|
4245
4342
|
let query = null;
|
|
4246
4343
|
let body = null;
|
|
4247
4344
|
let response = "unknown";
|
|
@@ -4249,7 +4346,7 @@ function parseDefineContractCall(callExpr) {
|
|
|
4249
4346
|
let bodyZodText = null;
|
|
4250
4347
|
let queryZodText = null;
|
|
4251
4348
|
for (const prop of optsArg.getProperties()) {
|
|
4252
|
-
if (!
|
|
4349
|
+
if (!Node8.isPropertyAssignment(prop)) continue;
|
|
4253
4350
|
const propName = prop.getName();
|
|
4254
4351
|
const val = prop.getInitializer();
|
|
4255
4352
|
if (!val) continue;
|
|
@@ -4278,6 +4375,7 @@ async function discoverContractsFast(opts) {
|
|
|
4278
4375
|
project.addSourceFileAtPath(f);
|
|
4279
4376
|
}
|
|
4280
4377
|
bindDiscoveryContext(project, cwd, tsconfigPath);
|
|
4378
|
+
clearMixinTypeProject();
|
|
4281
4379
|
return extractAllRoutes(project);
|
|
4282
4380
|
}
|
|
4283
4381
|
function resolveTsconfigPath(cwd, tsconfig) {
|
|
@@ -4285,14 +4383,14 @@ function resolveTsconfigPath(cwd, tsconfig) {
|
|
|
4285
4383
|
}
|
|
4286
4384
|
function createDiscoveryProject(tsconfigPath) {
|
|
4287
4385
|
try {
|
|
4288
|
-
return new
|
|
4386
|
+
return new Project4({
|
|
4289
4387
|
tsConfigFilePath: tsconfigPath,
|
|
4290
4388
|
skipAddingFilesFromTsConfig: true,
|
|
4291
4389
|
skipLoadingLibFiles: true,
|
|
4292
4390
|
skipFileDependencyResolution: true
|
|
4293
4391
|
});
|
|
4294
4392
|
} catch {
|
|
4295
|
-
return new
|
|
4393
|
+
return new Project4({
|
|
4296
4394
|
skipAddingFilesFromTsConfig: true,
|
|
4297
4395
|
skipLoadingLibFiles: true,
|
|
4298
4396
|
skipFileDependencyResolution: true,
|
|
@@ -4399,15 +4497,16 @@ var PersistentDiscovery = class _PersistentDiscovery {
|
|
|
4399
4497
|
runExtraction() {
|
|
4400
4498
|
clearTypeResolutionCaches(this.project);
|
|
4401
4499
|
clearEnumCache(this.project);
|
|
4500
|
+
clearMixinTypeProject();
|
|
4402
4501
|
return extractRoutesFrom(this.project, this.controllerPaths);
|
|
4403
4502
|
}
|
|
4404
4503
|
};
|
|
4405
4504
|
function decoratorStringArg(decoratorExpr) {
|
|
4406
4505
|
if (!decoratorExpr) return void 0;
|
|
4407
|
-
if (
|
|
4408
|
-
if (
|
|
4506
|
+
if (Node9.isStringLiteral(decoratorExpr)) return decoratorExpr.getLiteralValue();
|
|
4507
|
+
if (Node9.isArrayLiteralExpression(decoratorExpr)) {
|
|
4409
4508
|
const first = decoratorExpr.getElements()[0];
|
|
4410
|
-
if (first &&
|
|
4509
|
+
if (first && Node9.isStringLiteral(first)) return first.getLiteralValue();
|
|
4411
4510
|
}
|
|
4412
4511
|
return void 0;
|
|
4413
4512
|
}
|
|
@@ -4429,7 +4528,8 @@ function joinPaths(prefix, suffix) {
|
|
|
4429
4528
|
if (!prefix && !suffix) return "/";
|
|
4430
4529
|
if (!prefix) return suffix.startsWith("/") ? suffix : `/${suffix}`;
|
|
4431
4530
|
if (!suffix) return prefix.startsWith("/") ? prefix : `/${prefix}`;
|
|
4432
|
-
const
|
|
4531
|
+
const withLeadingSlash = prefix.startsWith("/") ? prefix : `/${prefix}`;
|
|
4532
|
+
const p = withLeadingSlash.endsWith("/") ? withLeadingSlash.slice(0, -1) : withLeadingSlash;
|
|
4433
4533
|
const s = suffix.startsWith("/") ? suffix : `/${suffix}`;
|
|
4434
4534
|
const combined = p + s;
|
|
4435
4535
|
return combined === "" ? "/" : combined;
|
|
@@ -4483,7 +4583,8 @@ function buildRoute(args) {
|
|
|
4483
4583
|
methodAs,
|
|
4484
4584
|
sourceFile,
|
|
4485
4585
|
seenNames,
|
|
4486
|
-
contractSource
|
|
4586
|
+
contractSource,
|
|
4587
|
+
mixin
|
|
4487
4588
|
} = args;
|
|
4488
4589
|
const routeName = resolveRouteName(className, methodName, classAs, methodAs);
|
|
4489
4590
|
const qualifiedRef = `${className}.${methodName}`;
|
|
@@ -4499,7 +4600,12 @@ function buildRoute(args) {
|
|
|
4499
4600
|
path: combinedPath,
|
|
4500
4601
|
name: routeName,
|
|
4501
4602
|
params: extractParams(combinedPath),
|
|
4502
|
-
controllerRef: {
|
|
4603
|
+
controllerRef: {
|
|
4604
|
+
className,
|
|
4605
|
+
methodName,
|
|
4606
|
+
filePath: sourceFile.getFilePath(),
|
|
4607
|
+
...mixin ? { mixin } : {}
|
|
4608
|
+
},
|
|
4503
4609
|
contract: { contractSource }
|
|
4504
4610
|
};
|
|
4505
4611
|
}
|
|
@@ -4513,16 +4619,17 @@ function extractContractRoute(args) {
|
|
|
4513
4619
|
className,
|
|
4514
4620
|
sourceFile,
|
|
4515
4621
|
project,
|
|
4516
|
-
seenNames
|
|
4622
|
+
seenNames,
|
|
4623
|
+
mixin
|
|
4517
4624
|
} = args;
|
|
4518
4625
|
const firstDecoratorArg = applyContractDecorator.getArguments()[0];
|
|
4519
4626
|
if (!firstDecoratorArg) return null;
|
|
4520
4627
|
let contractDef = null;
|
|
4521
4628
|
let bodyZodRef = null;
|
|
4522
4629
|
let queryZodRef = null;
|
|
4523
|
-
if (
|
|
4630
|
+
if (Node9.isCallExpression(firstDecoratorArg)) {
|
|
4524
4631
|
contractDef = parseDefineContractCall(firstDecoratorArg);
|
|
4525
|
-
} else if (
|
|
4632
|
+
} else if (Node9.isIdentifier(firstDecoratorArg)) {
|
|
4526
4633
|
const identName = firstDecoratorArg.getText();
|
|
4527
4634
|
const resolvedVar = resolveImportedVariable(identName, sourceFile, project);
|
|
4528
4635
|
if (!resolvedVar) {
|
|
@@ -4565,6 +4672,7 @@ function extractContractRoute(args) {
|
|
|
4565
4672
|
methodAs,
|
|
4566
4673
|
sourceFile,
|
|
4567
4674
|
seenNames,
|
|
4675
|
+
mixin,
|
|
4568
4676
|
contractSource: {
|
|
4569
4677
|
query: contractDef.query,
|
|
4570
4678
|
body: contractDef.body,
|
|
@@ -4581,13 +4689,14 @@ function extractContractRoute(args) {
|
|
|
4581
4689
|
});
|
|
4582
4690
|
}
|
|
4583
4691
|
function extractDtoRoute(args) {
|
|
4584
|
-
const { cls, method, verb, prefix, className, sourceFile, project, seenNames } = args;
|
|
4692
|
+
const { cls, method, verb, prefix, className, sourceFile, project, seenNames, mixin } = args;
|
|
4585
4693
|
if (!verb) return null;
|
|
4586
4694
|
const combined = joinPaths(prefix, verb.handlerPath);
|
|
4587
4695
|
const methodName = method.getName();
|
|
4588
4696
|
const classAs = readAsDecorator(cls, `class ${className}`);
|
|
4589
4697
|
const methodAs = readAsDecorator(method, `${className}.${methodName}`);
|
|
4590
|
-
const dtoContract = extractDtoContract(method, sourceFile, project);
|
|
4698
|
+
const dtoContract = extractDtoContract(method, sourceFile, project, mixin);
|
|
4699
|
+
const mixinResponse = mixin ? resolveInstantiatedReturnType(cls, methodName) : void 0;
|
|
4591
4700
|
return buildRoute({
|
|
4592
4701
|
className,
|
|
4593
4702
|
methodName,
|
|
@@ -4597,10 +4706,11 @@ function extractDtoRoute(args) {
|
|
|
4597
4706
|
methodAs,
|
|
4598
4707
|
sourceFile,
|
|
4599
4708
|
seenNames,
|
|
4709
|
+
mixin,
|
|
4600
4710
|
contractSource: {
|
|
4601
4711
|
query: dtoContract?.query ?? null,
|
|
4602
4712
|
body: dtoContract?.body ?? null,
|
|
4603
|
-
response: dtoContract?.response ?? "unknown",
|
|
4713
|
+
response: mixinResponse ?? dtoContract?.response ?? "unknown",
|
|
4604
4714
|
error: dtoContract?.error ?? null,
|
|
4605
4715
|
queryRef: dtoContract?.queryRef ?? null,
|
|
4606
4716
|
bodyRef: dtoContract?.bodyRef ?? null,
|
|
@@ -4629,7 +4739,17 @@ function extractFromSourceFile(sourceFile, project) {
|
|
|
4629
4739
|
const firstArg2 = controllerDecorator.getArguments()[0];
|
|
4630
4740
|
const prefix = decoratorStringArg(firstArg2) ?? "";
|
|
4631
4741
|
const className = cls.getName() ?? "Unknown";
|
|
4632
|
-
|
|
4742
|
+
const inherited = resolveInheritedMethods(cls);
|
|
4743
|
+
const mixinBinding = inherited ? {
|
|
4744
|
+
factoryName: inherited.factoryName,
|
|
4745
|
+
factoryFilePath: inherited.factoryFilePath,
|
|
4746
|
+
classArgs: inherited.classArgs
|
|
4747
|
+
} : void 0;
|
|
4748
|
+
const methods = [
|
|
4749
|
+
...cls.getMethods().map((method) => ({ method })),
|
|
4750
|
+
...(inherited?.methods ?? []).map((method) => ({ method, mixin: mixinBinding }))
|
|
4751
|
+
];
|
|
4752
|
+
for (const { method, mixin } of methods) {
|
|
4633
4753
|
const verb = resolveVerb(method);
|
|
4634
4754
|
const applyContractDecorator = method.getDecorator("ApplyContract");
|
|
4635
4755
|
const route = applyContractDecorator ? extractContractRoute({
|
|
@@ -4641,7 +4761,8 @@ function extractFromSourceFile(sourceFile, project) {
|
|
|
4641
4761
|
className,
|
|
4642
4762
|
sourceFile,
|
|
4643
4763
|
project,
|
|
4644
|
-
seenNames
|
|
4764
|
+
seenNames,
|
|
4765
|
+
mixin
|
|
4645
4766
|
}) : extractDtoRoute({
|
|
4646
4767
|
cls,
|
|
4647
4768
|
method,
|
|
@@ -4650,7 +4771,8 @@ function extractFromSourceFile(sourceFile, project) {
|
|
|
4650
4771
|
className,
|
|
4651
4772
|
sourceFile,
|
|
4652
4773
|
project,
|
|
4653
|
-
seenNames
|
|
4774
|
+
seenNames,
|
|
4775
|
+
mixin
|
|
4654
4776
|
});
|
|
4655
4777
|
if (route) routes.push(route);
|
|
4656
4778
|
}
|
|
@@ -4934,7 +5056,7 @@ function createChainModuleRenderer(opts) {
|
|
|
4934
5056
|
}
|
|
4935
5057
|
|
|
4936
5058
|
// src/index.ts
|
|
4937
|
-
var VERSION = "0.
|
|
5059
|
+
var VERSION = "0.16.0";
|
|
4938
5060
|
export {
|
|
4939
5061
|
CodegenError,
|
|
4940
5062
|
ConfigError,
|