@trpc/openapi 11.19.0-alpha → 11.21.1-canary.20.10e2ef98f
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.mjs +120 -26
- package/dist/index.cjs +122 -27
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +122 -27
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
- package/src/generate.ts +226 -40
package/dist/cli.mjs
CHANGED
|
@@ -438,16 +438,45 @@ function convertUnionType(type, ctx, depth) {
|
|
|
438
438
|
const schemas = effective.map((m) => typeToJsonSchema(m, ctx, depth + 1)).filter(isNonEmptySchema);
|
|
439
439
|
if (hasBoolPair) schemas.push({ type: "boolean" });
|
|
440
440
|
if (hasNull) schemas.push({ type: "null" });
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
if (
|
|
445
|
-
|
|
441
|
+
const distinctSchemas = dedupeSchemas(schemas, ctx.schemas);
|
|
442
|
+
if (distinctSchemas.length === 0) return {};
|
|
443
|
+
const [firstSchema] = distinctSchemas;
|
|
444
|
+
if (distinctSchemas.length === 1 && firstSchema !== void 0) return firstSchema;
|
|
445
|
+
if (distinctSchemas.every(isSimpleTypeSchema)) return { type: distinctSchemas.map((s) => s.type) };
|
|
446
|
+
const discriminatorProp = detectDiscriminatorProperty(distinctSchemas);
|
|
446
447
|
if (discriminatorProp) return {
|
|
447
|
-
oneOf:
|
|
448
|
+
oneOf: distinctSchemas,
|
|
448
449
|
discriminator: { propertyName: discriminatorProp }
|
|
449
450
|
};
|
|
450
|
-
return { oneOf:
|
|
451
|
+
return { oneOf: distinctSchemas };
|
|
452
|
+
}
|
|
453
|
+
function dedupeSchemas(schemas, components) {
|
|
454
|
+
const seen = /* @__PURE__ */ new Set();
|
|
455
|
+
return schemas.filter((schema) => {
|
|
456
|
+
const key = canonicalize(resolveBareRef(schema, components));
|
|
457
|
+
if (seen.has(key)) return false;
|
|
458
|
+
seen.add(key);
|
|
459
|
+
return true;
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* A `$ref` on its own describes exactly the component it points at, so compare
|
|
464
|
+
* through the component - otherwise the same shape reached both by reference
|
|
465
|
+
* and inline looks like two distinct schemas.
|
|
466
|
+
*/
|
|
467
|
+
function resolveBareRef(schema, components) {
|
|
468
|
+
if (!isBareRef(schema)) return schema;
|
|
469
|
+
const target = getReferencedSchema(schema, components);
|
|
470
|
+
return target && isNonEmptySchema(target) ? target : schema;
|
|
471
|
+
}
|
|
472
|
+
/** A `$ref` with no sibling keys, i.e. one that stands for its component. */
|
|
473
|
+
function isBareRef(schema) {
|
|
474
|
+
return schema.$ref !== void 0 && Object.keys(schema).length === 1;
|
|
475
|
+
}
|
|
476
|
+
function canonicalize(value) {
|
|
477
|
+
if (Array.isArray(value)) return `[${value.map(canonicalize).join(",")}]`;
|
|
478
|
+
if (value && typeof value === "object") return `{${Object.entries(value).filter(([, v]) => v !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([k, v]) => `${JSON.stringify(k)}:${canonicalize(v)}`).join(",")}}`;
|
|
479
|
+
return JSON.stringify(value) ?? "undefined";
|
|
451
480
|
}
|
|
452
481
|
/**
|
|
453
482
|
* If every schema in a oneOf is an object with a common required property
|
|
@@ -652,7 +681,11 @@ function getProcedureInputTypeName(type, path) {
|
|
|
652
681
|
const declarationName = ts.getNameOfDeclaration(declaration)?.getText();
|
|
653
682
|
if (declarationName && !ANONYMOUS_NAMES.has(declarationName) && !declarationName.startsWith("__")) return declarationName;
|
|
654
683
|
}
|
|
655
|
-
return `${path
|
|
684
|
+
return `${pascalCasePath(path) || "Procedure"}Input`;
|
|
685
|
+
}
|
|
686
|
+
/** `user.getById` → `UserGetById`, for naming components after a procedure. */
|
|
687
|
+
function pascalCasePath(path) {
|
|
688
|
+
return path.split(".").filter(Boolean).map((segment) => segment.split(/[^A-Za-z0-9]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("")).join("");
|
|
656
689
|
}
|
|
657
690
|
function isUnknownLikeType(type) {
|
|
658
691
|
return hasFlag(type, ts.TypeFlags.Unknown | ts.TypeFlags.Any);
|
|
@@ -733,9 +766,28 @@ function extractProcedure(def, ctx) {
|
|
|
733
766
|
type: def.typeName,
|
|
734
767
|
inputSchema,
|
|
735
768
|
outputSchema,
|
|
769
|
+
errorSchema: extractProcedureErrorSchema($typesType, ctx),
|
|
736
770
|
description: def.description
|
|
737
771
|
});
|
|
738
772
|
}
|
|
773
|
+
function extractProcedureErrorSchema($typesType, ctx) {
|
|
774
|
+
const { schemaCtx } = ctx;
|
|
775
|
+
const errorSym = $typesType.getProperty("errorShape");
|
|
776
|
+
if (!errorSym) return null;
|
|
777
|
+
const { checker } = schemaCtx;
|
|
778
|
+
const errorType = checker.getTypeOfSymbol(errorSym);
|
|
779
|
+
if (hasFlag(errorType, ts.TypeFlags.Any) || isUnknownLikeType(errorType) || addsNothingToRouterErrorType(errorType, ctx.routerErrorType, checker)) return null;
|
|
780
|
+
const schema = typeToJsonSchema(errorType, schemaCtx);
|
|
781
|
+
return isNonEmptySchema(schema) ? schema : null;
|
|
782
|
+
}
|
|
783
|
+
function addsNothingToRouterErrorType(errorType, routerErrorType, checker) {
|
|
784
|
+
if (!routerErrorType) return false;
|
|
785
|
+
if (errorType === routerErrorType) return true;
|
|
786
|
+
const describe = (type) => checker.typeToString(type, void 0, ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.UseFullyQualifiedType);
|
|
787
|
+
const unionMembers = (type) => type.isUnion() ? type.types : [type];
|
|
788
|
+
const routerMembers = new Set(unionMembers(routerErrorType).map(describe));
|
|
789
|
+
return unionMembers(errorType).every((member) => routerMembers.has(describe(member)));
|
|
790
|
+
}
|
|
739
791
|
/** Extract the JSDoc comment text from a symbol, if any. */
|
|
740
792
|
function getJsDocComment(sym, checker) {
|
|
741
793
|
const normalize = (filePath) => filePath.replace(/\\/g, "/");
|
|
@@ -823,7 +875,7 @@ function loadCompilerOptions(startDir) {
|
|
|
823
875
|
* it to a JSON Schema. Returns `null` when the path cannot be resolved
|
|
824
876
|
* (e.g. older tRPC versions or missing type info).
|
|
825
877
|
*/
|
|
826
|
-
function
|
|
878
|
+
function getRouterErrorType(routerType, checker) {
|
|
827
879
|
const walk = (type, keys) => {
|
|
828
880
|
const [head, ...rest] = keys;
|
|
829
881
|
if (!head) return type;
|
|
@@ -837,10 +889,21 @@ function extractErrorSchema(routerType, checker, schemaCtx) {
|
|
|
837
889
|
"$types",
|
|
838
890
|
"errorShape"
|
|
839
891
|
]);
|
|
892
|
+
if (!errorShapeType || hasFlag(errorShapeType, ts.TypeFlags.Any)) return null;
|
|
893
|
+
return errorShapeType;
|
|
894
|
+
}
|
|
895
|
+
function extractErrorSchema(routerType, checker, schemaCtx) {
|
|
896
|
+
const errorShapeType = getRouterErrorType(routerType, checker);
|
|
840
897
|
if (!errorShapeType) return null;
|
|
841
|
-
if (hasFlag(errorShapeType, ts.TypeFlags.Any)) return null;
|
|
842
898
|
return typeToJsonSchema(errorShapeType, schemaCtx);
|
|
843
899
|
}
|
|
900
|
+
function wrapInErrorEnvelope(errorSchema) {
|
|
901
|
+
return {
|
|
902
|
+
type: "object",
|
|
903
|
+
properties: { error: errorSchema },
|
|
904
|
+
required: ["error"]
|
|
905
|
+
};
|
|
906
|
+
}
|
|
844
907
|
/** Fallback error schema when the router type doesn't expose an error shape. */
|
|
845
908
|
const DEFAULT_ERROR_SCHEMA = {
|
|
846
909
|
type: "object",
|
|
@@ -872,7 +935,7 @@ function wrapInSuccessEnvelope(outputSchema) {
|
|
|
872
935
|
required: ["result"]
|
|
873
936
|
};
|
|
874
937
|
}
|
|
875
|
-
function buildProcedureOperation(proc, method) {
|
|
938
|
+
function buildProcedureOperation(proc, method, errorResponseRef) {
|
|
876
939
|
const [tag = proc.path] = proc.path.split(".");
|
|
877
940
|
const operation = {
|
|
878
941
|
operationId: proc.path,
|
|
@@ -883,7 +946,7 @@ function buildProcedureOperation(proc, method) {
|
|
|
883
946
|
description: "Successful response",
|
|
884
947
|
content: { "application/json": { schema: wrapInSuccessEnvelope(proc.outputSchema) } }
|
|
885
948
|
},
|
|
886
|
-
default: { $ref:
|
|
949
|
+
default: { $ref: errorResponseRef }
|
|
887
950
|
}
|
|
888
951
|
};
|
|
889
952
|
if (proc.inputSchema === null) return operation;
|
|
@@ -900,17 +963,54 @@ function buildProcedureOperation(proc, method) {
|
|
|
900
963
|
};
|
|
901
964
|
return operation;
|
|
902
965
|
}
|
|
966
|
+
function buildErrorResponse(schema) {
|
|
967
|
+
return {
|
|
968
|
+
description: "Error response",
|
|
969
|
+
content: { "application/json": { schema: wrapInErrorEnvelope(schema) } }
|
|
970
|
+
};
|
|
971
|
+
}
|
|
972
|
+
function buildErrorResponses(procedures, routerErrorSchema, schemas) {
|
|
973
|
+
const responses = { Error: buildErrorResponse(routerErrorSchema) };
|
|
974
|
+
const shapeKey = (schema) => canonicalize(resolveBareRef(schema, schemas));
|
|
975
|
+
const refByShape = /* @__PURE__ */ new Map([[shapeKey(routerErrorSchema), "#/components/responses/Error"]]);
|
|
976
|
+
const refByProcedurePath = /* @__PURE__ */ new Map();
|
|
977
|
+
for (const proc of procedures) {
|
|
978
|
+
if (!proc.errorSchema) continue;
|
|
979
|
+
const key = shapeKey(proc.errorSchema);
|
|
980
|
+
let ref = refByShape.get(key);
|
|
981
|
+
if (!ref) {
|
|
982
|
+
const name = `${pascalCasePath(proc.path) || "Procedure"}Error`;
|
|
983
|
+
const shape = isBareRef(proc.errorSchema) ? proc.errorSchema : registerSchema(`${name}Shape`, proc.errorSchema, schemas);
|
|
984
|
+
const responseName = ensureUniqueName(name, responses);
|
|
985
|
+
responses[responseName] = buildErrorResponse(shape);
|
|
986
|
+
ref = `#/components/responses/${responseName}`;
|
|
987
|
+
refByShape.set(key, ref);
|
|
988
|
+
}
|
|
989
|
+
refByProcedurePath.set(proc.path, ref);
|
|
990
|
+
}
|
|
991
|
+
return {
|
|
992
|
+
responses,
|
|
993
|
+
refByProcedurePath
|
|
994
|
+
};
|
|
995
|
+
}
|
|
996
|
+
function registerSchema(name, schema, schemas) {
|
|
997
|
+
const refName = ensureUniqueName(name, schemas);
|
|
998
|
+
schemas[refName] = schema;
|
|
999
|
+
return { $ref: `#/components/schemas/${refName}` };
|
|
1000
|
+
}
|
|
903
1001
|
function buildOpenAPIDocument(procedures, options, meta = { errorSchema: null }) {
|
|
904
1002
|
const paths = {};
|
|
905
|
-
|
|
906
|
-
|
|
1003
|
+
const included = procedures.filter((proc) => shouldIncludeProcedureInOpenAPI(proc.type));
|
|
1004
|
+
const schemas = meta.schemas ?? {};
|
|
1005
|
+
const { responses: errorResponses, refByProcedurePath } = buildErrorResponses(included, meta.errorSchema ?? DEFAULT_ERROR_SCHEMA, schemas);
|
|
1006
|
+
for (const proc of included) {
|
|
907
1007
|
const opPath = `/${proc.path}`;
|
|
908
1008
|
const method = proc.type === "query" ? "get" : "post";
|
|
909
1009
|
const pathItem = paths[opPath] ?? {};
|
|
910
1010
|
paths[opPath] = pathItem;
|
|
911
|
-
pathItem[method] = buildProcedureOperation(proc, method);
|
|
1011
|
+
pathItem[method] = buildProcedureOperation(proc, method, refByProcedurePath.get(proc.path) ?? "#/components/responses/Error");
|
|
912
1012
|
}
|
|
913
|
-
const hasNamedSchemas =
|
|
1013
|
+
const hasNamedSchemas = Object.keys(schemas).length > 0;
|
|
914
1014
|
return {
|
|
915
1015
|
openapi: "3.1.1",
|
|
916
1016
|
jsonSchemaDialect: "https://spec.openapis.org/oas/3.1/dialect/base",
|
|
@@ -921,15 +1021,8 @@ function buildOpenAPIDocument(procedures, options, meta = { errorSchema: null })
|
|
|
921
1021
|
...options.servers?.length ? { servers: options.servers } : {},
|
|
922
1022
|
paths,
|
|
923
1023
|
components: {
|
|
924
|
-
...hasNamedSchemas
|
|
925
|
-
responses:
|
|
926
|
-
description: "Error response",
|
|
927
|
-
content: { "application/json": { schema: {
|
|
928
|
-
type: "object",
|
|
929
|
-
properties: { error: meta.errorSchema ?? DEFAULT_ERROR_SCHEMA },
|
|
930
|
-
required: ["error"]
|
|
931
|
-
} } }
|
|
932
|
-
} }
|
|
1024
|
+
...hasNamedSchemas ? { schemas } : {},
|
|
1025
|
+
responses: errorResponses
|
|
933
1026
|
}
|
|
934
1027
|
};
|
|
935
1028
|
}
|
|
@@ -973,7 +1066,8 @@ async function generateOpenAPIDocument(routerFilePath, options = {}) {
|
|
|
973
1066
|
procedures: [],
|
|
974
1067
|
seen: /* @__PURE__ */ new Set(),
|
|
975
1068
|
schemaCtx,
|
|
976
|
-
runtimeDescriptions
|
|
1069
|
+
runtimeDescriptions,
|
|
1070
|
+
routerErrorType: getRouterErrorType(routerType, checker)
|
|
977
1071
|
};
|
|
978
1072
|
walkType({
|
|
979
1073
|
type: routerType,
|
package/dist/index.cjs
CHANGED
|
@@ -487,16 +487,46 @@ function convertUnionType(type, ctx, depth) {
|
|
|
487
487
|
const schemas = effective.map((m) => typeToJsonSchema(m, ctx, depth + 1)).filter(isNonEmptySchema);
|
|
488
488
|
if (hasBoolPair) schemas.push({ type: "boolean" });
|
|
489
489
|
if (hasNull) schemas.push({ type: "null" });
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
if (
|
|
494
|
-
|
|
490
|
+
const distinctSchemas = dedupeSchemas(schemas, ctx.schemas);
|
|
491
|
+
if (distinctSchemas.length === 0) return {};
|
|
492
|
+
const [firstSchema] = distinctSchemas;
|
|
493
|
+
if (distinctSchemas.length === 1 && firstSchema !== void 0) return firstSchema;
|
|
494
|
+
if (distinctSchemas.every(isSimpleTypeSchema)) return { type: distinctSchemas.map((s) => s.type) };
|
|
495
|
+
const discriminatorProp = detectDiscriminatorProperty(distinctSchemas);
|
|
495
496
|
if (discriminatorProp) return {
|
|
496
|
-
oneOf:
|
|
497
|
+
oneOf: distinctSchemas,
|
|
497
498
|
discriminator: { propertyName: discriminatorProp }
|
|
498
499
|
};
|
|
499
|
-
return { oneOf:
|
|
500
|
+
return { oneOf: distinctSchemas };
|
|
501
|
+
}
|
|
502
|
+
function dedupeSchemas(schemas, components) {
|
|
503
|
+
const seen = /* @__PURE__ */ new Set();
|
|
504
|
+
return schemas.filter((schema) => {
|
|
505
|
+
const key = canonicalize(resolveBareRef(schema, components));
|
|
506
|
+
if (seen.has(key)) return false;
|
|
507
|
+
seen.add(key);
|
|
508
|
+
return true;
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* A `$ref` on its own describes exactly the component it points at, so compare
|
|
513
|
+
* through the component - otherwise the same shape reached both by reference
|
|
514
|
+
* and inline looks like two distinct schemas.
|
|
515
|
+
*/
|
|
516
|
+
function resolveBareRef(schema, components) {
|
|
517
|
+
if (!isBareRef(schema)) return schema;
|
|
518
|
+
const target = getReferencedSchema(schema, components);
|
|
519
|
+
return target && isNonEmptySchema(target) ? target : schema;
|
|
520
|
+
}
|
|
521
|
+
/** A `$ref` with no sibling keys, i.e. one that stands for its component. */
|
|
522
|
+
function isBareRef(schema) {
|
|
523
|
+
return schema.$ref !== void 0 && Object.keys(schema).length === 1;
|
|
524
|
+
}
|
|
525
|
+
function canonicalize(value) {
|
|
526
|
+
var _JSON$stringify;
|
|
527
|
+
if (Array.isArray(value)) return `[${value.map(canonicalize).join(",")}]`;
|
|
528
|
+
if (value && typeof value === "object") return `{${Object.entries(value).filter(([, v]) => v !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([k, v]) => `${JSON.stringify(k)}:${canonicalize(v)}`).join(",")}}`;
|
|
529
|
+
return (_JSON$stringify = JSON.stringify(value)) !== null && _JSON$stringify !== void 0 ? _JSON$stringify : "undefined";
|
|
500
530
|
}
|
|
501
531
|
/**
|
|
502
532
|
* If every schema in a oneOf is an object with a common required property
|
|
@@ -709,7 +739,11 @@ function getProcedureInputTypeName(type, path) {
|
|
|
709
739
|
if (declarationName && !ANONYMOUS_NAMES.has(declarationName) && !declarationName.startsWith("__")) return declarationName;
|
|
710
740
|
}
|
|
711
741
|
}
|
|
712
|
-
return `${path
|
|
742
|
+
return `${pascalCasePath(path) || "Procedure"}Input`;
|
|
743
|
+
}
|
|
744
|
+
/** `user.getById` → `UserGetById`, for naming components after a procedure. */
|
|
745
|
+
function pascalCasePath(path) {
|
|
746
|
+
return path.split(".").filter(Boolean).map((segment) => segment.split(/[^A-Za-z0-9]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("")).join("");
|
|
713
747
|
}
|
|
714
748
|
function isUnknownLikeType(type) {
|
|
715
749
|
return hasFlag(type, typescript.TypeFlags.Unknown | typescript.TypeFlags.Any);
|
|
@@ -792,9 +826,28 @@ function extractProcedure(def, ctx) {
|
|
|
792
826
|
type: def.typeName,
|
|
793
827
|
inputSchema,
|
|
794
828
|
outputSchema,
|
|
829
|
+
errorSchema: extractProcedureErrorSchema($typesType, ctx),
|
|
795
830
|
description: def.description
|
|
796
831
|
});
|
|
797
832
|
}
|
|
833
|
+
function extractProcedureErrorSchema($typesType, ctx) {
|
|
834
|
+
const { schemaCtx } = ctx;
|
|
835
|
+
const errorSym = $typesType.getProperty("errorShape");
|
|
836
|
+
if (!errorSym) return null;
|
|
837
|
+
const { checker } = schemaCtx;
|
|
838
|
+
const errorType = checker.getTypeOfSymbol(errorSym);
|
|
839
|
+
if (hasFlag(errorType, typescript.TypeFlags.Any) || isUnknownLikeType(errorType) || addsNothingToRouterErrorType(errorType, ctx.routerErrorType, checker)) return null;
|
|
840
|
+
const schema = typeToJsonSchema(errorType, schemaCtx);
|
|
841
|
+
return isNonEmptySchema(schema) ? schema : null;
|
|
842
|
+
}
|
|
843
|
+
function addsNothingToRouterErrorType(errorType, routerErrorType, checker) {
|
|
844
|
+
if (!routerErrorType) return false;
|
|
845
|
+
if (errorType === routerErrorType) return true;
|
|
846
|
+
const describe = (type) => checker.typeToString(type, void 0, typescript.TypeFormatFlags.NoTruncation | typescript.TypeFormatFlags.UseFullyQualifiedType);
|
|
847
|
+
const unionMembers = (type) => type.isUnion() ? type.types : [type];
|
|
848
|
+
const routerMembers = new Set(unionMembers(routerErrorType).map(describe));
|
|
849
|
+
return unionMembers(errorType).every((member) => routerMembers.has(describe(member)));
|
|
850
|
+
}
|
|
798
851
|
/** Extract the JSDoc comment text from a symbol, if any. */
|
|
799
852
|
function getJsDocComment(sym, checker) {
|
|
800
853
|
var _sym$declarations2;
|
|
@@ -882,7 +935,7 @@ function loadCompilerOptions(startDir) {
|
|
|
882
935
|
* it to a JSON Schema. Returns `null` when the path cannot be resolved
|
|
883
936
|
* (e.g. older tRPC versions or missing type info).
|
|
884
937
|
*/
|
|
885
|
-
function
|
|
938
|
+
function getRouterErrorType(routerType, checker) {
|
|
886
939
|
const walk = (type, keys) => {
|
|
887
940
|
const [head, ...rest] = keys;
|
|
888
941
|
if (!head) return type;
|
|
@@ -896,10 +949,21 @@ function extractErrorSchema(routerType, checker, schemaCtx) {
|
|
|
896
949
|
"$types",
|
|
897
950
|
"errorShape"
|
|
898
951
|
]);
|
|
952
|
+
if (!errorShapeType || hasFlag(errorShapeType, typescript.TypeFlags.Any)) return null;
|
|
953
|
+
return errorShapeType;
|
|
954
|
+
}
|
|
955
|
+
function extractErrorSchema(routerType, checker, schemaCtx) {
|
|
956
|
+
const errorShapeType = getRouterErrorType(routerType, checker);
|
|
899
957
|
if (!errorShapeType) return null;
|
|
900
|
-
if (hasFlag(errorShapeType, typescript.TypeFlags.Any)) return null;
|
|
901
958
|
return typeToJsonSchema(errorShapeType, schemaCtx);
|
|
902
959
|
}
|
|
960
|
+
function wrapInErrorEnvelope(errorSchema) {
|
|
961
|
+
return {
|
|
962
|
+
type: "object",
|
|
963
|
+
properties: { error: errorSchema },
|
|
964
|
+
required: ["error"]
|
|
965
|
+
};
|
|
966
|
+
}
|
|
903
967
|
/** Fallback error schema when the router type doesn't expose an error shape. */
|
|
904
968
|
const DEFAULT_ERROR_SCHEMA = {
|
|
905
969
|
type: "object",
|
|
@@ -930,7 +994,7 @@ function wrapInSuccessEnvelope(outputSchema) {
|
|
|
930
994
|
required: ["result"]
|
|
931
995
|
};
|
|
932
996
|
}
|
|
933
|
-
function buildProcedureOperation(proc, method) {
|
|
997
|
+
function buildProcedureOperation(proc, method, errorResponseRef) {
|
|
934
998
|
const [tag = proc.path] = proc.path.split(".");
|
|
935
999
|
const operation = require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({ operationId: proc.path }, proc.description ? { description: proc.description } : {}), {}, {
|
|
936
1000
|
tags: [tag],
|
|
@@ -939,7 +1003,7 @@ function buildProcedureOperation(proc, method) {
|
|
|
939
1003
|
description: "Successful response",
|
|
940
1004
|
content: { "application/json": { schema: wrapInSuccessEnvelope(proc.outputSchema) } }
|
|
941
1005
|
},
|
|
942
|
-
default: { $ref:
|
|
1006
|
+
default: { $ref: errorResponseRef }
|
|
943
1007
|
}
|
|
944
1008
|
});
|
|
945
1009
|
if (proc.inputSchema === null) return operation;
|
|
@@ -956,19 +1020,56 @@ function buildProcedureOperation(proc, method) {
|
|
|
956
1020
|
};
|
|
957
1021
|
return operation;
|
|
958
1022
|
}
|
|
1023
|
+
function buildErrorResponse(schema) {
|
|
1024
|
+
return {
|
|
1025
|
+
description: "Error response",
|
|
1026
|
+
content: { "application/json": { schema: wrapInErrorEnvelope(schema) } }
|
|
1027
|
+
};
|
|
1028
|
+
}
|
|
1029
|
+
function buildErrorResponses(procedures, routerErrorSchema, schemas) {
|
|
1030
|
+
const responses = { Error: buildErrorResponse(routerErrorSchema) };
|
|
1031
|
+
const shapeKey = (schema) => canonicalize(resolveBareRef(schema, schemas));
|
|
1032
|
+
const refByShape = /* @__PURE__ */ new Map([[shapeKey(routerErrorSchema), "#/components/responses/Error"]]);
|
|
1033
|
+
const refByProcedurePath = /* @__PURE__ */ new Map();
|
|
1034
|
+
for (const proc of procedures) {
|
|
1035
|
+
if (!proc.errorSchema) continue;
|
|
1036
|
+
const key = shapeKey(proc.errorSchema);
|
|
1037
|
+
let ref = refByShape.get(key);
|
|
1038
|
+
if (!ref) {
|
|
1039
|
+
const name = `${pascalCasePath(proc.path) || "Procedure"}Error`;
|
|
1040
|
+
const shape = isBareRef(proc.errorSchema) ? proc.errorSchema : registerSchema(`${name}Shape`, proc.errorSchema, schemas);
|
|
1041
|
+
const responseName = ensureUniqueName(name, responses);
|
|
1042
|
+
responses[responseName] = buildErrorResponse(shape);
|
|
1043
|
+
ref = `#/components/responses/${responseName}`;
|
|
1044
|
+
refByShape.set(key, ref);
|
|
1045
|
+
}
|
|
1046
|
+
refByProcedurePath.set(proc.path, ref);
|
|
1047
|
+
}
|
|
1048
|
+
return {
|
|
1049
|
+
responses,
|
|
1050
|
+
refByProcedurePath
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
function registerSchema(name, schema, schemas) {
|
|
1054
|
+
const refName = ensureUniqueName(name, schemas);
|
|
1055
|
+
schemas[refName] = schema;
|
|
1056
|
+
return { $ref: `#/components/schemas/${refName}` };
|
|
1057
|
+
}
|
|
959
1058
|
function buildOpenAPIDocument(procedures, options, meta = { errorSchema: null }) {
|
|
960
|
-
var _options$title, _options$version, _options$servers
|
|
1059
|
+
var _meta$schemas, _meta$errorSchema, _options$title, _options$version, _options$servers;
|
|
961
1060
|
const paths = {};
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
1061
|
+
const included = procedures.filter((proc) => shouldIncludeProcedureInOpenAPI(proc.type));
|
|
1062
|
+
const schemas = (_meta$schemas = meta.schemas) !== null && _meta$schemas !== void 0 ? _meta$schemas : {};
|
|
1063
|
+
const { responses: errorResponses, refByProcedurePath } = buildErrorResponses(included, (_meta$errorSchema = meta.errorSchema) !== null && _meta$errorSchema !== void 0 ? _meta$errorSchema : DEFAULT_ERROR_SCHEMA, schemas);
|
|
1064
|
+
for (const proc of included) {
|
|
1065
|
+
var _paths$opPath, _refByProcedurePath$g;
|
|
965
1066
|
const opPath = `/${proc.path}`;
|
|
966
1067
|
const method = proc.type === "query" ? "get" : "post";
|
|
967
1068
|
const pathItem = (_paths$opPath = paths[opPath]) !== null && _paths$opPath !== void 0 ? _paths$opPath : {};
|
|
968
1069
|
paths[opPath] = pathItem;
|
|
969
|
-
pathItem[method] = buildProcedureOperation(proc, method);
|
|
1070
|
+
pathItem[method] = buildProcedureOperation(proc, method, (_refByProcedurePath$g = refByProcedurePath.get(proc.path)) !== null && _refByProcedurePath$g !== void 0 ? _refByProcedurePath$g : "#/components/responses/Error");
|
|
970
1071
|
}
|
|
971
|
-
const hasNamedSchemas =
|
|
1072
|
+
const hasNamedSchemas = Object.keys(schemas).length > 0;
|
|
972
1073
|
return require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({
|
|
973
1074
|
openapi: "3.1.1",
|
|
974
1075
|
jsonSchemaDialect: "https://spec.openapis.org/oas/3.1/dialect/base",
|
|
@@ -978,14 +1079,7 @@ function buildOpenAPIDocument(procedures, options, meta = { errorSchema: null })
|
|
|
978
1079
|
}
|
|
979
1080
|
}, ((_options$servers = options.servers) === null || _options$servers === void 0 ? void 0 : _options$servers.length) ? { servers: options.servers } : {}), {}, {
|
|
980
1081
|
paths,
|
|
981
|
-
components: require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, hasNamedSchemas
|
|
982
|
-
description: "Error response",
|
|
983
|
-
content: { "application/json": { schema: {
|
|
984
|
-
type: "object",
|
|
985
|
-
properties: { error: (_meta$errorSchema = meta.errorSchema) !== null && _meta$errorSchema !== void 0 ? _meta$errorSchema : DEFAULT_ERROR_SCHEMA },
|
|
986
|
-
required: ["error"]
|
|
987
|
-
} } }
|
|
988
|
-
} } })
|
|
1082
|
+
components: require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, hasNamedSchemas ? { schemas } : {}), {}, { responses: errorResponses })
|
|
989
1083
|
});
|
|
990
1084
|
}
|
|
991
1085
|
/**
|
|
@@ -1029,7 +1123,8 @@ async function generateOpenAPIDocument(routerFilePath, options = {}) {
|
|
|
1029
1123
|
procedures: [],
|
|
1030
1124
|
seen: /* @__PURE__ */ new Set(),
|
|
1031
1125
|
schemaCtx,
|
|
1032
|
-
runtimeDescriptions
|
|
1126
|
+
runtimeDescriptions,
|
|
1127
|
+
routerErrorType: getRouterErrorType(routerType, checker)
|
|
1033
1128
|
};
|
|
1034
1129
|
walkType({
|
|
1035
1130
|
type: routerType,
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/generate.ts"],"mappings":";;;;KAEY,QAAQ,SAAS,gBAAgB,KAAK,eAAe,gBAC/D;KAEU;KAGA,sBAAsB;KAEtB,cAAc,YAAgB;KAC9B,kBAAkB,YAAgB;KAClC,gBAAgB,YAAgB;KAChC,sBAAsB,YAAgB;KACtC,8BACV,YAAgB;KACN,YAAY,YAAgB;KAC5B,aAAa,YAAgB;KAC7B,uBAAuB,YAAgB;KACvC,eAAe,YAAgB;KAE/B,eAAe,QACzB,YAAgB;EAEd;EACA,QAAQ,eAAe;EACvB;EACA;EACA,aAAa,eAAe;EAC5B;EACA,QAAQ;EACR,cAAc;EACd;EACA;EACA,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,MAAM;EACN,iCAAiC;EACjC,gBAAgB;EAChB,eAAe;EACf,MAAM;EACN;EACA;EACA;;KAIQ,aAAa;UAER,0BAA0B;EACzC;EACA,OAAO;;KAGG,kBAAkB,QAC5B,YAAgB;EAEd,SAAS,eAAe;EACxB,WAAW,eAAe,kBAAkB;;UAI/B,4BAA4B,QAC3C,YAAgB;EAEd,SAAS,eAAe;EACxB,WAAW,eAAe,kBAAkB;EAC5C,UAAU,eAAe;;UAIZ,wBAAwB;EACvC;EACA;;KAGU,eAAe;KAEf,oBAAoB,QAC9B,YAAgB;EAEd,SAAS,eAAe;;KAIhB,iBAAiB,QAC3B,YAAgB;EAEd,UAAU,eAAe,kBAAkB;EAC3C,UAAU,eAAe;EACzB,QAAQ,eAAe,kBAAkB;;KAIjC,kBAAkB,eAAe,kBAAkB;KAEnD,gBAAgB,qBAAqB,QAC/C,YAAgB,gBAAgB;EAE9B,cAAc,kBAAkB;EAChC,cAAc,kBAAkB;EAChC,YAAY;EACZ,YAAY,eAAe,kBAAkB;KAG/C;KAEU,eAAe,qBAAqB,QAC9C,YAAgB,eAAe;EAE7B,cAAc,kBAAkB;QAGjC,UAAU,eAAe,gBAAgB;KAGhC,YAAY,mBAAmB,yBAAyB,gBAEjE,eAAe,KAAK;KAGX,iBAAiB,eAAe,iBAAiB;KAEjD,mBAAmB,QAC7B,YAAgB;EAEd,UAAU,eAAe;EACzB,YAAY,eAAe,kBAAkB;EAC7C,aAAa,eAAe,kBAAkB;EAC9C,gBAAgB,eAAe,kBAAkB;EACjD,UAAU,eAAe,kBAAkB;EAC3C,QAAQ,eAAe,kBAAkB;EACzC,YAAY,eAAe,kBAAkB;EAC7C,YAAY,eAAe,kBAAkB;;KAIrC,SAAS,qBAAqB,QACxC,YAAgB,SAAS;EAEvB,QAAQ,YAAY;EACpB,aAAa;;;;
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/generate.ts"],"mappings":";;;;KAEY,QAAQ,SAAS,gBAAgB,KAAK,eAAe,gBAC/D;KAEU;KAGA,sBAAsB;KAEtB,cAAc,YAAgB;KAC9B,kBAAkB,YAAgB;KAClC,gBAAgB,YAAgB;KAChC,sBAAsB,YAAgB;KACtC,8BACV,YAAgB;KACN,YAAY,YAAgB;KAC5B,aAAa,YAAgB;KAC7B,uBAAuB,YAAgB;KACvC,eAAe,YAAgB;KAE/B,eAAe,QACzB,YAAgB;EAEd;EACA,QAAQ,eAAe;EACvB;EACA;EACA,aAAa,eAAe;EAC5B;EACA,QAAQ;EACR,cAAc;EACd;EACA;EACA,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,MAAM;EACN,iCAAiC;EACjC,gBAAgB;EAChB,eAAe;EACf,MAAM;EACN;EACA;EACA;;KAIQ,aAAa;UAER,0BAA0B;EACzC;EACA,OAAO;;KAGG,kBAAkB,QAC5B,YAAgB;EAEd,SAAS,eAAe;EACxB,WAAW,eAAe,kBAAkB;;UAI/B,4BAA4B,QAC3C,YAAgB;EAEd,SAAS,eAAe;EACxB,WAAW,eAAe,kBAAkB;EAC5C,UAAU,eAAe;;UAIZ,wBAAwB;EACvC;EACA;;KAGU,eAAe;KAEf,oBAAoB,QAC9B,YAAgB;EAEd,SAAS,eAAe;;KAIhB,iBAAiB,QAC3B,YAAgB;EAEd,UAAU,eAAe,kBAAkB;EAC3C,UAAU,eAAe;EACzB,QAAQ,eAAe,kBAAkB;;KAIjC,kBAAkB,eAAe,kBAAkB;KAEnD,gBAAgB,qBAAqB,QAC/C,YAAgB,gBAAgB;EAE9B,cAAc,kBAAkB;EAChC,cAAc,kBAAkB;EAChC,YAAY;EACZ,YAAY,eAAe,kBAAkB;KAG/C;KAEU,eAAe,qBAAqB,QAC9C,YAAgB,eAAe;EAE7B,cAAc,kBAAkB;QAGjC,UAAU,eAAe,gBAAgB;KAGhC,YAAY,mBAAmB,yBAAyB,gBAEjE,eAAe,KAAK;KAGX,iBAAiB,eAAe,iBAAiB;KAEjD,mBAAmB,QAC7B,YAAgB;EAEd,UAAU,eAAe;EACzB,YAAY,eAAe,kBAAkB;EAC7C,aAAa,eAAe,kBAAkB;EAC9C,gBAAgB,eAAe,kBAAkB;EACjD,UAAU,eAAe,kBAAkB;EAC3C,QAAQ,eAAe,kBAAkB;EACzC,YAAY,eAAe,kBAAkB;EAC7C,YAAY,eAAe,kBAAkB;;KAIrC,SAAS,qBAAqB,QACxC,YAAgB,SAAS;EAEvB,QAAQ,YAAY;EACpB,aAAa;;;;UC5GA;;;;;EAKf;;EAEA;;EAEA;;;;;;;EAOA,UAAU;;;;;;;;;;wBAqoDU,wBACpB,wBACA,UAAS,kBACR,QAAQ"}
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/generate.ts"],"mappings":";;;;KAEY,QAAQ,SAAS,gBAAgB,KAAK,eAAe,gBAC/D;KAEU;KAGA,sBAAsB;KAEtB,cAAc,YAAgB;KAC9B,kBAAkB,YAAgB;KAClC,gBAAgB,YAAgB;KAChC,sBAAsB,YAAgB;KACtC,8BACV,YAAgB;KACN,YAAY,YAAgB;KAC5B,aAAa,YAAgB;KAC7B,uBAAuB,YAAgB;KACvC,eAAe,YAAgB;KAE/B,eAAe,QACzB,YAAgB;EAEd;EACA,QAAQ,eAAe;EACvB;EACA;EACA,aAAa,eAAe;EAC5B;EACA,QAAQ;EACR,cAAc;EACd;EACA;EACA,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,MAAM;EACN,iCAAiC;EACjC,gBAAgB;EAChB,eAAe;EACf,MAAM;EACN;EACA;EACA;;KAIQ,aAAa;UAER,0BAA0B;EACzC;EACA,OAAO;;KAGG,kBAAkB,QAC5B,YAAgB;EAEd,SAAS,eAAe;EACxB,WAAW,eAAe,kBAAkB;;UAI/B,4BAA4B,QAC3C,YAAgB;EAEd,SAAS,eAAe;EACxB,WAAW,eAAe,kBAAkB;EAC5C,UAAU,eAAe;;UAIZ,wBAAwB;EACvC;EACA;;KAGU,eAAe;KAEf,oBAAoB,QAC9B,YAAgB;EAEd,SAAS,eAAe;;KAIhB,iBAAiB,QAC3B,YAAgB;EAEd,UAAU,eAAe,kBAAkB;EAC3C,UAAU,eAAe;EACzB,QAAQ,eAAe,kBAAkB;;KAIjC,kBAAkB,eAAe,kBAAkB;KAEnD,gBAAgB,qBAAqB,QAC/C,YAAgB,gBAAgB;EAE9B,cAAc,kBAAkB;EAChC,cAAc,kBAAkB;EAChC,YAAY;EACZ,YAAY,eAAe,kBAAkB;KAG/C;KAEU,eAAe,qBAAqB,QAC9C,YAAgB,eAAe;EAE7B,cAAc,kBAAkB;QAGjC,UAAU,eAAe,gBAAgB;KAGhC,YAAY,mBAAmB,yBAAyB,gBAEjE,eAAe,KAAK;KAGX,iBAAiB,eAAe,iBAAiB;KAEjD,mBAAmB,QAC7B,YAAgB;EAEd,UAAU,eAAe;EACzB,YAAY,eAAe,kBAAkB;EAC7C,aAAa,eAAe,kBAAkB;EAC9C,gBAAgB,eAAe,kBAAkB;EACjD,UAAU,eAAe,kBAAkB;EAC3C,QAAQ,eAAe,kBAAkB;EACzC,YAAY,eAAe,kBAAkB;EAC7C,YAAY,eAAe,kBAAkB;;KAIrC,SAAS,qBAAqB,QACxC,YAAgB,SAAS;EAEvB,QAAQ,YAAY;EACpB,aAAa;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/generate.ts"],"mappings":";;;;KAEY,QAAQ,SAAS,gBAAgB,KAAK,eAAe,gBAC/D;KAEU;KAGA,sBAAsB;KAEtB,cAAc,YAAgB;KAC9B,kBAAkB,YAAgB;KAClC,gBAAgB,YAAgB;KAChC,sBAAsB,YAAgB;KACtC,8BACV,YAAgB;KACN,YAAY,YAAgB;KAC5B,aAAa,YAAgB;KAC7B,uBAAuB,YAAgB;KACvC,eAAe,YAAgB;KAE/B,eAAe,QACzB,YAAgB;EAEd;EACA,QAAQ,eAAe;EACvB;EACA;EACA,aAAa,eAAe;EAC5B;EACA,QAAQ;EACR,cAAc;EACd;EACA;EACA,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,MAAM;EACN,iCAAiC;EACjC,gBAAgB;EAChB,eAAe;EACf,MAAM;EACN;EACA;EACA;;KAIQ,aAAa;UAER,0BAA0B;EACzC;EACA,OAAO;;KAGG,kBAAkB,QAC5B,YAAgB;EAEd,SAAS,eAAe;EACxB,WAAW,eAAe,kBAAkB;;UAI/B,4BAA4B,QAC3C,YAAgB;EAEd,SAAS,eAAe;EACxB,WAAW,eAAe,kBAAkB;EAC5C,UAAU,eAAe;;UAIZ,wBAAwB;EACvC;EACA;;KAGU,eAAe;KAEf,oBAAoB,QAC9B,YAAgB;EAEd,SAAS,eAAe;;KAIhB,iBAAiB,QAC3B,YAAgB;EAEd,UAAU,eAAe,kBAAkB;EAC3C,UAAU,eAAe;EACzB,QAAQ,eAAe,kBAAkB;;KAIjC,kBAAkB,eAAe,kBAAkB;KAEnD,gBAAgB,qBAAqB,QAC/C,YAAgB,gBAAgB;EAE9B,cAAc,kBAAkB;EAChC,cAAc,kBAAkB;EAChC,YAAY;EACZ,YAAY,eAAe,kBAAkB;KAG/C;KAEU,eAAe,qBAAqB,QAC9C,YAAgB,eAAe;EAE7B,cAAc,kBAAkB;QAGjC,UAAU,eAAe,gBAAgB;KAGhC,YAAY,mBAAmB,yBAAyB,gBAEjE,eAAe,KAAK;KAGX,iBAAiB,eAAe,iBAAiB;KAEjD,mBAAmB,QAC7B,YAAgB;EAEd,UAAU,eAAe;EACzB,YAAY,eAAe,kBAAkB;EAC7C,aAAa,eAAe,kBAAkB;EAC9C,gBAAgB,eAAe,kBAAkB;EACjD,UAAU,eAAe,kBAAkB;EAC3C,QAAQ,eAAe,kBAAkB;EACzC,YAAY,eAAe,kBAAkB;EAC7C,YAAY,eAAe,kBAAkB;;KAIrC,SAAS,qBAAqB,QACxC,YAAgB,SAAS;EAEvB,QAAQ,YAAY;EACpB,aAAa;;;;UC5GA;;;;;EAKf;;EAEA;;EAEA;;;;;;;EAOA,UAAU;;;;;;;;;;wBAqoDU,wBACpB,wBACA,UAAS,kBACR,QAAQ"}
|