adorn-api 1.0.9 → 1.0.10
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/dist/cli.cjs +106 -50
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +106 -50
- package/dist/cli.js.map +1 -1
- package/dist/compiler/analyze/scanControllers.d.ts +1 -0
- package/dist/compiler/analyze/scanControllers.d.ts.map +1 -1
- package/dist/compiler/schema/typeToJsonSchema.d.ts.map +1 -1
- package/dist/metal/searchWhere.d.ts +20 -9
- package/dist/metal/searchWhere.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -137,6 +137,7 @@ function analyzeMethod(node, className, checker) {
|
|
|
137
137
|
if (!signature) return null;
|
|
138
138
|
let returnType = checker.getReturnTypeOfSignature(signature);
|
|
139
139
|
returnType = unwrapPromise(returnType, checker);
|
|
140
|
+
const returnTypeNode = unwrapPromiseTypeNode(node.type);
|
|
140
141
|
const parameters = [];
|
|
141
142
|
for (let i = 0; i < node.parameters.length; i++) {
|
|
142
143
|
const param = node.parameters[i];
|
|
@@ -161,6 +162,7 @@ function analyzeMethod(node, className, checker) {
|
|
|
161
162
|
operationId: defaultOperationId(className, methodName),
|
|
162
163
|
methodDeclaration: node,
|
|
163
164
|
returnType,
|
|
165
|
+
returnTypeNode,
|
|
164
166
|
parameters,
|
|
165
167
|
pathParamIndices,
|
|
166
168
|
bodyParamIndex,
|
|
@@ -291,6 +293,15 @@ function unwrapPromise(type, checker) {
|
|
|
291
293
|
}
|
|
292
294
|
return type;
|
|
293
295
|
}
|
|
296
|
+
function unwrapPromiseTypeNode(typeNode) {
|
|
297
|
+
if (!typeNode) return void 0;
|
|
298
|
+
if (ts2.isTypeReferenceNode(typeNode)) {
|
|
299
|
+
if (ts2.isIdentifier(typeNode.typeName) && typeNode.typeName.text === "Promise") {
|
|
300
|
+
return typeNode.typeArguments?.[0] ?? typeNode;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return typeNode;
|
|
304
|
+
}
|
|
294
305
|
|
|
295
306
|
// src/compiler/schema/openapi.ts
|
|
296
307
|
import ts6 from "typescript";
|
|
@@ -337,10 +348,10 @@ function typeToJsonSchema(type, ctx, typeNode) {
|
|
|
337
348
|
return { type: "boolean", enum: [intrinsic === "true"] };
|
|
338
349
|
}
|
|
339
350
|
if (type.isUnion()) {
|
|
340
|
-
return handleUnion(type
|
|
351
|
+
return handleUnion(type, ctx, typeNode);
|
|
341
352
|
}
|
|
342
353
|
if (type.isIntersection()) {
|
|
343
|
-
return handleIntersection(type
|
|
354
|
+
return handleIntersection(type, ctx, typeNode);
|
|
344
355
|
}
|
|
345
356
|
if (checker.isArrayType(type)) {
|
|
346
357
|
const typeArgs = type.typeArguments;
|
|
@@ -377,56 +388,96 @@ function isSetType(type, checker) {
|
|
|
377
388
|
if (name === "Set") return true;
|
|
378
389
|
return false;
|
|
379
390
|
}
|
|
380
|
-
function
|
|
381
|
-
const
|
|
382
|
-
const
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
const enumValues = otherTypes.map((t) => t.value);
|
|
386
|
-
const schema = { type: "string", enum: enumValues };
|
|
387
|
-
if (nullType) {
|
|
388
|
-
schema.type = ["string", "null"];
|
|
389
|
-
}
|
|
390
|
-
return schema;
|
|
391
|
+
function getSchemaName(type, typeNode) {
|
|
392
|
+
const aliasSymbol = type.aliasSymbol ?? type.aliasSymbol;
|
|
393
|
+
const aliasName = aliasSymbol?.getName();
|
|
394
|
+
if (aliasName && aliasName !== "__type") {
|
|
395
|
+
return aliasName;
|
|
391
396
|
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
}
|
|
397
|
-
return innerSchema;
|
|
398
|
-
}
|
|
399
|
-
if (otherTypes.length > 1) {
|
|
400
|
-
const branches = otherTypes.map((t) => typeToJsonSchema(t, ctx));
|
|
401
|
-
const hasNull = !!nullType;
|
|
402
|
-
const result = {};
|
|
403
|
-
if (hasNull) {
|
|
404
|
-
result.anyOf = [...branches, { type: "null" }];
|
|
405
|
-
} else {
|
|
406
|
-
result.anyOf = branches;
|
|
407
|
-
}
|
|
408
|
-
const discriminatorResult = detectDiscriminatedUnion(otherTypes, ctx, branches);
|
|
409
|
-
if (discriminatorResult) {
|
|
410
|
-
result.oneOf = branches;
|
|
411
|
-
result.discriminator = discriminatorResult;
|
|
412
|
-
}
|
|
413
|
-
return result;
|
|
397
|
+
const symbol = type.getSymbol();
|
|
398
|
+
const symbolName = symbol?.getName?.();
|
|
399
|
+
if (symbolName && symbolName !== "__type") {
|
|
400
|
+
return symbolName;
|
|
414
401
|
}
|
|
415
|
-
|
|
416
|
-
|
|
402
|
+
const nodeName = getExplicitTypeNameFromNode(typeNode);
|
|
403
|
+
if (nodeName && nodeName !== "__type") {
|
|
404
|
+
return nodeName;
|
|
417
405
|
}
|
|
418
|
-
return
|
|
406
|
+
return null;
|
|
419
407
|
}
|
|
420
|
-
function
|
|
421
|
-
const
|
|
422
|
-
if (
|
|
423
|
-
return
|
|
408
|
+
function buildNamedSchema(type, ctx, typeNode, build) {
|
|
409
|
+
const name = getSchemaName(type, typeNode);
|
|
410
|
+
if (!name) {
|
|
411
|
+
return build();
|
|
424
412
|
}
|
|
425
|
-
const
|
|
426
|
-
|
|
427
|
-
|
|
413
|
+
const { components, typeStack } = ctx;
|
|
414
|
+
if (components.has(name) || typeStack.has(type)) {
|
|
415
|
+
return { $ref: `#/components/schemas/${name}` };
|
|
428
416
|
}
|
|
429
|
-
|
|
417
|
+
typeStack.add(type);
|
|
418
|
+
const schema = build();
|
|
419
|
+
typeStack.delete(type);
|
|
420
|
+
if (!components.has(name)) {
|
|
421
|
+
components.set(name, schema);
|
|
422
|
+
}
|
|
423
|
+
return { $ref: `#/components/schemas/${name}` };
|
|
424
|
+
}
|
|
425
|
+
function handleUnion(type, ctx, typeNode) {
|
|
426
|
+
return buildNamedSchema(type, ctx, typeNode, () => {
|
|
427
|
+
const types = type.types;
|
|
428
|
+
const nullType = types.find((t) => t.flags & ts3.TypeFlags.Null);
|
|
429
|
+
const otherTypes = types.filter((t) => !(t.flags & ts3.TypeFlags.Null) && !(t.flags & ts3.TypeFlags.Undefined));
|
|
430
|
+
const allStringLiterals = otherTypes.every((t) => t.flags & ts3.TypeFlags.StringLiteral);
|
|
431
|
+
if (allStringLiterals && otherTypes.length > 0) {
|
|
432
|
+
const enumValues = otherTypes.map((t) => t.value);
|
|
433
|
+
const schema = { type: "string", enum: enumValues };
|
|
434
|
+
if (nullType) {
|
|
435
|
+
schema.type = ["string", "null"];
|
|
436
|
+
}
|
|
437
|
+
return schema;
|
|
438
|
+
}
|
|
439
|
+
if (otherTypes.length === 1 && nullType) {
|
|
440
|
+
const innerSchema = typeToJsonSchema(otherTypes[0], ctx);
|
|
441
|
+
if (typeof innerSchema.type === "string") {
|
|
442
|
+
innerSchema.type = [innerSchema.type, "null"];
|
|
443
|
+
}
|
|
444
|
+
return innerSchema;
|
|
445
|
+
}
|
|
446
|
+
if (otherTypes.length > 1) {
|
|
447
|
+
const branches = otherTypes.map((t) => typeToJsonSchema(t, ctx));
|
|
448
|
+
const hasNull = !!nullType;
|
|
449
|
+
const result = {};
|
|
450
|
+
if (hasNull) {
|
|
451
|
+
result.anyOf = [...branches, { type: "null" }];
|
|
452
|
+
} else {
|
|
453
|
+
result.anyOf = branches;
|
|
454
|
+
}
|
|
455
|
+
const discriminatorResult = detectDiscriminatedUnion(otherTypes, ctx, branches);
|
|
456
|
+
if (discriminatorResult) {
|
|
457
|
+
result.oneOf = branches;
|
|
458
|
+
result.discriminator = discriminatorResult;
|
|
459
|
+
}
|
|
460
|
+
return result;
|
|
461
|
+
}
|
|
462
|
+
if (otherTypes.length === 1) {
|
|
463
|
+
return typeToJsonSchema(otherTypes[0], ctx);
|
|
464
|
+
}
|
|
465
|
+
return {};
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
function handleIntersection(type, ctx, typeNode) {
|
|
469
|
+
return buildNamedSchema(type, ctx, typeNode, () => {
|
|
470
|
+
const types = type.types;
|
|
471
|
+
const brandCollapsed = tryCollapseBrandedIntersection(types, ctx, typeNode);
|
|
472
|
+
if (brandCollapsed) {
|
|
473
|
+
return brandCollapsed;
|
|
474
|
+
}
|
|
475
|
+
const allOf = [];
|
|
476
|
+
for (const t of types) {
|
|
477
|
+
allOf.push(typeToJsonSchema(t, ctx));
|
|
478
|
+
}
|
|
479
|
+
return { allOf };
|
|
480
|
+
});
|
|
430
481
|
}
|
|
431
482
|
function tryCollapseBrandedIntersection(types, ctx, typeNode) {
|
|
432
483
|
const { checker } = ctx;
|
|
@@ -557,8 +608,8 @@ function handleObjectType(type, ctx, typeNode) {
|
|
|
557
608
|
typeStack.delete(type);
|
|
558
609
|
return schema;
|
|
559
610
|
}
|
|
560
|
-
function
|
|
561
|
-
if (!typeNode) return
|
|
611
|
+
function getExplicitTypeNameFromNode(typeNode) {
|
|
612
|
+
if (!typeNode) return null;
|
|
562
613
|
if (ts3.isTypeReferenceNode(typeNode)) {
|
|
563
614
|
if (ts3.isIdentifier(typeNode.typeName)) {
|
|
564
615
|
return typeNode.typeName.text;
|
|
@@ -569,6 +620,11 @@ function getTypeNameFromNode(typeNode, ctx) {
|
|
|
569
620
|
return typeNode.parent.name.text;
|
|
570
621
|
}
|
|
571
622
|
}
|
|
623
|
+
return null;
|
|
624
|
+
}
|
|
625
|
+
function getTypeNameFromNode(typeNode, ctx) {
|
|
626
|
+
const explicitName = getExplicitTypeNameFromNode(typeNode);
|
|
627
|
+
if (explicitName) return explicitName;
|
|
572
628
|
return `Anonymous_${ctx.typeNameStack.length}`;
|
|
573
629
|
}
|
|
574
630
|
function buildObjectSchema(type, ctx, typeNode) {
|
|
@@ -867,7 +923,7 @@ function buildOperation(operation, ctx, controllerConsumes) {
|
|
|
867
923
|
if (parameters.length > 0) {
|
|
868
924
|
op.parameters = parameters;
|
|
869
925
|
}
|
|
870
|
-
const responseSchema = typeToJsonSchema(operation.returnType, ctx);
|
|
926
|
+
const responseSchema = typeToJsonSchema(operation.returnType, ctx, operation.returnTypeNode);
|
|
871
927
|
const status = operation.httpMethod === "POST" ? 201 : 200;
|
|
872
928
|
op.responses[status] = {
|
|
873
929
|
description: status === 201 ? "Created" : "OK",
|
|
@@ -1104,7 +1160,7 @@ function buildOperationEntry(op, ctx) {
|
|
|
1104
1160
|
};
|
|
1105
1161
|
}
|
|
1106
1162
|
}
|
|
1107
|
-
const responseSchema = typeToJsonSchema(op.returnType, ctx);
|
|
1163
|
+
const responseSchema = typeToJsonSchema(op.returnType, ctx, op.returnTypeNode);
|
|
1108
1164
|
const status = op.httpMethod === "POST" ? 201 : 200;
|
|
1109
1165
|
let schemaRef = responseSchema.$ref;
|
|
1110
1166
|
let isArray = false;
|