{"version":3,"file":"filterInvalidDictionaries.cjs","names":["formatPath","ANSIColors","formatLocale","x"],"sources":["../../src/filterInvalidDictionaries.ts"],"sourcesContent":["import * as ANSIColors from '@intlayer/config/colors';\nimport {\n  colorize,\n  colorizeKey,\n  colorizePath,\n  getAppLogger,\n  x,\n} from '@intlayer/config/logger';\nimport { getBasePlugins, getContent } from '@intlayer/core/interpreter';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { formatLocale, formatPath } from './utils/formatter';\n\ntype IsInvalidDictionaryOptions = { checkSchema: boolean };\n\nexport const isInvalidDictionary = (\n  dictionary: Dictionary | undefined,\n  configuration?: IntlayerConfig,\n  options?: IsInvalidDictionaryOptions\n): boolean => {\n  const appLogger = getAppLogger(configuration);\n\n  if (!dictionary) return false;\n\n  const isLocal = Boolean(\n    dictionary.location === 'local' || typeof dictionary.filePath === 'string'\n  );\n  const location = isLocal ? 'Local' : 'Remote';\n  const hasKey = Boolean(dictionary.key);\n  const hasContent = Boolean(dictionary.content);\n\n  if (!hasKey) {\n    appLogger(`${location} dictionary has no key`, {\n      level: 'error',\n    });\n\n    return false;\n  }\n\n  // Reject keys that contain path-unsafe characters.\n  // A key is used as a filename component ({key}.json), so slashes, backslashes,\n  // null bytes, or pure dot-segments can escape the output directory or break\n  // dictionary resolution.\n  // Allows alphanumeric characters, dashes, and underscores.\n  // Allows dots, but not as the first or last character, and no consecutive dots.\n  // Allows chinese or russian characters e.g. 你好\n  const isInsecureKey = !/^[\\p{L}\\p{N}]+([._-][\\p{L}\\p{N}]+)*$/u.test(\n    dictionary.key\n  );\n\n  if (isInsecureKey) {\n    appLogger(\n      `Insecure key ${colorizeKey(dictionary.key)} at ${dictionary.filePath ? formatPath(dictionary.filePath) : colorizePath('Remote')} - dictionary filtered out`,\n      { level: 'error' }\n    );\n    return false;\n  }\n\n  if (!hasContent) {\n    appLogger(\n      `${location} dictionary ${colorizeKey(dictionary.key)} has no content - ${dictionary.filePath ? formatPath(dictionary.filePath) : colorizePath('Remote')}`,\n      {\n        level: 'error',\n      }\n    );\n    return false;\n  }\n\n  if (dictionary.schema && options?.checkSchema) {\n    const isAsync =\n      typeof dictionary.content === 'function' ||\n      (typeof dictionary.content === 'object' &&\n        dictionary.content !== null &&\n        typeof (dictionary.content as any).then === 'function');\n\n    if (!isAsync) {\n      const locales = configuration?.internationalization?.locales ?? [];\n      const isStrict =\n        configuration?.internationalization.strictMode === 'strict';\n\n      const schema =\n        typeof dictionary.schema === 'string'\n          ? configuration?.schemas?.[dictionary.schema]\n          : undefined;\n\n      if (schema && typeof schema.safeParse === 'function') {\n        for (const locale of locales) {\n          const resolvedContent = getContent(\n            dictionary.content,\n            {\n              dictionaryKey: dictionary.key,\n              keyPath: [],\n              locale,\n            },\n            getBasePlugins(locale, !isStrict)\n          );\n          const result = (schema as any).safeParse(resolvedContent);\n\n          if (!result.success) {\n            appLogger(\n              `${location} dictionary ${colorizeKey(dictionary.key)} has invalid content according to schema ${colorize(dictionary.schema as string, ANSIColors.ORANGE)} for locale ${formatLocale(locale)} - ${dictionary.filePath ? formatPath(dictionary.filePath) : colorizePath('Remote')}`,\n              {\n                level: 'error',\n              }\n            );\n\n            result.error.issues.forEach((issue: any) => {\n              appLogger(\n                `${x} Error: ${colorizeKey(dictionary.key)} - ${formatLocale(locale)} - ${colorize(`${issue.path.join('.')}:`, ANSIColors.BLUE)} ${colorize(issue.message, ANSIColors.GREY)}`,\n                {\n                  level: 'error',\n                }\n              );\n            });\n\n            return false;\n          }\n        }\n      }\n    }\n  }\n\n  return true;\n};\n\nexport const filterInvalidDictionaries = (\n  dictionaries: (Dictionary | undefined)[] | undefined,\n  configuration: IntlayerConfig,\n  options?: IsInvalidDictionaryOptions\n): Dictionary[] =>\n  (dictionaries ?? [])?.filter((dictionary) =>\n    isInvalidDictionary(dictionary, configuration, options)\n  ) as Dictionary[];\n"],"mappings":";;;;;;;;;AAeA,MAAa,uBACX,YACA,eACA,YACY;CACZ,MAAM,sDAAyB,aAAa;CAE5C,IAAI,CAAC,YAAY,OAAO;CAKxB,MAAM,WAHU,QACd,WAAW,aAAa,WAAW,OAAO,WAAW,aAAa,QAE7C,IAAI,UAAU;CACrC,MAAM,SAAS,QAAQ,WAAW,GAAG;CACrC,MAAM,aAAa,QAAQ,WAAW,OAAO;CAE7C,IAAI,CAAC,QAAQ;EACX,UAAU,GAAG,SAAS,yBAAyB,EAC7C,OAAO,QACT,CAAC;EAED,OAAO;CACT;CAaA,IAAI,CAJmB,wCAAwC,KAC7D,WAAW,GACb,GAEmB;EACjB,UACE,yDAA4B,WAAW,GAAG,EAAE,MAAM,WAAW,WAAWA,mCAAW,WAAW,QAAQ,8CAAiB,QAAQ,EAAE,6BACjI,EAAE,OAAO,QAAQ,CACnB;EACA,OAAO;CACT;CAEA,IAAI,CAAC,YAAY;EACf,UACE,GAAG,SAAS,uDAA0B,WAAW,GAAG,EAAE,oBAAoB,WAAW,WAAWA,mCAAW,WAAW,QAAQ,8CAAiB,QAAQ,KACvJ,EACE,OAAO,QACT,CACF;EACA,OAAO;CACT;CAEA,IAAI,WAAW,UAAU,SAAS,aAOhC;MAAI,EALF,OAAO,WAAW,YAAY,cAC7B,OAAO,WAAW,YAAY,YAC7B,WAAW,YAAY,QACvB,OAAQ,WAAW,QAAgB,SAAS,aAElC;GACZ,MAAM,UAAU,eAAe,sBAAsB,WAAW,CAAC;GACjE,MAAM,WACJ,eAAe,qBAAqB,eAAe;GAErD,MAAM,SACJ,OAAO,WAAW,WAAW,WACzB,eAAe,UAAU,WAAW,UACpC;GAEN,IAAI,UAAU,OAAO,OAAO,cAAc,YACxC,KAAK,MAAM,UAAU,SAAS;IAC5B,MAAM,6DACJ,WAAW,SACX;KACE,eAAe,WAAW;KAC1B,SAAS,CAAC;KACV;IACF,kDACe,QAAQ,CAAC,QAAQ,CAClC;IACA,MAAM,SAAU,OAAe,UAAU,eAAe;IAExD,IAAI,CAAC,OAAO,SAAS;KACnB,UACE,GAAG,SAAS,uDAA0B,WAAW,GAAG,EAAE,iFAAoD,WAAW,QAAkBC,wBAAW,MAAM,EAAE,cAAcC,qCAAa,MAAM,EAAE,KAAK,WAAW,WAAWF,mCAAW,WAAW,QAAQ,8CAAiB,QAAQ,KAC/Q,EACE,OAAO,QACT,CACF;KAEA,OAAO,MAAM,OAAO,SAAS,UAAe;MAC1C,UACE,GAAGG,0BAAE,mDAAsB,WAAW,GAAG,EAAE,KAAKD,qCAAa,MAAM,EAAE,2CAAc,GAAG,MAAM,KAAK,KAAK,GAAG,EAAE,IAAID,wBAAW,IAAI,EAAE,yCAAY,MAAM,SAASA,wBAAW,IAAI,KAC1K,EACE,OAAO,QACT,CACF;KACF,CAAC;KAED,OAAO;IACT;GACF;EAEJ;;CAGF,OAAO;AACT;AAEA,MAAa,6BACX,cACA,eACA,aAEC,gBAAgB,CAAC,IAAI,QAAQ,eAC5B,oBAAoB,YAAY,eAAe,OAAO,CACxD"}