Home Reference Source

lib6/mapping.rulesfactories.js

/**
 * Copyright (c) "Neo4j"
 * Neo4j Sweden AB [http://neo4j.com]
 *
 * This file is part of Neo4j.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { valueAs, optionalParameterConversion, defaultNameMapping, getRules } from './mapping.highlevel';
import { isNode, isPath, isRelationship } from './graph-types';
import { isPoint } from './spatial-types';
import { Date, DateTime, Duration, LocalDateTime, LocalTime, Time, isDate, isDateTime, isDuration, isLocalDateTime, isLocalTime, isTime } from './temporal-types';
import { isVector, vector } from './vector';
import { newError } from './error';
import Integer, { isInt } from './integer';
/**
 * @property {function(rule: ?Rule)} asBoolean Create a {@link Rule} that validates the value is a Boolean.
 *
 * @property {function(rule: ?Rule)} asString Create a {@link Rule} that validates the value is a String.
 *
 * @property {function(rule: ?Rule & { isInteger?: boolean })} asNumber Create a {@link Rule} that validates the value is a {@link Number}.
 *
 * @property {function(rule: ?Rule & { acceptNumber?: boolean })} asBigInt Create a {@link Rule} that validates the value is a {@link BigInt}.
 *
 * @property {function(rule: ?Rule & { acceptNumber?: boolean })} asInteger Create a {@link Rule} that validates the value is an {@link Integer}.
 *
 * @property {function(rule: ?Rule)} asNode Create a {@link Rule} that validates the value is a {@link Node}.
 *
 * @property {function(rule: ?Rule)} asRelationship Create a {@link Rule} that validates the value is a {@link Relationship}.
 *
 * @property {function(rule: ?Rule)} asPath Create a {@link Rule} that validates the value is a {@link Path}.
 *
 * @property {function(rule: ?Rule)} asPoint Create a {@link Rule} that validates the value is a {@link Point}.
 *
 * @property {function(rule: ?Rule & { stringify?: boolean })} asDuration Create a {@link Rule} that validates the value is a {@link Duration}.
 *
 * @property {function(rule: ?Rule & { stringify?: boolean })} asLocalTime Create a {@link Rule} that validates the value is a {@link LocalTime}.
 *
 * @property {function(rule: ?Rule & { stringify?: boolean })} asTime Create a {@link Rule} that validates the value is a {@link Time}.
 *
 * @property {function(rule: ?Rule & { stringify?: boolean, jsNativeDate?: boolean })} asDate Create a {@link Rule} that validates the value is a {@link Date}.
 *
 * @property {function(rule: ?Rule & { stringify?: boolean, jsNativeDate?: boolean })} asLocalDateTime Create a {@link Rule} that validates the value is a {@link LocalDateTime}.
 *
 * @property {function(rule: ?Rule & { stringify?: boolean, jsNativeDate?: boolean })} asDateTime Create a {@link Rule} that validates the value is a {@link DateTime}.
 *
 * @property {function(rule: ?Rule & { apply?: Rule })} asList Create a {@link Rule} that validates the value is a List.
 *
 * @property {function(rule: ?Rule & { asTypedList?: boolean, dimension?: number, type?: VectorType })} asVector Create a {@link Rule} that validates the value is a Vector.
 *
 * @property {function(rules: Rules)} asObject Create a {@link Rule} for an object, allowing complex mapping of even nested results.
 */
export const rule = Object.freeze({
    /**
     * Create a {@link Rule} that validates the value is a Boolean.
     *
     * @param {Rule | undefined} rule Configurations for the rule
     * @returns {Rule} A new rule for the value
     */
    asBoolean(rule) {
        return Object.assign({ validate: (value, field) => {
                if (typeof value !== 'boolean') {
                    throw new TypeError(`${field} should be a boolean but received ${typeof value}`);
                }
            } }, rule);
    },
    /**
     * Create a {@link Rule} that validates the value is a String.
     *
     * Optionally takes a {@link Rule}, in which case the returned rule will keep all fields of the one provided.
     *
     * @param {Rule | undefined} rule Configurations for the rule
     * @returns {Rule} A new rule for the value
     */
    asString(rule) {
        return Object.assign({ validate: (value, field) => {
                if (typeof value !== 'string') {
                    throw new TypeError(`${field} should be a string but received ${typeof value}`);
                }
            } }, rule);
    },
    /**
     * Create a {@link Rule} that validates the value is a {@link Number}.
     *
     * Optionally takes a {@link Rule}, in which case the returned rule will keep all fields of the one provided.
     *
     * @param {Rule & { isInteger?: boolean } | undefined} rule Configurations for the rule.
     * If `isInteger` is set to true, the created validate function will allow Integer values through, and the conversion functions will ensure results are return as numbers while parameters are transmitted as integers.
     * @returns {Rule} A new rule for the value
     */
    asNumber(rule) {
        return Object.assign({ validate: (value, field) => {
                if (isInt(value) && (rule === null || rule === void 0 ? void 0 : rule.isInteger) !== true) {
                    throw new TypeError('Number returned as Integer Object. To use asNumber mapping with Integers, set "isInteger" in rule configuration.');
                }
                if ((rule === null || rule === void 0 ? void 0 : rule.isInteger) !== true && typeof value === 'bigint') {
                    throw new TypeError('Number returned as BigInt. To use asNumber mapping with integer values, set "isInteger" in rule configuration.');
                }
                if (typeof value !== 'number' && !(isInt(value) && (rule === null || rule === void 0 ? void 0 : rule.isInteger) === true)) {
                    throw new TypeError(`${field} should be a number but received ${typeof value}`);
                }
                if ((rule === null || rule === void 0 ? void 0 : rule.isInteger) === true && typeof value === 'number' && !Number.isInteger(value)) {
                    throw new TypeError(`${field} should be an integer value but received decimal number.`);
                }
            }, convert: (value) => {
                if (typeof value === 'bigint') {
                    return Number(value);
                }
                if (isInt(value)) {
                    return value.toNumber();
                }
                return value;
            }, parameterConversion: (value) => {
                if ((rule === null || rule === void 0 ? void 0 : rule.isInteger) === true) {
                    return Integer.fromValue(value);
                }
                return value;
            } }, rule);
    },
    /**
     * Create a {@link Rule} that validates the value is a {@link BigInt}.
     *
     * Optionally takes a {@link Rule}, in which case the returned rule will keep all fields of the one provided.
     *
     * @returns {Rule} A new rule for the value
     */
    asBigInt(rule) {
        return Object.assign({ validate: (value, field) => {
                if (typeof value !== 'bigint' && ((rule === null || rule === void 0 ? void 0 : rule.acceptNumber) !== true || typeof value !== 'number') && !isInt(value)) {
                    throw new TypeError(`${field} should be a bigint but received ${typeof value}`);
                }
            }, convert: (value) => {
                if (typeof value === 'number') {
                    return BigInt(value);
                }
                if (isInt(value)) {
                    return value.toBigInt();
                }
                return value;
            } }, rule);
    },
    /**
     * Create a {@link Rule} that validates the value is an {@link Integer}.
     *
     * Optionally takes a {@link Rule}, in which case the returned rule will keep all fields of the one provided.
     *
     * @param {Rule & { acceptNumber?: boolean } | undefined} rule Configurations for the rule, if `acceptNumber` is set to true, the created validate function will allow Numbers through and the conversion functions will turn Numbers into Integers.
     * @returns {Rule} A new rule for the value
     */
    asInteger(rule) {
        return Object.assign({ validate: (value, field) => {
                if (typeof value !== 'bigint' && !isInt(value) && !(typeof value === 'number' && (rule === null || rule === void 0 ? void 0 : rule.acceptNumber) === true)) {
                    throw new TypeError(`${field} should be an Integer but received ${typeof value}`);
                }
            }, convert: (value) => {
                if (typeof value === 'bigint') {
                    return Integer.fromValue(value);
                }
                return value;
            } }, rule);
    },
    /**
     * Create a {@link Rule} that validates the value is a {@link Node}.
     *
     * Optionally takes a {@link Rule}, in which case the returned rule will keep all fields of the one provided.
     *
     * @example
     * const actingJobsRules: Rules = {
     *  // Converts the person node to a Person object in accordance with provided rules
     *  person: neo4j.rule.asNode({
     *    convert: (node: Node) => node.as(Person, personRules)
     *  }),
     *  // Returns the movie node as a Node
     *  movie: neo4j.rule.asNode({}),
     * }
     *
     * @param {Rule | undefined} rule Configurations for the rule
     * @returns {Rule} A new rule for the value
     */
    asNode(rule) {
        return Object.assign({ validate: (value, field) => {
                if (!isNode(value)) {
                    throw new TypeError(`${field} should be a Node but received ${typeof value}`);
                }
            } }, rule);
    },
    /**
     * Create a {@link Rule} that validates the value is a {@link Relationship}.
     *
     * Optionally takes a {@link Rule}, in which case the returned rule will keep all fields of the one provided.
     *
     * @example
     * const actingJobsRules: Rules = {
     *  // Converts the role relationship to a Role object in accordance with provided rules
     *  role: neo4j.rule.asRelationship({
     *    convert: (rel: Relationship) => rel.as(Role, roleRules)
     *  }),
     *  // Returns the employment relationship as a Relationship
     *  employment: neo4j.rule.asRelationship({}),
     * }
     *
     * @param {Rule | undefined} rule Configurations for the rule.
     * @returns {Rule} A new rule for the value
     */
    asRelationship(rule) {
        return Object.assign({ validate: (value, field) => {
                if (!isRelationship(value)) {
                    throw new TypeError(`${field} should be a Relationship but received ${typeof value}`);
                }
            } }, rule);
    },
    /**
     * Create a {@link Rule} that validates the value is a {@link Path}
     *
     * Optionally takes a {@link Rule}, in which case the returned rule will keep all fields of the one provided.
     *
     * @param {Rule | undefined} rule Configurations for the rule
     * @returns {Rule} A new rule for the value
     */
    asPath(rule) {
        return Object.assign({ validate: (value, field) => {
                if (!isPath(value)) {
                    throw new TypeError(`${field} should be a Path but received ${typeof value}`);
                }
            } }, rule);
    },
    /**
     * Create a {@link Rule} that validates the value is a {@link Point}
     *
     * Optionally takes a {@link Rule}, in which case the returned rule will keep all fields of the one provided.
     *
     * @param {Rule | undefined} rule Configurations for the rule
     * @returns {Rule} A new rule for the value
     */
    asPoint(rule) {
        return Object.assign({ validate: (value, field) => {
                if (!isPoint(value)) {
                    throw new TypeError(`${field} should be a Point but received ${typeof value}`);
                }
            } }, rule);
    },
    /**
     * Create a {@link Rule} that validates the value is a {@link Duration}
     *
     * Optionally takes a {@link Rule}, in which case the returned rule will keep all fields of the one provided.
     *
     * @param {Rule & { stringify?: boolean } | undefined} rule Configurations for the rule. If `stringify` is set, the returned rule will have `convert` and `parameterConversion` functions which automatically convert between strings in user code and {@link Duration}s in the database.
     * @returns {Rule} A new rule for the value
     */
    asDuration(rule) {
        if ((rule === null || rule === void 0 ? void 0 : rule.stringify) != null && ((rule === null || rule === void 0 ? void 0 : rule.convert) != null || rule.parameterConversion != null)) {
            throw newError('Provided rule already has convert and/or parameterConversion function, stringify can not be used in combination with custom conversion functions.');
        }
        return Object.assign({ validate: (value, field) => {
                if (!isDuration(value)) {
                    throw new TypeError(`${field} should be a Duration but received ${typeof value}`);
                }
            }, convert: (value) => (rule === null || rule === void 0 ? void 0 : rule.stringify) === true ? value.toString() : value, parameterConversion: (rule === null || rule === void 0 ? void 0 : rule.stringify) === true ? (str) => Duration.fromString(str) : undefined }, rule);
    },
    /**
     * Create a {@link Rule} that validates the value is a {@link LocalTime}
     *
     * @param {Rule & { stringify?: boolean } | undefined} rule Configurations for the rule. If `stringify` is set, the returned rule will have `convert` and `parameterConversion` functions which automatically convert between strings in user code and {@link LocalTime}s in the database.
     * @returns {Rule} A new rule for the value
     */
    asLocalTime(rule) {
        if ((rule === null || rule === void 0 ? void 0 : rule.stringify) != null && ((rule === null || rule === void 0 ? void 0 : rule.convert) != null || rule.parameterConversion != null)) {
            throw newError('Provided rule already has convert and/or parameterConversion function, stringify can not be used in combination with custom conversion functions.');
        }
        return Object.assign({ validate: (value, field) => {
                if (!isLocalTime(value)) {
                    throw new TypeError(`${field} should be a LocalTime but received ${typeof value}`);
                }
            }, convert: (value) => (rule === null || rule === void 0 ? void 0 : rule.stringify) === true ? value.toString() : value, parameterConversion: (rule === null || rule === void 0 ? void 0 : rule.stringify) === true ? (str) => LocalTime.fromString(str) : undefined }, rule);
    },
    /**
     * Create a {@link Rule} that validates the value is a {@link Time}
     *
     * @param {Rule & { stringify?: boolean } | undefined} rule Configurations for the rule. If `stringify` is set, the returned rule will have `convert` and `parameterConversion` functions which automatically convert between strings in user code and {@link Time}s in the database.
     * @returns {Rule} A new rule for the value
     */
    asTime(rule) {
        if ((rule === null || rule === void 0 ? void 0 : rule.stringify) != null && ((rule === null || rule === void 0 ? void 0 : rule.convert) != null || rule.parameterConversion != null)) {
            throw newError('Provided rule already has convert and/or parameterConversion function, stringify can not be used in combination with custom conversion functions.');
        }
        return Object.assign({ validate: (value, field) => {
                if (!isTime(value)) {
                    throw new TypeError(`${field} should be a Time but received ${typeof value}`);
                }
            }, convert: (value) => (rule === null || rule === void 0 ? void 0 : rule.stringify) === true ? value.toString() : value, parameterConversion: (rule === null || rule === void 0 ? void 0 : rule.stringify) === true ? (str) => Time.fromString(str) : undefined }, rule);
    },
    /**
     * Create a {@link Rule} that validates the value is a {@link Date}
     *
     * @param {Rule & { stringify?: boolean, jsNativeDate?: boolean } | undefined} rule Configurations for the rule. If `stringify`/`jsNativeDate` is set, the returned rule will have `convert` and `parameterConversion` functions which automatically convert between strings/JavaScript Dates in user code and {@link Date}s in the database.
     * @returns {Rule} A new rule for the value
     */
    asDate(rule) {
        if ((rule === null || rule === void 0 ? void 0 : rule.stringify) != null && ((rule === null || rule === void 0 ? void 0 : rule.convert) != null || rule.parameterConversion != null)) {
            throw newError('Provided rule already has convert and/or parameterConversion function, stringify can not be used in combination with custom conversion functions.');
        }
        if ((rule === null || rule === void 0 ? void 0 : rule.jsNativeDate) != null && ((rule === null || rule === void 0 ? void 0 : rule.convert) != null || rule.parameterConversion != null)) {
            throw newError('Provided rule already has convert and/or parameterConversion function, jsNativeDate can not be used in combination with custom conversion functions.');
        }
        if ((rule === null || rule === void 0 ? void 0 : rule.stringify) === true && (rule === null || rule === void 0 ? void 0 : rule.jsNativeDate) === true) {
            throw newError('both stringify and jsNativeDate cannot be set; use one or neither');
        }
        let parameterConversion;
        if ((rule === null || rule === void 0 ? void 0 : rule.stringify) === true) {
            parameterConversion = (str) => Date.fromString(str);
        }
        if ((rule === null || rule === void 0 ? void 0 : rule.jsNativeDate) === true) {
            parameterConversion = (standardDate) => Date.fromStandardDateLocal(standardDate);
        }
        return Object.assign({ validate: (value, field) => {
                if (!isDate(value)) {
                    throw new TypeError(`${field} should be a Date but received ${typeof value}`);
                }
            }, convert: (value) => convertStdDate(value, rule), parameterConversion }, rule);
    },
    /**
     * Create a {@link Rule} that validates the value is a {@link LocalDateTime}
     *
     * @param {Rule & { stringify?: boolean, jsNativeDate?: boolean } | undefined} rule Configurations for the rule. If `stringify`/`jsNativeDate` is set, the returned rule will have `convert` and `parameterConversion` functions which automatically convert between strings/JavaScript Dates in user code and {@link LocalDateTime}s in the database.
     * @returns {Rule} A new rule for the value
     */
    asLocalDateTime(rule) {
        if ((rule === null || rule === void 0 ? void 0 : rule.stringify) != null && ((rule === null || rule === void 0 ? void 0 : rule.convert) != null || rule.parameterConversion != null)) {
            throw newError('Provided rule already has convert and/or parameterConversion function, stringify can not be used in combination with custom conversion functions.');
        }
        if ((rule === null || rule === void 0 ? void 0 : rule.jsNativeDate) != null && ((rule === null || rule === void 0 ? void 0 : rule.convert) != null || rule.parameterConversion != null)) {
            throw newError('Provided rule already has convert and/or parameterConversion function, jsNativeDate can not be used in combination with custom conversion functions.');
        }
        if ((rule === null || rule === void 0 ? void 0 : rule.stringify) === true && (rule === null || rule === void 0 ? void 0 : rule.jsNativeDate) === true) {
            throw newError('both stringify and jsNativeDate cannot be set; use one or neither');
        }
        let parameterConversion;
        if ((rule === null || rule === void 0 ? void 0 : rule.stringify) === true) {
            parameterConversion = (str) => LocalDateTime.fromString(str);
        }
        if ((rule === null || rule === void 0 ? void 0 : rule.jsNativeDate) === true) {
            parameterConversion = (standardDate) => LocalDateTime.fromStandardDate(standardDate);
        }
        return Object.assign({ validate: (value, field) => {
                if (!isLocalDateTime(value)) {
                    throw new TypeError(`${field} should be a LocalDateTime but received ${typeof value}`);
                }
            }, convert: (value) => convertStdDate(value, rule), parameterConversion }, rule);
    },
    /**
     * Create a {@link Rule} that validates the value is a {@link DateTime}
     *
     * @param {Rule & { stringify?: boolean, jsNativeDate?: boolean } | undefined} rule Configurations for the rule. If `stringify`/`jsNativeDate` is set, the returned rule will have `convert` and `parameterConversion` functions which automatically convert between strings/JavaScript Dates in user code and {@link DateTime}s in the database.
     * @returns {Rule} A new rule for the value
     */
    asDateTime(rule) {
        if ((rule === null || rule === void 0 ? void 0 : rule.stringify) != null && ((rule === null || rule === void 0 ? void 0 : rule.convert) != null || rule.parameterConversion != null)) {
            throw newError('Provided rule already has convert and/or parameterConversion function, stringify can not be used in combination with custom conversion functions.');
        }
        if ((rule === null || rule === void 0 ? void 0 : rule.jsNativeDate) != null && ((rule === null || rule === void 0 ? void 0 : rule.convert) != null || rule.parameterConversion != null)) {
            throw newError('Provided rule already has convert and/or parameterConversion function, jsNativeDate can not be used in combination with custom conversion functions.');
        }
        if ((rule === null || rule === void 0 ? void 0 : rule.stringify) === true && (rule === null || rule === void 0 ? void 0 : rule.jsNativeDate) === true) {
            throw newError('both stringify and jsNativeDate cannot be set; use one or neither');
        }
        let parameterConversion;
        if ((rule === null || rule === void 0 ? void 0 : rule.stringify) === true) {
            parameterConversion = (str) => DateTime.fromString(str);
        }
        if ((rule === null || rule === void 0 ? void 0 : rule.jsNativeDate) === true) {
            parameterConversion = (standardDate) => DateTime.fromStandardDate(standardDate);
        }
        return Object.assign({ validate: (value, field) => {
                if (!isDateTime(value)) {
                    throw new TypeError(`${field} should be a DateTime but received ${typeof value}`);
                }
            }, convert: (value) => convertStdDate(value, rule), parameterConversion }, rule);
    },
    /**
     * Create a {@link Rule} that validates the value is a List.
     *
     * Optionally taking a rule for hydrating the contained values.
     *
     * @param {Rule & { apply?: Rule } | undefined} rule Configurations for the rule. Setting apply to a rule will apply that rule to all elements of the list.
     * @returns {Rule} A new rule for the value
     */
    asList(rule) {
        return Object.assign({ validate: (list, field) => {
                var _a;
                if (!Array.isArray(list)) {
                    throw new TypeError(`${field} should be a list but received ${typeof list}`);
                }
                const validate = (_a = rule === null || rule === void 0 ? void 0 : rule.apply) === null || _a === void 0 ? void 0 : _a.validate;
                if (validate != null) {
                    list.forEach((value, index) => validate(value, `${field}[${index}]`));
                }
            }, convert: (list, field) => {
                if ((rule === null || rule === void 0 ? void 0 : rule.apply) != null) {
                    return list.map((value, index) => valueAs(value, `${field}[${index}]`, rule.apply));
                }
                return list;
            }, parameterConversion: (list) => {
                const apply = rule === null || rule === void 0 ? void 0 : rule.apply;
                if (apply != null) {
                    return list.map((value) => optionalParameterConversion(value, apply));
                }
                return list;
            } }, rule);
    },
    /**
     * Create a {@link Rule} that validates the value is a Vector.
     *
     * @param {Rule & { asTypedList?: boolean, dimension?: number, type?: VectorType } | undefined} rule Configurations for the rule. Setting asTypedList will automatically convert between TypedList in user code and Vectors in the database.
     * @returns {Rule} A new rule for the value
     */
    asVector(rule) {
        if ((rule === null || rule === void 0 ? void 0 : rule.asTypedList) != null && ((rule === null || rule === void 0 ? void 0 : rule.convert) != null || rule.parameterConversion != null)) {
            throw newError('Provided rule already has convert and/or parameterConversion function, asTypedList can not be used in combination with custom conversion functions.');
        }
        return Object.assign({ validate: (value, field) => {
                if (!isVector(value)) {
                    throw new TypeError(`${field} should be a vector but received ${typeof value}`);
                }
                if ((rule === null || rule === void 0 ? void 0 : rule.dimension) != null && value.asTypedArray().length !== rule.dimension) {
                    throw new TypeError(`${field} should be a vector of length ${rule.dimension} but received length ${value.asTypedArray().length}`);
                }
                if ((rule === null || rule === void 0 ? void 0 : rule.type) != null && value.getType() !== rule.type) {
                    throw new TypeError(`${field} should be a vector of type ${rule.type} but received type ${value.getType()}`);
                }
            }, convert: (value) => {
                if ((rule === null || rule === void 0 ? void 0 : rule.asTypedList) === true) {
                    return value._typedArray;
                }
                return value;
            }, parameterConversion: (rule === null || rule === void 0 ? void 0 : rule.asTypedList) === true ? (typedArray) => vector(typedArray) : undefined }, rule);
    },
    /**
     * Create a {@link Rule} for an object, allowing complex mapping of even nested results
     *
     * NOTE: When using this rule, object identifiers will be mapped according to any name mapping set with neo4j.RecordObjectMapping.translateIdentifiers.
     *
     * @param {Rules} rules rules for the fields of the object.
     * @param {GenericConstructor} constructor The constructor function of the class to map to. The constructor must be callable with all arguments undefined.
     * @returns {Rule} A new rule for the value
     */
    asObject(constructorOrRules, rules) {
        const GenericConstructor = typeof constructorOrRules === 'function' ? constructorOrRules : Object;
        const theRules = getRules(constructorOrRules, rules);
        return Object.assign({ validate: (value, field) => {
                for (const key in theRules) {
                    const mappedKey = theRules[key].from != null ? theRules[key].from : defaultNameMapping(key);
                    if (value[mappedKey] == null) {
                        if (theRules[key].optional === true) {
                            continue;
                        }
                        else {
                            throw newError(`Mapped object did not include required field ${field} with key ${mappedKey}.`);
                        }
                    }
                    if (theRules[key].validate != null) {
                        theRules[key].validate(value[mappedKey], `${field}[${key}]`);
                    }
                }
            }, convert: (value, field) => {
                const convertedValue = new GenericConstructor();
                for (const key in theRules) {
                    const mappedKey = theRules[key].from != null ? theRules[key].from : defaultNameMapping(key);
                    if (value[mappedKey] != null && theRules[key].convert != null) {
                        // @ts-expect-error
                        convertedValue[key] = theRules[key].convert(value[mappedKey], `${field}[${mappedKey}]`);
                    }
                    else {
                        // @ts-expect-error
                        convertedValue[key] = value[mappedKey];
                    }
                }
                return convertedValue;
            }, parameterConversion: (value) => {
                const convertedValue = {};
                for (const key in theRules) {
                    const mappedKey = theRules[key].from != null ? theRules[key].from : defaultNameMapping(key);
                    if (value[key] != null && theRules[key].parameterConversion != null) {
                        convertedValue[mappedKey] = theRules[key].parameterConversion(value[key]);
                    }
                    else {
                        convertedValue[mappedKey] = value[key];
                    }
                }
                return convertedValue;
            } }, rule);
    }
});
function convertStdDate(value, rule) {
    if (rule != null) {
        if (rule.stringify === true) {
            return value.toString();
        }
        else if (rule.jsNativeDate === true) {
            return value.toStandardDate();
        }
    }
    return value;
}