UNPKG

react-querybuilder

Version:

React Query Builder component for constructing queries and filters, with utilities for executing them in various database and evaluation contexts

172 lines (166 loc) 7.12 kB
const require_isRuleGroup = require('./isRuleGroup-Bf2BUwdE.js'); const require_optGroupUtils = require('./optGroupUtils-BVZSodaD.js'); const immer = require_isRuleGroup.__toESM(require("immer")); //#region src/utils/filterFieldsByComparator.ts const filterByComparator = (field, operator, fieldToCompare) => { const fullField = require_optGroupUtils.toFullOption(field); const fullFieldToCompare = require_optGroupUtils.toFullOption(fieldToCompare); if (fullField.value === fullFieldToCompare.value) return false; if (typeof fullField.comparator === "string") return fullField[fullField.comparator] === fullFieldToCompare[fullField.comparator]; return fullField.comparator?.(fullFieldToCompare, operator) ?? false; }; /** * For a given {@link FullField}, returns the `fields` list filtered for * other fields that match by `comparator`. Only fields *other than the * one in question* will ever be included, even if `comparator` is `null` * or `undefined`. If `comparator` is a string, fields with the same value * for that property will be included. If `comparator` is a function, each * field will be passed to the function along with the `operator` and fields * for which the function returns `true` will be included. * * @group Option Lists */ const filterFieldsByComparator = (field, fields, operator) => { if (!field.comparator) { const filterOutSameField = (f) => (f.value ?? f.name) !== (field.value ?? field.name); if (require_optGroupUtils.isFlexibleOptionGroupArray(fields)) return fields.map((og) => ({ ...og, options: og.options.filter((v) => filterOutSameField(v)) })); return fields.filter((v) => filterOutSameField(v)); } if (require_optGroupUtils.isFlexibleOptionGroupArray(fields)) return fields.map((og) => ({ ...og, options: og.options.filter((f) => filterByComparator(field, operator, f)) })).filter((og) => og.options.length > 0); return fields.filter((f) => filterByComparator(field, operator, f)); }; //#endregion //#region src/utils/getValueSourcesUtil.ts const defaultValueSourcesArray = [{ name: "value", value: "value", label: "value" }]; const dummyFD = { name: "name", value: "name", valueSources: null, label: "label" }; /** * Utility function to get the value sources array for the given * field and operator. If the field definition does not define a * `valueSources` property, the `getValueSources` prop is used. * Returns `[FullOption<"value">]` by default. */ const getValueSourcesUtil = (fieldData, operator, getValueSources) => { const fd = fieldData ? require_optGroupUtils.toFullOption(fieldData) : dummyFD; let valueSourcesNEW = fd.valueSources ?? false; if (typeof valueSourcesNEW === "function") valueSourcesNEW = valueSourcesNEW(operator); if (!valueSourcesNEW && getValueSources) valueSourcesNEW = getValueSources(fd.value, operator, { fieldData: fd }); if (!valueSourcesNEW) return defaultValueSourcesArray; if (require_optGroupUtils.isFlexibleOptionArray(valueSourcesNEW)) return require_optGroupUtils.toFullOptionList(valueSourcesNEW); return valueSourcesNEW.map((vs) => defaultValueSourcesArray.find((dmm) => dmm.value === require_isRuleGroup.lc(vs)) ?? { name: vs, value: vs, label: vs }); }; //#endregion //#region src/utils/parserUtils.ts const getFieldsArray = (fields) => { const fieldsArray = fields ? Array.isArray(fields) ? fields : Object.keys(fields).map((fld) => ({ ...fields[fld], name: fld })).sort((a, b) => a.label.localeCompare(b.label)) : []; return require_optGroupUtils.toFlatOptionArray(fieldsArray); }; function fieldIsValidUtil(params) { const { fieldsFlat, fieldName, operator, subordinateFieldName, getValueSources } = params; const vsIncludes = (vs) => { const vss = getValueSourcesUtil(primaryField, operator, getValueSources); return require_optGroupUtils.isFlexibleOptionArray(vss) && vss.some((vso) => vso.value === vs || vso.name === vs); }; if (fieldsFlat.length === 0) return true; let valid = false; const primaryField = require_optGroupUtils.toFullOption(fieldsFlat.find((ff) => ff.name === fieldName)); if (primaryField) { valid = !(!subordinateFieldName && operator !== "notNull" && operator !== "null" && !vsIncludes("value")); if (valid && !!subordinateFieldName) if (vsIncludes("field") && fieldName !== subordinateFieldName) { const validSubordinateFields = filterFieldsByComparator(primaryField, fieldsFlat, operator); if (!validSubordinateFields.some((vsf) => vsf.name === subordinateFieldName)) valid = false; } else valid = false; } return valid; } //#endregion //#region src/utils/generateID.ts const cryptoModule = globalThis.crypto; /** * Default `id` generator. Generates a valid v4 UUID. Uses `crypto.randomUUID()` * when available, otherwise uses an alternate method based on `getRandomValues`. * The returned string is guaranteed to match this regex: * ``` * /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i * ``` * @returns Valid v4 UUID */ // istanbul ignore next let generateID = () => "00-0-4-2-000".replaceAll(/[^-]/g, (s) => ((Math.random() + Math.trunc(s)) * 65536 >> Number.parseInt(s)).toString(16).padStart(4, "0")); // istanbul ignore else if (cryptoModule) { // istanbul ignore else if (typeof cryptoModule.randomUUID === "function") generateID = () => cryptoModule.randomUUID(); else if (typeof cryptoModule.getRandomValues === "function") { const position19vals = "89ab"; const container = new Uint32Array(32); generateID = () => { cryptoModule.getRandomValues(container); let id = (container[0] % 16).toString(16); for (let i = 1; i < 32; i++) { if (i === 12) id = `${id}4`; else if (i === 16) id = `${id}${position19vals[container[17] % 4]}`; else id = `${id}${(container[i] % 16).toString(16)}`; if (i === 7 || i === 11 || i === 15 || i === 19) id = `${id}-`; } return id; }; } } //#endregion //#region src/utils/prepareQueryObjects.ts /** * Ensures that a rule is valid by adding an `id` property if it does not already exist. */ const prepareRule = (rule, { idGenerator = generateID } = {}) => (0, immer.produce)(rule, (draft) => { if (!draft.id) draft.id = idGenerator(); }); /** * Ensures that a rule group is valid by recursively adding an `id` property to the group itself * and all its rules and subgroups where one does not already exist. */ const prepareRuleGroup = (queryObject, { idGenerator = generateID } = {}) => (0, immer.produce)(queryObject, (draft) => { if (!draft.id) draft.id = idGenerator(); draft.rules = draft.rules.map((r) => typeof r === "string" ? r : require_isRuleGroup.isRuleGroup(r) ? prepareRuleGroup(r, { idGenerator }) : prepareRule(r, { idGenerator })); }); //#endregion Object.defineProperty(exports, 'fieldIsValidUtil', { enumerable: true, get: function () { return fieldIsValidUtil; } }); Object.defineProperty(exports, 'getFieldsArray', { enumerable: true, get: function () { return getFieldsArray; } }); Object.defineProperty(exports, 'prepareRuleGroup', { enumerable: true, get: function () { return prepareRuleGroup; } }); //# sourceMappingURL=prepareQueryObjects-D-xu06SF.js.map