UNPKG

moleculer-zod-validator

Version:

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

99 lines (98 loc) 4.46 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ZodValidator = void 0; const zod_1 = require("zod"); const moleculer_1 = require("moleculer"); // Why does this work when an import doesn't??? const FastestValidator = require("fastest-validator"); const helpers_1 = require("./helpers"); class ZodValidator extends moleculer_1.Validators.Base { constructor() { super(); this.fvFallback = new FastestValidator(); } compile(schema) { // There's an issue in Moleculer 0.14.x where the internal services like // $node.services use fastest-validator configuration and can't be changed. // Since the schema used for this validator is an object with all functions // (vs an object with strings/numbers/booleans) we can check for the existence // of the Zod _def property // Not super elegant, but hey, if it keeps Moleculer from crashing... // ¯\_(ツ)_/¯ if ( // _def exists on all ZodType objects and should be a good litmus test Object.keys(schema).filter((key) => schema[key].hasOwnProperty("_def")) .length > 0) { return (params) => this.validate(params, schema); } else { // This is based on Moleculer's fastest.js validator // TODO: Why does this crash with cloneDeep? // return this.fvFallback.compile(_.cloneDeep(schema)); return this.fvFallback.compile(structuredClone(schema)); } } validate(params, schemaWithOptions) { // Since we have to worry about the fastest-validator fallback, check the // schema type and go back to the fallback depending on that. Same check // as in compile(). if (Object.keys(schemaWithOptions).filter((key) => schemaWithOptions[key].hasOwnProperty("_def")).length > 0) { try { const { $$$options: opts, ...schema } = schemaWithOptions; let compiled; if (opts.strip) { compiled = zod_1.z.object(schema).strip(); } else if (opts.strict) { compiled = zod_1.z.object(schema).strict(); } else if (opts.passthrough) { compiled = zod_1.z.object(schema).passthrough(); } else { compiled = zod_1.z.object(schema); } if (opts.partial) { compiled = compiled.partial(); } else if (opts.deepPartial) { compiled = compiled.deepPartial(); } if (opts.catchall) { compiled = compiled.catchall(opts.catchall); } // Functions should be considered truthy if (opts.superRefine) { compiled = compiled.superRefine(opts.superRefine); } if (opts.refine) { if (typeof opts.refine === "function") { compiled = compiled.refine(opts.refine); } else { compiled = compiled.refine(opts.refine.validator, opts.refine.params); } } const results = compiled.parse(params); // params is passed by reference, meaning that we can apply transformations // to what gets passed to the validator from here. However, simply setting // it to a new value will just change the pointer to the object in function // scope, so we need to actually mutate the original ourselves. (0, helpers_1.mutateObject)(params, results, false); return true; } catch (err) { if (err instanceof zod_1.z.ZodError) throw new moleculer_1.Errors.ValidationError("Parameter validation error", "VALIDATION_ERROR", err.issues); throw err; } } else { const res = this.fvFallback.validate(params, structuredClone(schemaWithOptions)); if (res !== true) throw new moleculer_1.Errors.ValidationError("Parameters validation error!", "VALIDATION_ERROR", res); return true; } } } exports.ZodValidator = ZodValidator;