{"version":3,"sources":["../src/validation.ts"],"names":["validation","node","hints"],"mappings":"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","sourcesContent":["import { FormKitNode, FormKitMessage, createMessage } from '@formkit/core'\nimport {\n  FormKitObservedNode,\n  createObserver,\n  applyListeners,\n  diffDeps,\n  removeListeners,\n  FormKitDependencies,\n  isKilled,\n} from '@formkit/observer'\nimport { has, empty, token, clone, cloneAny, eq } from '@formkit/utils'\n\n/**\n * Special validation properties that affect the way validations are applied.\n *\n * @public\n */\nexport interface FormKitValidationHints {\n  /**\n   * If this validation fails, should it block the form from being submitted or\n   * considered \"valid\"? There are some cases where it is acceptable to allow\n   * an incorrect value to still be allowed to submit.\n   */\n  blocking: boolean\n  /**\n   * Only run this rule after this many milliseconds of debounce. This is\n   * particularity helpful for more \"expensive\" async validation rules like\n   * checking if a username is taken from the backend.\n   */\n  debounce: number\n  /**\n   * Normally the first validation rule to fail blocks other rules from running\n   * if this flag is flipped to true, this rule will be run every time even if\n   * a previous rule in the validation stack failed.\n   */\n  force: boolean\n  /**\n   * Most validation rules are not run when the input is empty, but this flag\n   * allows that behavior to be changed.\n   */\n  skipEmpty: boolean\n  /**\n   * The actual name of the validation rule.\n   */\n  name: string\n}\n\n/**\n * Defines what fully parsed validation rules look like.\n * @public\n */\nexport type FormKitValidation = {\n  /**\n   * The actual rule function that will be called\n   */\n  rule: FormKitValidationRule\n  /**\n   * Arguments to be passed to the validation rule\n   */\n  args: any[]\n  /**\n   * The debounce timer for this input.\n   */\n  timer: number\n  /**\n   * The state of a validation, can be true, false, or null which means unknown.\n   */\n  state: boolean | null\n  /**\n   * Determines if the rule should be considered for the next run cycle. This\n   * does not mean the rule will be validated, it just means that it should be\n   * considered.\n   */\n  queued: boolean\n  /**\n   * Dependencies this validation rule is observing.\n   */\n  deps: FormKitDependencies\n  /**\n   * The observed node that is being validated.\n   */\n  observer: FormKitObservedNode\n  /**\n   * An observer that updates validation messages when it’s dependencies change,\n   * for example, the label of the input.\n   */\n  messageObserver?: FormKitObservedNode\n} & FormKitValidationHints\n\n/**\n * Defines what validation rules look like when they are parsed, but have not\n * necessarily had validation rules substituted in yet.\n * @public\n */\nexport type FormKitValidationIntent = [string | FormKitValidationRule, ...any[]]\n\n/**\n * Signature for a generic validation rule. It accepts an input — often a string\n * — but should be able to accept any input type, and returns a boolean\n * indicating whether or not it passed validation.\n * @public\n */\nexport type FormKitValidationRule = {\n  (node: FormKitNode, ...args: any[]): boolean | Promise<boolean>\n  ruleName?: string\n} & Partial<FormKitValidationHints>\n\n/**\n * A validation rule result.\n * @public\n */\nexport interface FormKitValidationRuleResult {\n  result: boolean\n  validation: FormKitValidation\n}\n\n/**\n * FormKit validation rules are structured as on object of key/function pairs\n * where the key of the object is the validation rule name.\n * @public\n */\nexport interface FormKitValidationRules {\n  [index: string]: FormKitValidationRule\n}\n\n/**\n * The interface for the localized validation message function.\n * @public\n */\nexport interface FormKitValidationMessage {\n  (...args: FormKitValidationI18NArgs): string\n}\n\n/**\n * The interface for the localized validation message registry.\n * @public\n */\nexport interface FormKitValidationMessages {\n  [index: string]: string | FormKitValidationMessage\n}\n\n/**\n * Determines the validation nonce.\n * @public\n */\ninterface FormKitValidationState {\n  input: string | null\n  rerun: number | null\n  isPassing: boolean\n}\n\n/**\n * The arguments that are passed to the validation messages in the i18n plugin.\n *\n * @public\n */\nexport type FormKitValidationI18NArgs = [\n  {\n    node: FormKitNode\n    name: string\n    args: any[]\n    message?: string\n  }\n]\n\n/**\n * Message that gets set when the node is awaiting validation.\n */\nconst validatingMessage = /* #__PURE__ */ createMessage({\n  type: 'state',\n  blocking: true,\n  visible: false,\n  value: true,\n  key: 'validating',\n})\n\n/**\n * The actual validation plugin function. Everything must be bootstrapped here.\n *\n * @param baseRules - Base validation rules to include in the plugin. By default,\n * FormKit makes all rules in the \\@formkit/rules package available via the\n * defaultConfig.\n *\n * @public\n */\nexport function createValidationPlugin(baseRules: FormKitValidationRules = {}) {\n  return function validationPlugin(node: FormKitNode): void {\n    let propRules = cloneAny(node.props.validationRules || {})\n    let availableRules = { ...baseRules, ...propRules }\n    // create an observed node\n    const state = { input: token(), rerun: null, isPassing: true }\n    let validation = cloneAny(node.props.validation)\n    // If the node's validation props change, reboot:\n    node.on('prop:validation', ({ payload }) => reboot(payload, propRules))\n    node.on('prop:validationRules', ({ payload }) =>\n      reboot(validation, payload)\n    )\n    /**\n     * Reboots the validation using new rules or declarations/intents.\n     * @param newValidation - New validation declaration to use\n     * @param newRules - New validation rules to use\n     * @returns\n     */\n    function reboot(\n      newValidation: undefined | string | FormKitValidationIntent[],\n      newRules: FormKitValidationRules\n    ) {\n      if (\n        eq(Object.keys(propRules || {}), Object.keys(newRules || {})) &&\n        eq(validation, newValidation)\n      )\n        return\n      propRules = cloneAny(newRules)\n      validation = cloneAny(newValidation)\n      availableRules = { ...baseRules, ...propRules }\n      // Destroy all observers that may re-trigger validation on an old stack\n      // Clear existing message observers\n      node.props.parsedRules?.forEach((validation: FormKitValidation) => {\n        removeMessage(validation)\n        removeListeners(validation.observer.receipts)\n        validation.observer.kill()\n      })\n      // Remove all existing messages before re-validating\n      node.store.filter(() => false, 'validation')\n      node.props.parsedRules = parseRules(newValidation, availableRules, node)\n      state.isPassing = true\n      validate(node, node.props.parsedRules, state)\n    }\n\n    // Validate the field when this plugin is initialized\n    node.props.parsedRules = parseRules(validation, availableRules, node)\n    validate(node, node.props.parsedRules, state)\n  }\n}\n\n/**\n * Given parsed validations, a value and a node, run the validations and set\n * the appropriate store messages on the node.\n * @param value - The value being validated\n * @param node - The Node this value belongs to\n * @param rules - The rules\n */\nfunction validate(\n  node: FormKitNode | FormKitObservedNode,\n  validations: FormKitValidation[],\n  state: FormKitValidationState\n) {\n  if (isKilled(node)) return\n  state.input = token()\n  node.store.set(\n    /* #__PURE__ */ createMessage({\n      key: 'failing',\n      value: !state.isPassing,\n      visible: false,\n    })\n  )\n  state.isPassing = true\n  node.store.filter((message) => !message.meta.removeImmediately, 'validation')\n  validations.forEach(\n    (validation) => validation.debounce && clearTimeout(validation.timer)\n  )\n  if (validations.length) {\n    node.store.set(validatingMessage)\n    run(0, validations, state, false, () => {\n      node.store.remove(validatingMessage.key)\n      node.store.set(\n        /* #__PURE__ */ createMessage({\n          key: 'failing',\n          value: !state.isPassing,\n          visible: false,\n        })\n      )\n    })\n  }\n}\n\n/**\n * Runs validation rules recursively while collecting dependencies allowing for\n * cross-node validation rules that automatically re-trigger when a foreign\n * value is changed.\n * @param current - The index of the current validation rule\n * @param validations - The remaining validation rule stack to run\n * @param node - An observed node, the owner of this validation stack\n * @param state - An object of state information about this run\n * @param removeImmediately - Should messages created during this call be removed immediately when a new commit takes place?\n * @returns\n */\nfunction run(\n  current: number,\n  validations: FormKitValidation[],\n  state: FormKitValidationState,\n  removeImmediately: boolean,\n  complete: () => void\n): void {\n  const validation = validations[current]\n  if (!validation) return complete()\n  const node = validation.observer\n  if (isKilled(node)) return\n  const currentRun = state.input\n  validation.state = null\n\n  function next(async: boolean, result: boolean | null): void {\n    if (state.input !== currentRun) return\n    state.isPassing = state.isPassing && !!result\n    validation.queued = false\n    const newDeps = node.stopObserve()\n    const diff = diffDeps(validation.deps, newDeps)\n    applyListeners(\n      node,\n      diff,\n      function revalidate() {\n        // Event callback for when the deps change:\n        try {\n          node.store.set(validatingMessage)\n        } catch (e) {}\n        validation.queued = true\n        if (state.rerun) clearTimeout(state.rerun)\n        state.rerun = setTimeout(\n          validate,\n          0,\n          node,\n          validations,\n          state\n        ) as unknown as number\n      },\n      'unshift' // We want these listeners to run before other events are emitted so the 'state.validating' will be reliable.\n    )\n    validation.deps = newDeps\n\n    validation.state = result\n    if (result === false) {\n      createFailedMessage(validation, removeImmediately || async)\n    } else {\n      removeMessage(validation)\n    }\n    if (validations.length > current + 1) {\n      const nextValidation = validations[current + 1]\n      if (\n        (result || nextValidation.force || !nextValidation.skipEmpty) &&\n        nextValidation.state === null\n      ) {\n        // If the next rule was never run then it has not been observed so it could never\n        // run again on its own.\n        nextValidation.queued = true\n      }\n      run(current + 1, validations, state, removeImmediately || async, complete)\n    } else {\n      // The validation has completed\n      complete()\n    }\n  }\n  if (\n    (!empty(node.value) || !validation.skipEmpty) &&\n    (state.isPassing || validation.force)\n  ) {\n    if (validation.queued) {\n      runRule(validation, node, (result: boolean | Promise<boolean>) => {\n        result instanceof Promise\n          ? result.then((r) => next(true, r))\n          : next(false, result)\n      })\n    } else {\n      // In this case our rule is not queued, so literally nothing happened that\n      // would affect it, we just need to move past this rule and make no\n      // modifications to state\n      run(current + 1, validations, state, removeImmediately, complete)\n    }\n  } else if (empty(node.value) && validation.skipEmpty && state.isPassing) {\n    // This rule is not run because it is empty — the previous rule passed so normally we would run this rule\n    // but in this case we cannot because it is empty. The node being empty is the only condition by which\n    // this rule is not run, so the only dep at this point to the the value of the node.\n    node.observe()\n    node.value\n    next(false, state.isPassing)\n  } else {\n    // This rule is not being run because a previous validation rule is failing and this one is not forced\n    // In this case we should call next validation — a `null` result here explicitly means the rule was not run.\n    next(false, null)\n  }\n}\n\n/**\n * Run a validation rule debounced or not.\n * @param validation - A validation to debounce\n */\nfunction runRule(\n  validation: FormKitValidation,\n  node: FormKitObservedNode,\n  after: (result: boolean | Promise<boolean>) => void\n) {\n  if (validation.debounce) {\n    validation.timer = setTimeout(() => {\n      node.observe()\n      after(validation.rule(node, ...validation.args))\n    }, validation.debounce) as unknown as number\n  } else {\n    node.observe()\n    after(validation.rule(node, ...validation.args))\n  }\n}\n\n/**\n * The messages given to this function have already been set on the node, but\n * any other validation messages on the node that are not included in this\n * stack should be removed because they have been resolved.\n * @param node - The node to operate on.\n * @param messages - A new stack of messages\n */\nfunction removeMessage(validation: FormKitValidation) {\n  const key = `rule_${validation.name}`\n  if (validation.messageObserver) {\n    validation.messageObserver = validation.messageObserver.kill()\n  }\n  if (has(validation.observer.store, key)) {\n    validation.observer.store.remove(key)\n  }\n}\n\n/**\n *\n * @param value - The value that is failing\n * @param validation - The validation object\n */\nfunction createFailedMessage(\n  validation: FormKitValidation,\n  removeImmediately: boolean\n): void {\n  const node = validation.observer\n  if (isKilled(node)) return\n\n  if (!validation.messageObserver) {\n    validation.messageObserver = createObserver(node._node)\n  }\n  validation.messageObserver.watch(\n    (node) => {\n      const i18nArgs: FormKitValidationI18NArgs = createI18nArgs(\n        node,\n        validation\n      )\n      return i18nArgs\n    },\n    (i18nArgs) => {\n      const customMessage = createCustomMessage(node, validation, i18nArgs)\n      // Here we short circuit the i18n system to force the output.\n      const message = /* #__PURE__ */ createMessage({\n        blocking: validation.blocking,\n        key: `rule_${validation.name}`,\n        meta: {\n          /**\n           * Use this key instead of the message root key to produce i18n validation\n           * messages.\n           */\n          messageKey: validation.name,\n          /**\n           * For messages that were created *by or after* a debounced or async\n           * validation rule — we make note of it so we can immediately remove them\n           * as soon as the next commit happens.\n           */\n          removeImmediately,\n          /**\n           * Determines if this message should be passed to localization.\n           */\n          localize: !customMessage,\n          /**\n           * The arguments that will be passed to the validation rules\n           */\n          i18nArgs,\n        },\n        type: 'validation',\n        value: customMessage || 'This field is not valid.',\n      })\n      node.store.set(message)\n    }\n  )\n}\n\n/**\n * Returns a custom validation message if applicable.\n * @param node - FormKit Node\n * @param validation - The validation rule being processed.\n */\nfunction createCustomMessage(\n  node: FormKitNode,\n  validation: FormKitValidation,\n  i18nArgs: FormKitValidationI18NArgs\n): string | undefined {\n  const customMessage =\n    node.props.validationMessages &&\n    has(node.props.validationMessages, validation.name)\n      ? node.props.validationMessages[validation.name]\n      : undefined\n  if (typeof customMessage === 'function') {\n    return customMessage(...i18nArgs)\n  }\n  return customMessage\n}\n\n/**\n * Creates the arguments passed to the i18n\n * @param node - The node that performed the validation\n * @param validation - The validation that failed\n */\nfunction createI18nArgs(\n  node: FormKitNode,\n  validation: FormKitValidation\n): FormKitValidationI18NArgs {\n  // If a custom message has been found, short circuit the i18n system.\n  return [\n    {\n      node,\n      name: createMessageName(node),\n      args: validation.args,\n    },\n  ]\n}\n\n/**\n * Given a node, this returns the name that should be used in validation\n * messages. This is either the `validationLabel` prop, the `label` prop, or\n * the name of the input (in that order).\n * @param node - The node to display\n * @returns\n * @public\n */\nexport function createMessageName(node: FormKitNode): string {\n  if (typeof node.props.validationLabel === 'function') {\n    return node.props.validationLabel(node)\n  }\n  return (\n    node.props.validationLabel ||\n    node.props.label ||\n    node.props.name ||\n    String(node.name)\n  )\n}\n\n/**\n * Describes hints, must also be changed in the debounceExtractor.\n */\nconst hintPattern = '(?:[\\\\*+?()0-9]+)'\n\n/**\n * A pattern to describe rule names. Rules names can only contain letters,\n * numbers, and underscores and must start with a letter.\n */\nconst rulePattern = '[a-zA-Z][a-zA-Z0-9_]+'\n\n/**\n * Regular expression for extracting rule data.\n */\nconst ruleExtractor = new RegExp(\n  `^(${hintPattern}?${rulePattern})(?:\\\\:(.*)+)?$`,\n  'i'\n)\n\n/**\n * Validation hints are special characters preceding a validation rule, like\n * !phone\n */\nconst hintExtractor = new RegExp(`^(${hintPattern})(${rulePattern})$`, 'i')\n\n/**\n * Given a hint string like ^(200)? or ^? or (200)?^ extract the hints to\n * matches.\n */\nconst debounceExtractor = /([\\*+?]+)?(\\(\\d+\\))([\\*+?]+)?/\n\n/**\n * Determines if a given string is in the proper debounce format.\n */\nconst hasDebounce = /\\(\\d+\\)/\n\n/**\n * The default values of the available validation hints.\n */\nexport const defaultHints: FormKitValidationHints = {\n  blocking: true,\n  debounce: 0,\n  force: false,\n  skipEmpty: true,\n  name: '',\n}\n\n/**\n * Parse validation intents and strings into validation rule stacks.\n * @param validation - Either a string a validation rules, or proper array of structured rules.\n * @internal\n */\nexport function parseRules(\n  validation: undefined | string | FormKitValidationIntent[],\n  rules: FormKitValidationRules,\n  node: FormKitNode\n): FormKitValidation[] {\n  if (!validation) return []\n  const intents =\n    typeof validation === 'string'\n      ? extractRules(validation)\n      : clone(validation)\n  return intents.reduce((validations, args) => {\n    let rule = args.shift() as string | FormKitValidationRule\n    const hints = {}\n    if (typeof rule === 'string') {\n      const [ruleName, parsedHints] = parseHints(rule)\n      if (has(rules, ruleName)) {\n        rule = rules[ruleName]\n        Object.assign(hints, parsedHints)\n      }\n    }\n    if (typeof rule === 'function') {\n      validations.push({\n        observer: createObserver(node),\n        rule,\n        args,\n        timer: 0,\n        state: null,\n        queued: true,\n        deps: new Map(),\n        ...defaultHints,\n        ...fnHints(hints, rule),\n      })\n    }\n    return validations\n  }, [] as FormKitValidation[])\n}\n\n/**\n * A string of validation rules written in FormKitRule notation.\n * @param validation - The string of rules\n * @internal\n */\nfunction extractRules(validation: string): FormKitValidationIntent[] {\n  return validation.split('|').reduce((rules, rule) => {\n    const parsedRule = parseRule(rule)\n    if (parsedRule) {\n      rules.push(parsedRule)\n    }\n    return rules\n  }, [] as FormKitValidationIntent[])\n}\n\n/**\n * Given a rule like confirm:password_confirm produce a FormKitValidationIntent\n * @param rule - A string representing a validation rule.\n * @returns\n */\nfunction parseRule(rule: string): FormKitValidationIntent | false {\n  const trimmed = rule.trim()\n  if (trimmed) {\n    const matches = trimmed.match(ruleExtractor)\n    if (matches && typeof matches[1] === 'string') {\n      const ruleName = matches[1].trim()\n      const args =\n        matches[2] && typeof matches[2] === 'string'\n          ? matches[2].split(',').map((s) => s.trim())\n          : []\n      return [ruleName, ...args]\n    }\n  }\n  return false\n}\n\n/**\n * Given a rule name, detect if there are any additional hints like !\n * @param ruleName - string representing a rule name\n * @returns\n */\nfunction parseHints(\n  ruleName: string\n): [string, Partial<FormKitValidationHints>] {\n  const matches = ruleName.match(hintExtractor)\n  if (!matches) {\n    return [ruleName, { name: ruleName }]\n  }\n  const map: { [index: string]: Partial<FormKitValidationHints> } = {\n    '*': { force: true },\n    '+': { skipEmpty: false },\n    '?': { blocking: false },\n  }\n  const [, hints, rule] = matches\n  const hintGroups = hasDebounce.test(hints)\n    ? hints.match(debounceExtractor) || []\n    : [, hints]\n  return [\n    rule,\n    [hintGroups[1], hintGroups[2], hintGroups[3]].reduce(\n      (hints: Partial<FormKitValidationHints>, group: string | undefined) => {\n        if (!group) return hints\n        if (hasDebounce.test(group)) {\n          hints.debounce = parseInt(group.substr(1, group.length - 1))\n        } else {\n          group\n            .split('')\n            .forEach(\n              (hint) => has(map, hint) && Object.assign(hints, map[hint])\n            )\n        }\n        return hints\n      },\n      { name: rule } as Partial<FormKitValidationHints>\n    ),\n  ]\n}\n\n/**\n * Extracts hint properties from the validation rule function itself and applies\n * them if they are not already in the set of validation hints extracted from\n * strings.\n * @param existingHints - An existing set of hints already parsed\n * @param rule - The actual rule function, which can contain hint properties\n * @returns\n */\nfunction fnHints(\n  existingHints: Partial<FormKitValidationHints>,\n  rule: FormKitValidationRule\n) {\n  if (!existingHints.name) {\n    existingHints.name = rule.ruleName || rule.name\n  }\n  return ['skipEmpty', 'force', 'debounce', 'blocking'].reduce(\n    (hints: Partial<FormKitValidationHints>, hint: string) => {\n      if (has(rule, hint) && !has(hints, hint)) {\n        Object.assign(hints, {\n          [hint]: rule[hint as keyof FormKitValidationHints],\n        })\n      }\n      return hints\n    },\n    existingHints\n  )\n}\n\n/**\n * Extracts all validation messages from the given node and all its descendants.\n * This is not reactive and must be re-called each time the messages change.\n * @param node - The FormKit node to extract validation rules from — as well as its descendants.\n * @public\n */\nexport function getValidationMessages(\n  node: FormKitNode\n): Map<FormKitNode, FormKitMessage[]> {\n  const messages: Map<FormKitNode, FormKitMessage[]> = new Map()\n  const extract = (n: FormKitNode) => {\n    const nodeMessages = []\n    for (const key in n.store) {\n      const message = n.store[key]\n      if (\n        message.type === 'validation' &&\n        message.visible &&\n        typeof message.value === 'string'\n      ) {\n        nodeMessages.push(message)\n      }\n    }\n    if (nodeMessages.length) {\n      messages.set(n, nodeMessages)\n    }\n    return n\n  }\n  extract(node).walk(extract)\n  return messages\n}\n"]}