next-rest-framework
Version:
Next REST Framework - write type-safe, self-documenting REST APIs in Next.js
190 lines (188 loc) • 7.03 kB
JavaScript
;
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;