UNPKG

moleculer-zod-validator

Version:

A validator for the Moleculer microservice framework to allow the use of Zod.

147 lines (146 loc) 5.87 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ZodParams = void 0; const zod_1 = require("zod"); /** * An adapter for a standard {@link https://github.com/colinhacks/zod#objects ZodObject}, * which can be easier to work with in Moleculer than Zod on its own. */ class ZodParams { /** * Creates a new ZodParams adapter, which can be used to more easily provide typing * information to Moleculer services and calls. * @param {ZodRawShape} schema - The schema used in * {@link https://github.com/colinhacks/zod#objects z.object()}. * @param {ZodParamsOptionsType} options - This exposes several methods available * on the ZodObject type, * {@link https://github.com/colinhacks/zod#table-of-contents all of which can be referenced under the Objects section in the Zod documentation}. * @param {any} returnType - The return type of the action in question. This does * nothing at runtime and is used purely for storing a type on the object that can * then be referenced later on. This can be done like so: * * @example <caption>The return type will be `Promise<string>`</caption> * new ZodParams({ property: z.string() }, undefined, {} as Promise<string>) * * @todo * **Note**: {@link https://github.com/colinhacks/zod/issues/1949 There's currently a known issue in Zod where catchall type inferences don't work correctly.} * Until this upstream issue is fixed, catchall type inferences on ZodParams will * be disabled as not to break existing projects. This will not impact the runtime * behavior of catchall in the validator, just the type inference. * * If you wish to emulate the type inference, you can do so by using a TS union * when using broker.call or ctx.call. * * @example * broker.call< * typeof zodParamObject.return, * typeof zodParamObject.call & {[index: string]: string} * >({ ... }) * */ constructor(schema, options, returnType) { this._rawSchema = schema; const opts = ZodParamsOptions.parse(options || {}); // This is an effort to hopefully improve type inference // As for the @ts-expect-errors ahead, while trying to get this code to work as // you'd expect, I had to use some of my own types that were supposed to be // interoperable with the original Zod types. While the interop is supposed to // be one-way, TypeScript is giving me errors assuming it's supposed to go both // ways. As much as I'd like to give TS as much power over things as I can, // here it's just wrong. // @ts-expect-error this._validator = zod_1.z.object(this._rawSchema); if (opts.strip) { // @ts-expect-error this._validator = this._validator.strip(); } else if (opts.strict) { // @ts-expect-error this._validator = this._validator.strict(); } else if (opts.passthrough) { // @ts-expect-error this._validator = this._validator.passthrough(); } if (opts.partial) { // @ts-expect-error this._validator = this._validator.partial(); } else if (opts.deepPartial) { // @ts-expect-error this._validator = this._validator.deepPartial(); } if (opts.catchall) { this._validator = this._validator.catchall(opts.catchall); } // Functions should be considered truthy if (opts.superRefine) { // @ts-expect-error this._validator = this._validator.superRefine(opts.superRefine); } if (opts.refine) { if (typeof opts.refine === "function") { // @ts-expect-error this._validator = this._validator.refine(opts.refine); } else { // @ts-expect-error this._validator = this._validator.refine(opts.refine.validator, opts.refine.params); } } this._rawSchemaWithOptions = Object.assign({}, schema, { $$$options: opts }); } /** * Returns the raw Zod schema provided in the constructor. This should be passed * to the `params` object in the action definition. * * @example * broker.createService({ * name: "example", * actions: { * exampleAction: { * params: zodParamObject.schema, * handler(ctx: Context<typeof zodParamObject.context>) { ... } * } * } * }); */ get schema() { return this._rawSchemaWithOptions; } /** * Returns the compiled ZodObject validator. */ get validator() { return this._validator; } } exports.ZodParams = ZodParams; const ZodParamsOptions = zod_1.z .object({ partial: zod_1.z.boolean().default(false), deepPartial: zod_1.z.boolean().default(false), strict: zod_1.z.boolean().default(false), catchall: zod_1.z.any(), passthrough: zod_1.z.boolean(), strip: zod_1.z.boolean().default(false), refine: zod_1.z.union([ // Not sure how best to represent the validator function params zod_1.z.function().args(zod_1.z.any()), zod_1.z.object({ validator: zod_1.z.function().args(zod_1.z.any()), params: zod_1.z .object({ message: zod_1.z.string(), path: zod_1.z.array(zod_1.z.union([zod_1.z.string(), zod_1.z.number()])), params: zod_1.z.object({}).passthrough() }) .partial() .optional() }) ]), superRefine: zod_1.z.function().args(zod_1.z.any(), zod_1.z.any()) }) .partial();