UNPKG

next-rest-framework

Version:

Next REST Framework - write type-safe, self-documenting REST APIs in Next.js

190 lines (188 loc) 7.03 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getSchemaKeys = exports.getJsonSchema = exports.validateSchema = exports.convertZodSchema = exports.isZodSchema = void 0; const chalk_1 = __importDefault(require("chalk")); const isZodSchema = (schema) => !!schema && typeof schema === 'object' && '_def' in schema; exports.isZodSchema = isZodSchema; const zodSchemaValidator = ({ schema, obj }) => { const data = schema.safeParse(obj); const errors = !data.success ? data.error.issues.map(({ message }) => message) : null; return { valid: data.success, errors }; }; const zodTypeGuards = { string: (schema) => schema._def.typeName === 'ZodString', symbol: (schema) => schema._def.typeName === 'ZodSymbol', date: (schema) => schema._def.typeName === 'ZodDate', number: (schema) => schema._def.typeName === 'ZodNumber', bigint: (schema) => schema._def.typeName === 'ZodBigInt', boolean: (schema) => schema._def.typeName === 'ZodBoolean', undefined: (schema) => schema._def.typeName === 'ZodUndefined', null: (schema) => schema._def.typeName === 'ZodNull', void: (schema) => schema._def.typeName === 'ZodVoid', nan: (schema) => schema._def.typeName === 'ZodNaN', never: (schema) => schema._def.typeName === 'ZodNever', any: (schema) => schema._def.typeName === 'ZodAny', unknown: (schema) => schema._def.typeName === 'ZodUnknown', literal: (schema) => schema._def.typeName === 'ZodLiteral', enum: (schema) => schema._def.typeName === 'ZodEnum', nativeEnum: (schema) => schema._def.typeName === 'ZodNativeEnum', optional: (schema) => schema._def.typeName === 'ZodOptional', nullable: (schema) => schema._def.typeName === 'ZodNullable', array: (schema) => schema._def.typeName === 'ZodArray', object: (schema) => schema._def.typeName === 'ZodObject', union: (schema) => schema._def.typeName === 'ZodUnion', discriminatedUnion: (schema) => schema._def.typeName === 'ZodDiscriminatedUnion', intersection: (schema) => schema._def.typeName === 'ZodIntersection', tuple: (schema) => schema._def.typeName === 'ZodTuple', record: (schema) => schema._def.typeName === 'ZodRecord', map: (schema) => schema._def.typeName === 'ZodMap', set: (schema) => schema._def.typeName === 'ZodSet' }; const convertZodSchema = (schema) => { if (zodTypeGuards.string(schema) || zodTypeGuards.symbol(schema)) { return { type: 'string' }; } if (zodTypeGuards.date(schema)) { return { type: 'string', format: 'date-time' }; } if (zodTypeGuards.number(schema) || zodTypeGuards.bigint(schema)) { return { type: 'number' }; } if (zodTypeGuards.boolean(schema)) { return { type: 'boolean' }; } if (zodTypeGuards.undefined(schema) || zodTypeGuards.null(schema) || zodTypeGuards.void(schema) || zodTypeGuards.nan(schema) || zodTypeGuards.never(schema)) { return { type: 'null' }; } if (zodTypeGuards.any(schema) || zodTypeGuards.unknown(schema)) { return {}; } if (zodTypeGuards.literal(schema)) { return { type: 'string', enum: [schema._def.value] }; } if (zodTypeGuards.enum(schema)) { return { enum: schema._def.values }; } if (zodTypeGuards.nativeEnum(schema)) { return { enum: Object.values(schema._def.values) }; } if (zodTypeGuards.optional(schema) || zodTypeGuards.nullable(schema)) { return { type: [(0, exports.convertZodSchema)(schema._def.innerType).type, 'null'] }; } if (zodTypeGuards.object(schema)) { const jsonSchema = { type: 'object', properties: Object.entries(schema._def.shape()).reduce((properties, [key, val]) => ({ ...properties, [key]: (0, exports.convertZodSchema)(val) }), {}) }; const hasAdditionalProperties = schema._def.catchall._def.typeName === 'ZodNever'; if (!hasAdditionalProperties) { jsonSchema.additionalProperties = (0, exports.convertZodSchema)(schema._def.catchall); } return jsonSchema; } if (zodTypeGuards.array(schema)) { return { type: 'array', items: (0, exports.convertZodSchema)(schema._def.type) }; } if (zodTypeGuards.tuple(schema)) { return { type: 'array', items: schema._def.items.map((val) => (0, exports.convertZodSchema)(val)) }; } if (zodTypeGuards.union(schema)) { return { anyOf: schema._def.options.map((option) => (0, exports.convertZodSchema)(option)) }; } if (zodTypeGuards.discriminatedUnion(schema)) { return { oneOf: schema._def.options.map((option) => (0, exports.convertZodSchema)(option)) }; } if (zodTypeGuards.record(schema) || zodTypeGuards.map(schema)) { return { type: 'object', additionalProperties: (0, exports.convertZodSchema)(schema._def.valueType) }; } if (zodTypeGuards.set(schema)) { return { type: 'array', items: (0, exports.convertZodSchema)(schema._def.valueType), uniqueItems: true }; } if (zodTypeGuards.intersection(schema)) { return { allOf: [ (0, exports.convertZodSchema)(schema._def.left), (0, exports.convertZodSchema)(schema._def.right) ] }; } if (process.env.NODE_ENV !== 'production' && 'typeName' in schema._def) { console.warn(chalk_1.default.yellowBright(`Warning: Next REST Framework detected an unsupported schema type for schema: ${schema._def.typeName} If you think this schema type should be supported, please open an issue at: https://github.com/blomqma/next-rest-framework/issues`)); } return {}; }; exports.convertZodSchema = convertZodSchema; const validateSchema = async ({ schema, obj }) => { if ((0, exports.isZodSchema)(schema)) { return zodSchemaValidator({ schema, obj }); } throw Error('Invalid schema.'); }; exports.validateSchema = validateSchema; const getJsonSchema = ({ schema }) => { if ((0, exports.isZodSchema)(schema)) { return (0, exports.convertZodSchema)(schema); } throw Error('Invalid schema.'); }; exports.getJsonSchema = getJsonSchema; const getSchemaKeys = ({ schema }) => { if ((0, exports.isZodSchema)(schema)) { return Object.keys(schema._def.shape()); } throw Error('Invalid schema.'); }; exports.getSchemaKeys = getSchemaKeys;