mirror of
https://github.com/hanzoai/trpc-openapi.git
synced 2026-10-30 18:18:55 +00:00
206 lines
10 KiB
JavaScript
206 lines
10 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.getResponsesObject = exports.errorResponseFromMessage = exports.errorResponseFromStatusCode = exports.errorResponseObject = exports.hasInputs = exports.getRequestBodyObject = exports.getParameterObjects = void 0;
|
|
const server_1 = require("@trpc/server");
|
|
const zod_1 = require("zod");
|
|
const adapters_1 = require("../adapters");
|
|
const utils_1 = require("../utils");
|
|
const paths_1 = require("./paths");
|
|
const getParameterObjects = (schema, required, pathParameters, headersSchema, inType) => {
|
|
const shape = schema.shape;
|
|
const shapeKeys = Object.keys(shape);
|
|
for (const pathParameter of pathParameters) {
|
|
if (!shapeKeys.includes(pathParameter)) {
|
|
throw new server_1.TRPCError({
|
|
message: `Input parser expects key from path: "${pathParameter}"`,
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
});
|
|
}
|
|
}
|
|
// @ts-expect-error fix later
|
|
const { path, query } = shapeKeys
|
|
.filter((shapeKey) => {
|
|
const isPathParameter = pathParameters.includes(shapeKey);
|
|
if (inType === 'path') {
|
|
return isPathParameter;
|
|
}
|
|
else if (inType === 'query') {
|
|
return !isPathParameter;
|
|
}
|
|
return true;
|
|
})
|
|
.map((shapeKey) => {
|
|
let shapeSchema = shape[shapeKey];
|
|
const isShapeRequired = !shapeSchema.safeParse(undefined).success;
|
|
const isPathParameter = pathParameters.includes(shapeKey);
|
|
if (!(0, utils_1.instanceofZodTypeLikeString)(shapeSchema)) {
|
|
if (utils_1.zodSupportsCoerce) {
|
|
if (!(0, utils_1.instanceofZodTypeCoercible)(shapeSchema)) {
|
|
throw new server_1.TRPCError({
|
|
message: `Input parser key: "${shapeKey}" must be ZodString, ZodNumber, ZodBoolean, ZodBigInt or ZodDate`,
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
});
|
|
}
|
|
}
|
|
else {
|
|
throw new server_1.TRPCError({
|
|
message: `Input parser key: "${shapeKey}" must be ZodString`,
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
});
|
|
}
|
|
}
|
|
if ((0, utils_1.instanceofZodTypeOptional)(shapeSchema)) {
|
|
if (isPathParameter) {
|
|
throw new server_1.TRPCError({
|
|
message: `Path parameter: "${shapeKey}" must not be optional`,
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
});
|
|
}
|
|
shapeSchema = shapeSchema.unwrap();
|
|
}
|
|
return {
|
|
name: shapeKey,
|
|
paramType: isPathParameter ? 'path' : 'query',
|
|
required: isPathParameter || isShapeRequired,
|
|
schema: shapeSchema,
|
|
};
|
|
})
|
|
.reduce(({ path, query }, { name, paramType, schema, required }) =>
|
|
// @ts-expect-error fix later
|
|
paramType === 'path'
|
|
? {
|
|
path: Object.assign(Object.assign({}, path), { [name]: required ? schema : schema.optional() }),
|
|
query,
|
|
}
|
|
: {
|
|
path,
|
|
query: Object.assign(Object.assign({}, query), { [name]: required ? schema : schema.optional() }),
|
|
}, { path: {}, query: {} });
|
|
let res = {};
|
|
if (headersSchema) {
|
|
res.header = headersSchema;
|
|
}
|
|
res = Object.assign(Object.assign({}, res), { path: zod_1.z.object(path), query: zod_1.z.object(query) });
|
|
return res;
|
|
};
|
|
exports.getParameterObjects = getParameterObjects;
|
|
const getRequestBodyObject = (schema, required, pathParameters, contentTypes) => {
|
|
const mask = {};
|
|
pathParameters.forEach((pathParameter) => {
|
|
mask[pathParameter] = true;
|
|
});
|
|
const o = schema.meta();
|
|
let dedupedSchema;
|
|
try {
|
|
dedupedSchema = schema.omit(mask).meta(Object.assign(Object.assign(Object.assign({}, ((o === null || o === void 0 ? void 0 : o.title) ? { title: o === null || o === void 0 ? void 0 : o.title } : {})), ((o === null || o === void 0 ? void 0 : o.description) ? { description: o === null || o === void 0 ? void 0 : o.description } : {})), ((o === null || o === void 0 ? void 0 : o.examples) ? { examples: o === null || o === void 0 ? void 0 : o.examples } : {})));
|
|
}
|
|
catch (_a) {
|
|
// Zod 4: .omit() throws on object schemas containing refinements; build body schema from shape
|
|
const shape = schema.shape;
|
|
const bodyShape = {};
|
|
for (const key of Object.keys(shape)) {
|
|
if (!mask[key] && shape[key])
|
|
bodyShape[key] = shape[key];
|
|
}
|
|
dedupedSchema = zod_1.z.object(bodyShape).meta(Object.assign(Object.assign(Object.assign({}, ((o === null || o === void 0 ? void 0 : o.title) ? { title: o === null || o === void 0 ? void 0 : o.title } : {})), ((o === null || o === void 0 ? void 0 : o.description) ? { description: o === null || o === void 0 ? void 0 : o.description } : {})), ((o === null || o === void 0 ? void 0 : o.examples) ? { examples: o === null || o === void 0 ? void 0 : o.examples } : {})));
|
|
}
|
|
if (pathParameters.length > 0 && Object.keys(dedupedSchema.shape).length === 0) {
|
|
return undefined;
|
|
}
|
|
const content = {};
|
|
for (const contentType of contentTypes) {
|
|
content[contentType] = {
|
|
schema: dedupedSchema,
|
|
};
|
|
}
|
|
return {
|
|
required,
|
|
content,
|
|
};
|
|
};
|
|
exports.getRequestBodyObject = getRequestBodyObject;
|
|
const hasInputs = (schema) => (0, utils_1.instanceofZodType)(schema) && !(0, utils_1.instanceofZodTypeLikeVoid)((0, utils_1.unwrapZodType)(schema, true));
|
|
exports.hasInputs = hasInputs;
|
|
const errorResponseObjectByCode = {};
|
|
const errorResponseObject = (code = 'INTERNAL_SERVER_ERROR', message, issues) => {
|
|
var _a;
|
|
if (!errorResponseObjectByCode[code]) {
|
|
errorResponseObjectByCode[code] = {
|
|
description: message !== null && message !== void 0 ? message : 'An error response',
|
|
content: {
|
|
'application/json': {
|
|
schema: zod_1.z
|
|
.object({
|
|
message: zod_1.z.string().meta({
|
|
description: 'The error message',
|
|
example: message !== null && message !== void 0 ? message : 'Internal server error',
|
|
}),
|
|
code: zod_1.z.string().meta({
|
|
description: 'The error code',
|
|
example: code !== null && code !== void 0 ? code : 'INTERNAL_SERVER_ERROR',
|
|
}),
|
|
issues: zod_1.z
|
|
.array(zod_1.z.object({ message: zod_1.z.string() }))
|
|
.optional()
|
|
.meta({
|
|
description: 'An array of issues that were responsible for the error',
|
|
example: issues !== null && issues !== void 0 ? issues : [],
|
|
}),
|
|
})
|
|
.meta({
|
|
title: `${message !== null && message !== void 0 ? message : 'Internal server'} error (${(_a = adapters_1.TRPC_ERROR_CODE_HTTP_STATUS[code]) !== null && _a !== void 0 ? _a : 500})`,
|
|
description: 'The error information',
|
|
example: {
|
|
code: code !== null && code !== void 0 ? code : 'INTERNAL_SERVER_ERROR',
|
|
message: message !== null && message !== void 0 ? message : 'Internal server error',
|
|
issues: issues !== null && issues !== void 0 ? issues : [],
|
|
},
|
|
id: `error.${code}`,
|
|
}),
|
|
},
|
|
},
|
|
};
|
|
}
|
|
return errorResponseObjectByCode[code];
|
|
};
|
|
exports.errorResponseObject = errorResponseObject;
|
|
const errorResponseFromStatusCode = (status) => {
|
|
const code = adapters_1.HTTP_STATUS_TRPC_ERROR_CODE[status];
|
|
const message = code && adapters_1.TRPC_ERROR_CODE_MESSAGE[code];
|
|
return (0, exports.errorResponseObject)(code, message !== null && message !== void 0 ? message : 'Unknown error');
|
|
};
|
|
exports.errorResponseFromStatusCode = errorResponseFromStatusCode;
|
|
const errorResponseFromMessage = (status, message) => (0, exports.errorResponseObject)(adapters_1.HTTP_STATUS_TRPC_ERROR_CODE[status], message);
|
|
exports.errorResponseFromMessage = errorResponseFromMessage;
|
|
const getResponsesObject = (schema, httpMethod, headers, isProtected, hasInputs, successDescription, errorResponses) => (Object.assign({ 200: {
|
|
description: successDescription !== null && successDescription !== void 0 ? successDescription : 'Successful response',
|
|
headers: headers,
|
|
content: {
|
|
'application/json': {
|
|
schema: (0, utils_1.instanceofZodTypeKind)(schema, 'void')
|
|
? {}
|
|
: (0, utils_1.instanceofZodTypeKind)(schema, 'never') || (0, utils_1.instanceofZodTypeKind)(schema, 'undefined')
|
|
? { not: {} }
|
|
: schema,
|
|
},
|
|
},
|
|
} }, (errorResponses !== undefined
|
|
? Object.fromEntries(Array.isArray(errorResponses)
|
|
? errorResponses.map((x) => [x, (0, exports.errorResponseFromStatusCode)(x)])
|
|
: Object.entries(errorResponses).map(([k, v]) => [
|
|
k,
|
|
(0, exports.errorResponseFromMessage)(Number(k), v),
|
|
]))
|
|
: Object.assign(Object.assign(Object.assign({}, (isProtected
|
|
? {
|
|
401: (0, exports.errorResponseObject)('UNAUTHORIZED', 'Authorization not provided'),
|
|
403: (0, exports.errorResponseObject)('FORBIDDEN', 'Insufficient access'),
|
|
}
|
|
: {})), (hasInputs
|
|
? Object.assign({ 400: (0, exports.errorResponseObject)('BAD_REQUEST', 'Invalid input data') }, (httpMethod !== paths_1.HttpMethods.POST
|
|
? {
|
|
404: (0, exports.errorResponseObject)('NOT_FOUND', 'Not found'),
|
|
}
|
|
: {})) : {})), { 500: (0, exports.errorResponseObject)('INTERNAL_SERVER_ERROR', 'Internal server error') }))));
|
|
exports.getResponsesObject = getResponsesObject;
|
|
//# sourceMappingURL=schema.js.map
|