@giraphql/plugin-validation
Version:
A GiraphQL plugin for adding argument validation
102 lines (101 loc) • 4.9 kB
JavaScript
import './global-types.js';
import * as zod from 'zod';
import SchemaBuilder, { BasePlugin, mapInputFields, resolveInputTypeConfig, } from '@giraphql/core';
import createZodSchema, { combine, createArrayValidator, isArrayValidator, refine, } from './createZodSchema.js';
export * from './types.js';
const pluginName = "validation";
export class GiraphQLValidationPlugin extends BasePlugin {
constructor() {
super(...arguments);
this.inputFieldValidators = new Map();
this.inputTypeValidators = new Map();
}
onInputFieldConfig(fieldConfig) {
const fieldType = resolveInputTypeConfig(fieldConfig.type, this.buildCache);
const validationOptions = fieldConfig.giraphqlOptions.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 === "InputObject") {
this.inputFieldValidators.set(fieldConfig.parentType, {
...this.inputFieldValidators.get(fieldConfig.parentType),
[fieldConfig.name]: validator,
});
}
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) {
// Only used to check if validation is required
const argMap = mapInputFields(fieldConfig.args, this.buildCache, (field) => { var _a, _b; return (_b = (_a = field.extensions) === null || _a === void 0 ? void 0 : _a.validator) !== null && _b !== void 0 ? _b : null; });
if (!argMap && !fieldConfig.giraphqlOptions.validate) {
return resolver;
}
const args = {};
Object.keys(fieldConfig.args).forEach((argName) => {
var _a;
const validator = (_a = fieldConfig.args[argName].extensions) === null || _a === void 0 ? void 0 : _a.validator;
if (validator) {
args[argName] = validator;
}
});
let validator = zod.object(args).passthrough();
if (fieldConfig.giraphqlOptions.validate) {
validator = refine(validator, {
refine: fieldConfig.giraphqlOptions.validate,
});
}
return async (parent, rawArgs, context, info) => resolver(parent, (await 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 _a; return zod.object((_a = this.inputFieldValidators.get(typeConfig.name)) !== null && _a !== void 0 ? _a : {}).passthrough(); }), options);
if (typeConfig.giraphqlOptions.validate) {
fieldValidator = refine(fieldValidator, {
refine: typeConfig.giraphqlOptions.validate,
});
}
return combine([fieldValidator], type.required);
}
if ((type === null || type === void 0 ? void 0 : type.kind) === "List") {
if (options && !isArrayValidator(options)) {
throw new Error(`Expected valid array validator for ${fieldName}`);
}
const items = (options === null || options === void 0 ? void 0 : options.items)
? this.createValidator(options.items, type.type, fieldName)
: zod.unknown();
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);
}
}
SchemaBuilder.registerPlugin(pluginName, GiraphQLValidationPlugin);
export default pluginName;
export { default as createZodSchema } from './createZodSchema.js';
//# sourceMappingURL=index.js.map