turtle-express
Version:
`turtle-express` is kinda a framework or a library based on `express.js` with an opinionated express router with type safety and schema validation with zod. Also many [more features](https://github.com/mm-ninja-turtles/turtle-express/discussions/7) planni
163 lines • 5.57 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createOpenApiJsonElement = exports.zodToOpenApiJson = void 0;
const zod_1 = require("zod");
const lodash_es_1 = require("lodash-es");
/**
* Function to convert each ZodType schema to OpenAPI Request, Parameter, Response schemas.
*/
function zodToOpenApiJson(schema) {
const { type } = schema._openApi;
const openApiJsonElement = createOpenApiJsonElement(schema);
if (type === 'Response') {
const mediaType = schema._openApi.mediaType ?? 'application/json';
const response = {
description: openApiJsonElement.description ?? '',
content: {
[mediaType]: {
schema: openApiJsonElement,
},
},
};
return response;
}
if (type === 'RequestQuery' || type === 'RequestParam') {
const parameters = [];
Object.keys(openApiJsonElement?.properties ?? {}).forEach((key) => {
parameters.push({
name: key,
in: type === 'RequestQuery' ? 'query' : 'path',
schema: openApiJsonElement?.properties?.[key],
});
});
return parameters;
}
if (type === 'RequestBody') {
const mediaType = schema._openApi.mediaType ?? 'application/json';
const requestBody = {
description: openApiJsonElement.description ?? '',
content: {
[mediaType]: {
schema: openApiJsonElement,
},
},
};
return requestBody;
}
return openApiJsonElement;
}
exports.zodToOpenApiJson = zodToOpenApiJson;
/**
* @Credit https://github.com/kbkk/abitia/blob/master/packages/zod-dto/src/OpenApi/zodTypeToOpenApi.ts
* The following function code is inspired and reused some from the above package.
*
* Return the OpenAPI schema for a Zod type.
*/
function createOpenApiJsonElement(schema) {
const schemaDef = schema._def;
function createOpenApi(extendSchema) {
const title = schema?._openApi?.title ?? '';
const type = schema?._openApi?.type ?? '';
const transformedTitle = (0, lodash_es_1.chain)(`${title} ${type}`)
.camelCase()
.upperFirst()
.value();
return {
required: true,
...extendSchema,
operationId: transformedTitle ?? '',
title: transformedTitle ?? '',
description: schemaDef?.description ?? '',
};
}
switch (schema.constructor.name) {
case zod_1.z.ZodObject.name: {
const shape = schemaDef.shape();
const shapeKeys = Object.keys(shape);
const properties = {};
shapeKeys.forEach((key) => {
const property = createOpenApiJsonElement(shape[key]);
properties[key] = property;
});
return createOpenApi({
type: 'object',
properties,
});
}
case zod_1.z.ZodOptional.name: {
return createOpenApi({
...createOpenApiJsonElement(schemaDef.innerType),
required: false,
});
}
case zod_1.z.ZodNullable.name: {
return createOpenApi({
...createOpenApiJsonElement(schemaDef.innerType),
nullable: true,
});
}
case zod_1.z.ZodTransformer.name: {
return createOpenApi({
...createOpenApiJsonElement(schemaDef.schema),
});
}
case zod_1.z.ZodEnum.name: {
const enumValues = schemaDef.values;
return createOpenApi({
type: 'string',
enum: enumValues,
});
}
case zod_1.z.ZodLiteral.name: {
return createOpenApi({
type: 'string',
enum: [schemaDef.value],
});
}
case zod_1.z.ZodUnion.name: {
const options = schemaDef.options;
return createOpenApi({
oneOf: options.map((item) => createOpenApiJsonElement(item)),
});
}
case zod_1.z.ZodTuple.name: {
const items = schemaDef.items;
return createOpenApi({
type: 'array',
items: {
oneOf: items.map((item) => createOpenApiJsonElement(item)),
},
minItems: items.length,
maxItems: items.length,
});
}
case zod_1.z.ZodArray.name: {
const type = schemaDef.type;
return createOpenApi({
type: 'array',
items: type ? createOpenApiJsonElement(type) : {},
});
}
case zod_1.z.ZodBigInt.name: {
return createOpenApi({
type: 'integer',
format: 'int64',
});
}
case zod_1.z.ZodString.name: {
return createOpenApi({ type: 'string' });
}
case zod_1.z.ZodNumber.name: {
return createOpenApi({ type: 'number' });
}
case zod_1.z.ZodBoolean.name: {
return createOpenApi({ type: 'boolean' });
}
case zod_1.z.ZodDefault.name:
default: {
return createOpenApi({ type: 'string' });
}
}
}
exports.createOpenApiJsonElement = createOpenApiJsonElement;
//# sourceMappingURL=zod-to-open-api-json.js.map