UNPKG

@croz/nrich-form-configuration-core

Version:

Contains core utilities related to the nrich-form-configuration module

302 lines (295 loc) 11 kB
import { __async, __objRest, __spreadProps, __spreadValues, __toESM, require_uniqBy } from "../chunk-IX4UG67P.mjs"; // src/zod/store/form-configuration-store.ts import { create } from "zustand"; var useZodFormConfigurationStore = create((set) => ({ zodFormConfigurations: [], formConfigurationLoaded: false, set: (zodFormConfigurations) => set((state) => __spreadProps(__spreadValues({}, state), { zodFormConfigurations })), add: (zodFormConfigurations) => set((state) => ({ zodFormConfigurations: [...state.zodFormConfigurations, zodFormConfigurations] })), remove: (zodFormConfigurations) => set((state) => ({ zodFormConfigurations: state.zodFormConfigurations.filter((c) => c !== zodFormConfigurations) })), setFormConfigurationLoaded: (formConfigurationLoaded) => set({ formConfigurationLoaded }) })); // src/zod/hook/use-form-configuration.ts var useZodFormConfigurationState = () => { const formZodConfigurations = useZodFormConfigurationStore((state) => state.zodFormConfigurations); const formConfigurationLoaded = useZodFormConfigurationStore((state) => state.formConfigurationLoaded); const set = useZodFormConfigurationStore((state) => state.set); const add = useZodFormConfigurationStore((state) => state.add); const remove = useZodFormConfigurationStore((state) => state.remove); const setFormConfigurationLoaded = useZodFormConfigurationStore((state) => state.setFormConfigurationLoaded); return { formZodConfigurations, formConfigurationLoaded, set, add, remove, setFormConfigurationLoaded }; }; var useZodFormConfiguration = (formId) => { const { formZodConfigurations } = useZodFormConfigurationState(); const searchedFormConfiguration = formZodConfigurations.find((formZodConfiguration) => formZodConfiguration.formId === formId); if (!searchedFormConfiguration) { return void 0; } return searchedFormConfiguration.zodSchema; }; // src/zod/component/FormConfigurationZodProvider.tsx import React, { useEffect } from "react"; // src/zod/loader/fetch-form-configurations.ts var import_uniqBy = __toESM(require_uniqBy()); // src/zod/converter/FormConfigurationValidationZodConverter.ts import { z } from "zod"; var _FormConfigurationValidationZodConverter = class { constructor(additionalConverters = []) { this.additionalConverters = additionalConverters; } /** * Converts {@link FormConfiguration} to Zod's schema using builtin and provided converters. * @param formConfig Form configuration to convert */ convertFormConfigurationToZodSchema(formConfig) { const shape = {}; formConfig.constrainedPropertyConfigurationList.forEach( (property) => { let fieldSchema = _FormConfigurationValidationZodConverter.getBaseSchema(property); let isRequired = false; let lastRequiredValidator; property.validatorList.forEach( (validator) => { if (["NotNull", "NotBlank", "NotEmpty"].includes(validator.name)) { isRequired = true; lastRequiredValidator = validator; } fieldSchema = this.applyConverter(validator, fieldSchema); } ); if (!isRequired) { fieldSchema = fieldSchema.nullish(); } else { fieldSchema = fieldSchema.nullable().or(z.undefined()).refine( (val) => val != null, { message: lastRequiredValidator.errorMessage } ); } _FormConfigurationValidationZodConverter.setNestedField(shape, property.path.split("."), fieldSchema); } ); return _FormConfigurationValidationZodConverter.buildZodObject(shape); } /** * Determines the base Zod schema for a constrained property based on * its declared JavaScript type. */ static getBaseSchema(property) { switch (property.javascriptType.toLowerCase()) { case "string": return z.string(); case "number": return z.number(); case "boolean": return z.boolean(); case "object": return z.record(z.string(), z.any()); case "array": return z.array(z.any()); case "date": return z.date(); default: return z.unknown(); } } /** * Assigns a Zod schema to a nested path inside a JS object that represents the shape of the final Zod object. */ static setNestedField(shape, path, schema) { let current = shape; for (let i = 0; i < path.length - 1; i += 1) { const key = path[i]; if (!(key in current)) { current[key] = {}; } current = current[key]; } current[path[path.length - 1]] = schema; } /** * Recursively converts a nested shape object into a real ZodObject. */ static buildZodObject(shape) { const zodShape = {}; Object.entries(shape).forEach(([key, value]) => { if (value instanceof z.ZodType) { zodShape[key] = value; } else { zodShape[key] = _FormConfigurationValidationZodConverter.buildZodObject(value); } }); return z.object(zodShape); } applyConverter(config, schema) { const converter = this.resolveConverter(config); if (converter) { try { return converter.convert(config, schema); } catch (e) { } } return schema; } resolveConverter(config) { const allConverters = this.additionalConverters.concat(_FormConfigurationValidationZodConverter.DEFAULT_CONVERTERS_LIST); return allConverters.find((additionalConverter) => additionalConverter.supports(config)); } }; var FormConfigurationValidationZodConverter = _FormConfigurationValidationZodConverter; FormConfigurationValidationZodConverter.DEFAULT_CONVERTERS_LIST = [ { supports: (configuration) => ["NotNull", "NotBlank", "NotEmpty"].includes(configuration.name), convert: (configuration, schema) => { if (configuration.name === "NotBlank" && schema instanceof z.ZodString) { return schema.refine( (val) => val == null || typeof val === "string" && val.trim().length > 0, { message: configuration.errorMessage } ); } if (configuration.name === "NotEmpty") { if (schema instanceof z.ZodString) { return schema.refine( (val) => val == null || typeof val === "string" && val.length > 0, { message: configuration.errorMessage } ); } if (schema instanceof z.ZodArray) { return schema.refine( (val) => val == null || val.length > 0, { message: configuration.errorMessage } ); } } return schema; } }, { supports: (configuration) => ["Size", "Length"].includes(configuration.name), convert: (configuration, schema) => { if (schema instanceof z.ZodString || schema instanceof z.ZodArray) { let s = schema; if (configuration.argumentMap.min != null) s = s.min(configuration.argumentMap.min, { message: configuration.errorMessage }); if (configuration.argumentMap.max != null) s = s.max(configuration.argumentMap.max, { message: configuration.errorMessage }); return s; } return schema; } }, { supports: (configuration) => configuration.name === "Pattern", convert: (configuration, schema) => { if (!(schema instanceof z.ZodString)) { return schema; } const patternStr = configuration.argumentMap.pattern; if (typeof patternStr !== "string" || patternStr.trim() === "") { return schema; } let regex; try { regex = new RegExp(patternStr); } catch (e) { return schema; } return schema.regex(regex, { message: configuration.errorMessage }); } }, { supports: (configuration) => ["Min", "Max"].includes(configuration.name), convert: (configuration, schema) => { if (!(schema instanceof z.ZodNumber) || configuration.argumentMap.value == null) return schema; const value = configuration.argumentMap.value; return configuration.name === "Min" ? schema.min(value, { message: configuration.errorMessage }) : schema.max(value, { message: configuration.errorMessage }); } }, { supports: (configuration) => configuration.name === "InList", convert: (config, schema) => { const values = config.argumentMap.value; if (Array.isArray(values)) { return schema.refine( (val) => values.includes(val), { message: config.errorMessage } ); } return schema; } }, { supports: (configuration) => configuration.name === "Email", convert: (configuration, schema) => { if (!(schema instanceof z.ZodString)) { return schema; } return z.email(configuration.errorMessage); } }, { supports: () => true, convert: (_, schema) => schema } ]; // src/zod/loader/fetch-form-configurations.ts var mergeZodFormConfigurationsWithoutDuplicates = (oldFormConfiguration, newFormConfiguration) => { const mergedZodFormConfigurations = [...oldFormConfiguration, ...newFormConfiguration]; return (0, import_uniqBy.default)(mergedZodFormConfigurations, "formId"); }; var fetchZodFormConfigurations = (_0) => __async(void 0, [_0], function* ({ url, requestOptionsResolver, additionalValidatorConverters }) { const formConfigurationValidationConverter = new FormConfigurationValidationZodConverter(additionalValidatorConverters); const additionalOptions = (requestOptionsResolver == null ? void 0 : requestOptionsResolver()) || {}; const finalUrl = url || "/nrich/form/configuration"; const response = yield fetch(`${finalUrl}/fetch-all`, __spreadValues({ method: "POST" }, additionalOptions)); const body = yield response.json(); const zodFormConfigurations = []; if (response.ok) { body.forEach((item) => { zodFormConfigurations.push({ formId: item.formId, zodSchema: formConfigurationValidationConverter.convertFormConfigurationToZodSchema(item) }); }); useZodFormConfigurationStore.getState().set(mergeZodFormConfigurationsWithoutDuplicates(useZodFormConfigurationStore.getState().zodFormConfigurations, zodFormConfigurations)); useZodFormConfigurationStore.getState().setFormConfigurationLoaded(true); } return body; }); // src/zod/component/FormConfigurationZodProvider.tsx var FormConfigurationZodProvider = (_a) => { var _b = _a, { children, loader } = _b, fetchProps = __objRest(_b, ["children", "loader"]); useEffect(() => { fetchZodFormConfigurations(fetchProps); }, []); const { formConfigurationLoaded } = useZodFormConfigurationState(); return /* @__PURE__ */ React.createElement("div", null, formConfigurationLoaded ? children : loader != null ? loader : null); }; export { FormConfigurationZodProvider, useZodFormConfiguration, useZodFormConfigurationState }; //# sourceMappingURL=index.mjs.map