@pothos/plugin-zod
Version:
A Pothos plugin for adding argument validation
135 lines (134 loc) • 6.29 kB
JavaScript
function _define_property(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
}
else {
obj[key] = value;
}
return obj;
}
import './global-types.js';
import SchemaBuilder, { BasePlugin, mapInputFields, PothosSchemaError, PothosValidationError, resolveInputTypeConfig } from '@pothos/core';
import * as zod from 'zod';
import createZodSchema, { combine, createArrayValidator, isArrayValidator, refine } from './createZodSchema.js';
export * from './types.js';
const pluginName = "zod";
export class PothosZodPlugin extends BasePlugin {
onInputFieldConfig(fieldConfig) {
const fieldType = resolveInputTypeConfig(fieldConfig.type, this.buildCache);
const validationOptions = fieldConfig.pothosOptions.validate;
if (!validationOptions && fieldType.kind !== "InputObject") {
return fieldConfig;
}
const fieldName = fieldConfig.kind === "Arg" ? `${fieldConfig.parentType}.${fieldConfig.parentField}(${fieldConfig.name})` : `${fieldConfig.parentType}.${fieldConfig.name}`;
const validator = this.createValidator(validationOptions, fieldConfig.type, fieldName);
if (fieldConfig.kind === "Arg") {
return {
...fieldConfig,
extensions: {
...fieldConfig.extensions,
validator
}
};
}
this.inputFieldValidators.set(fieldConfig.parentType, {
...this.inputFieldValidators.get(fieldConfig.parentType),
[fieldConfig.name]: validator
});
return fieldConfig;
}
wrapResolve(resolver, fieldConfig) {
var _this_builder_options_zod;
// Only used to check if validation is required
const argMap = mapInputFields(fieldConfig.args, this.buildCache, (field) => {
var _field_extensions;
var _field_extensions_validator;
return (_field_extensions_validator = (_field_extensions = field.extensions) === null || _field_extensions === void 0 ? void 0 : _field_extensions.validator) !== null && _field_extensions_validator !== void 0 ? _field_extensions_validator : null;
}, this.mappingCache);
if (!argMap && !fieldConfig.pothosOptions.validate) {
return resolver;
}
const args = {};
for (const [argName, arg] of Object.entries(fieldConfig.args)) {
var _arg_extensions;
const validator = (_arg_extensions = arg.extensions) === null || _arg_extensions === void 0 ? void 0 : _arg_extensions.validator;
if (validator) {
args[argName] = validator;
}
}
let validator = zod.looseObject(args);
if (fieldConfig.pothosOptions.validate) {
validator = refine(validator, fieldConfig.pothosOptions.validate);
}
const validationError = (_this_builder_options_zod = this.builder.options.zod) === null || _this_builder_options_zod === void 0 ? void 0 : _this_builder_options_zod.validationError;
const validatorWithErrorHandling = validationError && async function validate(value, ctx, info) {
try {
const result = await validator.parseAsync(value);
return result;
}
catch (error) {
const errorOrMessage = validationError(error, value, ctx, info);
if (typeof errorOrMessage === "string") {
throw new PothosValidationError(errorOrMessage);
}
throw errorOrMessage;
}
};
return async (parent, rawArgs, context, info) => resolver(parent, await (validatorWithErrorHandling ? validatorWithErrorHandling(rawArgs, context, info) : validator.parseAsync(rawArgs)), context, info);
}
createValidator(optionsOrConstraint, type, fieldName) {
const options = Array.isArray(optionsOrConstraint) || typeof optionsOrConstraint === "function" ? {
refine: optionsOrConstraint
} : optionsOrConstraint;
if ((type === null || type === void 0 ? void 0 : type.kind) === "InputObject") {
const typeConfig = this.buildCache.getTypeConfig(type.ref, "InputObject");
let fieldValidator = refine(zod.lazy(() => {
var _this_inputFieldValidators_get;
return zod.looseObject((_this_inputFieldValidators_get = this.inputFieldValidators.get(typeConfig.name)) !== null && _this_inputFieldValidators_get !== void 0 ? _this_inputFieldValidators_get : {});
}), options);
if (typeConfig.pothosOptions.validate) {
fieldValidator = refine(fieldValidator, typeConfig.pothosOptions.validate);
}
return combine([
fieldValidator
], type.required);
}
if ((type === null || type === void 0 ? void 0 : type.kind) === "List") {
if (options && !isArrayValidator(options)) {
throw new PothosSchemaError(`Expected valid array validator for ${fieldName}`);
}
const items = this.createValidator(options === null || options === void 0 ? void 0 : options.items, type.type, fieldName);
if (options) {
return combine([
createArrayValidator(options, items)
], type.required);
}
return combine([
items.array()
], type.required);
}
if (!options) {
return zod.unknown();
}
return createZodSchema(options, !type || type.required);
}
constructor(...args) {
super(...args), _define_property(this, "inputFieldValidators", new Map()), _define_property(this, "mappingCache", new Map());
}
}
SchemaBuilder.registerPlugin(pluginName, PothosZodPlugin, {
v3(options) {
return {
validationOptions: undefined,
zod: options.validationOptions
};
}
});
export default pluginName;
export { default as createZodSchema } from './createZodSchema.js';
//# sourceMappingURL=index.js.map