{"version":3,"file":"config.mjs","names":["constants"],"sources":["../../../../src/libs/email/storage/config.ts"],"sourcesContent":["import constants from \"../../../constants/constants.js\";\nimport type { ServiceResponse } from \"../../../utils/services/types.js\";\nimport { copy } from \"../../i18n/index.js\";\nimport { isRecord } from \"./paths.js\";\nimport type {\n\tEmailStorageConfig,\n\tEmailStoragePathSegment,\n\tEmailStorageRule,\n\tParsedEmailStorageRule,\n} from \"./types.js\";\n\n/**\n * Parses a storage selector into path segments used by the storage transforms.\n */\nexport const parseEmailStorageSelector = (\n\tselector: string,\n): Awaited<ServiceResponse<EmailStoragePathSegment[]>> => {\n\tconst segments: EmailStoragePathSegment[] = [];\n\tlet index = 0;\n\n\twhile (index < selector.length) {\n\t\tif (selector[index] === \".\") {\n\t\t\treturn {\n\t\t\t\terror: {\n\t\t\t\t\ttype: \"validation\",\n\t\t\t\t\tstatus: 400,\n\t\t\t\t\tmessage: copy(\"server:core.email.storage.invalid.selector\", {\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tselector,\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t\tdata: undefined,\n\t\t\t};\n\t\t}\n\n\t\tlet key = \"\";\n\t\twhile (\n\t\t\tindex < selector.length &&\n\t\t\tselector[index] !== \".\" &&\n\t\t\tselector[index] !== \"[\"\n\t\t) {\n\t\t\tif (selector[index] === \"]\") {\n\t\t\t\treturn {\n\t\t\t\t\terror: {\n\t\t\t\t\t\ttype: \"validation\",\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\tmessage: copy(\"server:core.email.storage.invalid.selector\", {\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tselector,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t},\n\t\t\t\t\tdata: undefined,\n\t\t\t\t};\n\t\t\t}\n\t\t\tkey += selector[index];\n\t\t\tindex++;\n\t\t}\n\n\t\tif (key.length > 0) {\n\t\t\tsegments.push({\n\t\t\t\ttype: \"key\",\n\t\t\t\tkey,\n\t\t\t});\n\t\t}\n\n\t\twhile (index < selector.length && selector[index] === \"[\") {\n\t\t\tconst closeIndex = selector.indexOf(\"]\", index);\n\t\t\tif (closeIndex === -1) {\n\t\t\t\treturn {\n\t\t\t\t\terror: {\n\t\t\t\t\t\ttype: \"validation\",\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\tmessage: copy(\"server:core.email.storage.invalid.selector\", {\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tselector,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t},\n\t\t\t\t\tdata: undefined,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst content = selector.slice(index + 1, closeIndex);\n\t\t\tif (content === \"*\") {\n\t\t\t\tsegments.push({ type: \"wildcard\" });\n\t\t\t} else if (/^\\d+$/.test(content)) {\n\t\t\t\tsegments.push({\n\t\t\t\t\ttype: \"index\",\n\t\t\t\t\tindex: Number.parseInt(content, 10),\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\treturn {\n\t\t\t\t\terror: {\n\t\t\t\t\t\ttype: \"validation\",\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\tmessage: copy(\"server:core.email.storage.invalid.selector\", {\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tselector,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t},\n\t\t\t\t\tdata: undefined,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tindex = closeIndex + 1;\n\t\t}\n\n\t\tif (index < selector.length) {\n\t\t\tif (selector[index] !== \".\") {\n\t\t\t\treturn {\n\t\t\t\t\terror: {\n\t\t\t\t\t\ttype: \"validation\",\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\tmessage: copy(\"server:core.email.storage.invalid.selector\", {\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tselector,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t},\n\t\t\t\t\tdata: undefined,\n\t\t\t\t};\n\t\t\t}\n\t\t\tindex++;\n\t\t\tif (index >= selector.length) {\n\t\t\t\treturn {\n\t\t\t\t\terror: {\n\t\t\t\t\t\ttype: \"validation\",\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\tmessage: copy(\"server:core.email.storage.invalid.selector\", {\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tselector,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t},\n\t\t\t\t\tdata: undefined,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\tif (segments.length === 0) {\n\t\treturn {\n\t\t\terror: {\n\t\t\t\ttype: \"validation\",\n\t\t\t\tstatus: 400,\n\t\t\t\tmessage: copy(\"server:core.email.storage.invalid.selector\", {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tselector,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t},\n\t\t\tdata: undefined,\n\t\t};\n\t}\n\n\treturn {\n\t\terror: undefined,\n\t\tdata: segments,\n\t};\n};\n\nconst normalizeEmailStorageRule = (\n\tselector: string,\n\tvalue: unknown,\n): Awaited<ServiceResponse<EmailStorageRule>> => {\n\tif (!isRecord(value)) {\n\t\treturn {\n\t\t\terror: {\n\t\t\t\ttype: \"validation\",\n\t\t\t\tstatus: 400,\n\t\t\t\tmessage: copy(\"server:core.email.storage.rule.must.be.object\", {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tselector,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t},\n\t\t\tdata: undefined,\n\t\t};\n\t}\n\n\tconst encryptValue = value.encrypt;\n\tconst redactValue = value.redact;\n\tconst neverStoreValue = value.neverStore;\n\n\tif (encryptValue !== undefined && encryptValue !== true) {\n\t\treturn {\n\t\t\terror: {\n\t\t\t\ttype: \"validation\",\n\t\t\t\tstatus: 400,\n\t\t\t\tmessage: copy(\"server:core.email.storage.rule.flag.true\", {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tselector,\n\t\t\t\t\t\tflag: \"encrypt\",\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t},\n\t\t\tdata: undefined,\n\t\t};\n\t}\n\n\tif (redactValue !== undefined && redactValue !== true) {\n\t\treturn {\n\t\t\terror: {\n\t\t\t\ttype: \"validation\",\n\t\t\t\tstatus: 400,\n\t\t\t\tmessage: copy(\"server:core.email.storage.rule.flag.true\", {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tselector,\n\t\t\t\t\t\tflag: \"redact\",\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t},\n\t\t\tdata: undefined,\n\t\t};\n\t}\n\n\tif (neverStoreValue !== undefined && neverStoreValue !== true) {\n\t\treturn {\n\t\t\terror: {\n\t\t\t\ttype: \"validation\",\n\t\t\t\tstatus: 400,\n\t\t\t\tmessage: copy(\"server:core.email.storage.rule.flag.true\", {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tselector,\n\t\t\t\t\t\tflag: \"neverStore\",\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t},\n\t\t\tdata: undefined,\n\t\t};\n\t}\n\n\tconst encryptRule = encryptValue === true;\n\tconst redactRule = redactValue === true;\n\tconst neverStoreRule = neverStoreValue === true;\n\n\tif (!encryptRule && !redactRule && !neverStoreRule) {\n\t\treturn {\n\t\t\terror: {\n\t\t\t\ttype: \"validation\",\n\t\t\t\tstatus: 400,\n\t\t\t\tmessage: copy(\"server:core.email.storage.rule.requires.flag\", {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tselector,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t},\n\t\t\tdata: undefined,\n\t\t};\n\t}\n\n\tif (neverStoreRule && (encryptRule || redactRule)) {\n\t\treturn {\n\t\t\terror: {\n\t\t\t\ttype: \"validation\",\n\t\t\t\tstatus: 400,\n\t\t\t\tmessage: copy(\"server:core.email.storage.rule.never.store.exclusive\", {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tselector,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t},\n\t\t\tdata: undefined,\n\t\t};\n\t}\n\n\tconst fallback =\n\t\t\"previewFallback\" in value\n\t\t\t? { previewFallback: value.previewFallback }\n\t\t\t: redactRule || neverStoreRule\n\t\t\t\t? { previewFallback: constants.email.storage.defaultPreviewFallback }\n\t\t\t\t: {};\n\n\tif (neverStoreRule) {\n\t\treturn {\n\t\t\terror: undefined,\n\t\t\tdata: {\n\t\t\t\tneverStore: true,\n\t\t\t\t...fallback,\n\t\t\t},\n\t\t};\n\t}\n\n\treturn {\n\t\terror: undefined,\n\t\tdata: {\n\t\t\t...(encryptRule ? { encrypt: true } : {}),\n\t\t\t...(redactRule ? { redact: true } : {}),\n\t\t\t...fallback,\n\t\t} as EmailStorageRule,\n\t};\n};\n\n/**\n * Validates caller storage config so the persisted strategy is deterministic.\n */\nexport const normalizeEmailStorageConfig = (\n\tstorage?: EmailStorageConfig | null,\n): Awaited<ServiceResponse<EmailStorageConfig | null>> => {\n\tif (storage === undefined || storage === null) {\n\t\treturn {\n\t\t\terror: undefined,\n\t\t\tdata: null,\n\t\t};\n\t}\n\n\tconst normalized: EmailStorageConfig = {};\n\n\tfor (const [selector, rule] of Object.entries(storage)) {\n\t\tconst selectorRes = parseEmailStorageSelector(selector);\n\t\tif (selectorRes.error) return selectorRes;\n\n\t\tconst ruleRes = normalizeEmailStorageRule(selector, rule);\n\t\tif (ruleRes.error) return ruleRes;\n\n\t\tnormalized[selector] = ruleRes.data;\n\t}\n\n\treturn {\n\t\terror: undefined,\n\t\tdata: Object.keys(normalized).length > 0 ? normalized : null,\n\t};\n};\n\nconst getEmailStorageSpecificity = (segments: EmailStoragePathSegment[]) =>\n\tsegments.reduce((total, segment) => {\n\t\tif (segment.type === \"wildcard\") return total + 1;\n\t\treturn total + 2;\n\t}, 0);\n\n/**\n * Converts normalized config entries into parsed rules for path transforms.\n */\nexport const parseEmailStorageRules = (\n\tstorage?: EmailStorageConfig | null,\n): Awaited<ServiceResponse<ParsedEmailStorageRule[]>> => {\n\tconst normalizedRes = normalizeEmailStorageConfig(storage);\n\tif (normalizedRes.error) return normalizedRes;\n\tif (!normalizedRes.data) {\n\t\treturn {\n\t\t\terror: undefined,\n\t\t\tdata: [],\n\t\t};\n\t}\n\n\tconst rules: ParsedEmailStorageRule[] = [];\n\n\tfor (const [selector, rule] of Object.entries(normalizedRes.data)) {\n\t\tconst selectorRes = parseEmailStorageSelector(selector);\n\t\tif (selectorRes.error) return selectorRes;\n\n\t\trules.push({\n\t\t\tselector,\n\t\t\trule,\n\t\t\tsegments: selectorRes.data,\n\t\t\tindex: rules.length,\n\t\t\tspecificity: getEmailStorageSpecificity(selectorRes.data),\n\t\t});\n\t}\n\n\treturn {\n\t\terror: undefined,\n\t\tdata: rules,\n\t};\n};\n"],"mappings":"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"}