{"version":3,"file":"pattern.mjs","names":[],"sources":["../../../../../../../react-form/src/rules/pattern.ts"],"sourcesContent":["import { trans } from \"@mongez/localization\";\nimport { InputRule } from \"../types\";\n\n// Defense-in-depth caps: validation patterns/values may end up sourced from\n// server/CMS-driven config, so an unbounded pattern or input is a ReDoS risk.\nconst MAX_PATTERN_LENGTH = 200;\nconst MAX_VALUE_LENGTH = 2000;\n\nconst regexCache = new Map<string, RegExp | null>();\n\nfunction compilePattern(pattern: string | RegExp): RegExp | null {\n  const isString = typeof pattern === \"string\";\n  const source = isString ? pattern : pattern.source;\n  const flags = isString ? \"\" : pattern.flags;\n  const cacheKey = `${flags}::${source}`;\n\n  if (regexCache.has(cacheKey)) {\n    return regexCache.get(cacheKey) as RegExp | null;\n  }\n\n  let compiled: RegExp | null = null;\n\n  if (source.length <= MAX_PATTERN_LENGTH) {\n    try {\n      compiled = isString ? new RegExp(pattern) : pattern;\n    } catch {\n      compiled = null;\n    }\n  }\n\n  regexCache.set(cacheKey, compiled);\n\n  return compiled;\n}\n\nexport const patternRule: InputRule = {\n  name: \"pattern\",\n  preservedProps: [\"pattern\"],\n  validate: ({ value, pattern, errorKeys }) => {\n    if (!pattern) return;\n\n    const regex = compilePattern(pattern);\n\n    // An invalid or oversized pattern source is a config problem, not the\n    // user's fault — fail safe by skipping validation rather than blocking\n    // every submission.\n    if (!regex) return;\n\n    // A value longer than the cap is overwhelmingly more likely invalid than\n    // valid — fail closed instead of truncating, which would let an anchored\n    // pattern (e.g. `^[0-9a-f]+$`) pass on a valid prefix with an arbitrary tail.\n    if (typeof value === \"string\" && value.length > MAX_VALUE_LENGTH) {\n      return trans(\"validation.pattern\", {\n        input: errorKeys.name,\n        pattern: errorKeys.pattern || \"pattern\",\n      });\n    }\n\n    if (!regex.test(value)) {\n      return trans(\"validation.pattern\", {\n        input: errorKeys.name,\n        pattern: errorKeys.pattern || \"pattern\",\n      });\n    }\n  },\n};\n"],"mappings":";;;AAKA,MAAM,qBAAqB;AAC3B,MAAM,mBAAmB;AAEzB,MAAM,6BAAa,IAAI,IAA2B;AAElD,SAAS,eAAe,SAAyC;CAC/D,MAAM,WAAW,OAAO,YAAY;CACpC,MAAM,SAAS,WAAW,UAAU,QAAQ;CAE5C,MAAM,WAAW,GADH,WAAW,KAAK,QAAQ,MACZ,IAAI;CAE9B,IAAI,WAAW,IAAI,QAAQ,GACzB,OAAO,WAAW,IAAI,QAAQ;CAGhC,IAAI,WAA0B;CAE9B,IAAI,OAAO,UAAU,oBACnB,IAAI;EACF,WAAW,WAAW,IAAI,OAAO,OAAO,IAAI;CAC9C,QAAQ;EACN,WAAW;CACb;CAGF,WAAW,IAAI,UAAU,QAAQ;CAEjC,OAAO;AACT;AAEA,MAAa,cAAyB;CACpC,MAAM;CACN,gBAAgB,CAAC,SAAS;CAC1B,WAAW,EAAE,OAAO,SAAS,gBAAgB;EAC3C,IAAI,CAAC,SAAS;EAEd,MAAM,QAAQ,eAAe,OAAO;EAKpC,IAAI,CAAC,OAAO;EAKZ,IAAI,OAAO,UAAU,YAAY,MAAM,SAAS,kBAC9C,OAAO,MAAM,sBAAsB;GACjC,OAAO,UAAU;GACjB,SAAS,UAAU,WAAW;EAChC,CAAC;EAGH,IAAI,CAAC,MAAM,KAAK,KAAK,GACnB,OAAO,MAAM,sBAAsB;GACjC,OAAO,UAAU;GACjB,SAAS,UAAU,WAAW;EAChC,CAAC;CAEL;AACF"}