@layerfig/config
Version:
Layer and runtime-validate type-safe configs for JavaScript apps.
1 lines • 6.05 kB
Source Map (JSON)
{"version":3,"file":"source-C9BKBtnS.cjs","names":["#extractSlotName","envVarValue: string | undefined","value","result: ExtractedSlot[]","#safeSlotRegex","fallbackValue: string | undefined","slot: string"],"sources":["../src/sources/source.ts"],"sourcesContent":["import type { ConfigParser } from \"../parser/define-config-parser\";\nimport type { Prettify } from \"../types\";\n\ninterface RuntimeEnv {\n\t[key: string]: string | undefined;\n}\n\nexport interface LoadSourceOptions {\n\tparser: ConfigParser;\n\trelativeConfigFolderPath: string;\n\truntimeEnv: RuntimeEnv;\n\tslotPrefix: string;\n}\n\ninterface MaybeReplaceSlotFromValueOptions\n\textends Pick<LoadSourceOptions, \"runtimeEnv\" | \"slotPrefix\"> {\n\tvalue: string;\n}\n\ninterface ExtractedSlot {\n\tslotPattern: RegExp;\n\tenvVarName: string[];\n\tvalue: string;\n\tfallback?: string;\n}\n\nexport abstract class Source<T = Record<string, unknown>> {\n\t/**\n\t * An abstract method that must be implemented by any subclass.\n\t * It defines the contract for loading a source.\n\t * @param loadSourceOptions - The options for loading the source.\n\t * @returns A record representing the loaded source data.\n\t */\n\tabstract loadSource(loadSourceOptions: LoadSourceOptions): Prettify<T>;\n\n\tmaybeReplaceSlotFromValue({\n\t\tvalue,\n\t\tslotPrefix,\n\t\truntimeEnv,\n\t}: MaybeReplaceSlotFromValueOptions): string {\n\t\tconst slots = this.#extractSlotName({\n\t\t\tslotPrefix,\n\t\t\tvalue,\n\t\t});\n\n\t\tif (slots === null) {\n\t\t\treturn value;\n\t\t}\n\n\t\tlet newValue = value;\n\n\t\tfor (const slot of slots) {\n\t\t\tlet envVarValue: string | undefined;\n\n\t\t\tfor (const envVar of slot.envVarName) {\n\t\t\t\tconst value = runtimeEnv[envVar];\n\n\t\t\t\tif (value) {\n\t\t\t\t\tenvVarValue = value;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tenvVarValue ??= slot.fallback;\n\n\t\t\tif (envVarValue) {\n\t\t\t\tnewValue = newValue.replace(slot.slotPattern, envVarValue);\n\t\t\t} else {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t\"[SLOT_REPLACEMENT]\",\n\t\t\t\t\t`The value for the slot \"${slot.envVarName}\" is not defined in the runtime environment. The slot will not be replaced.`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn newValue;\n\t}\n\n\t#extractSlotName({\n\t\tslotPrefix,\n\t\tvalue,\n\t}: Pick<MaybeReplaceSlotFromValueOptions, \"value\" | \"slotPrefix\">):\n\t\t| ExtractedSlot[]\n\t\t| null {\n\t\t/**\n\t\t * Something like: /\\$\\w+/g\n\t\t * To match basic slots like $MY_VAR\n\t\t */\n\t\tconst basicSlotRegex = new RegExp(`\\\\${slotPrefix}\\\\w+`, \"g\");\n\t\t/**\n\t\t * Something like: /\\$\\{.*\\}/g\n\t\t * To match multi-slot patterns like ${MY_VAR:MY_OTHER_VAR}\n\t\t */\n\t\tconst multiSlotRegex = new RegExp(`\\\\${slotPrefix}{.*}`, \"g\");\n\n\t\tconst basicMatches = value.match(basicSlotRegex);\n\t\tconst multiMatches = value.match(multiSlotRegex);\n\n\t\tif (!basicMatches && !multiMatches) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst result: ExtractedSlot[] = [];\n\n\t\tif (basicMatches) {\n\t\t\tconst uniqueSlots = new Set(basicMatches);\n\n\t\t\tresult.push(\n\t\t\t\t...Array.from(uniqueSlots).map((slotMatch) => ({\n\t\t\t\t\tenvVarName: [slotMatch.replace(slotPrefix, \"\")],\n\t\t\t\t\tslotPattern: this.#safeSlotRegex(slotMatch),\n\t\t\t\t\tvalue,\n\t\t\t\t})),\n\t\t\t);\n\t\t}\n\n\t\tif (multiMatches) {\n\t\t\tconst possibleEnvVarSlots = new Set(multiMatches);\n\n\t\t\tfor (const possibleSlot of possibleEnvVarSlots) {\n\t\t\t\tlet fallbackValue: string | undefined;\n\n\t\t\t\tconst values = possibleSlot\n\t\t\t\t\t.replace(`${slotPrefix}{`, \"\")\n\t\t\t\t\t.replace(\"}\", \"\")\n\t\t\t\t\t.split(\":\");\n\n\t\t\t\t// If the last value contains a hyphen, it is considered a fallback value\n\t\t\t\tif (values[values.length - 1]?.includes(\"-\")) {\n\t\t\t\t\tfallbackValue = values.pop()?.trim().replace(\"-\", \"\");\n\t\t\t\t}\n\n\t\t\t\tresult.push({\n\t\t\t\t\tenvVarName: values,\n\t\t\t\t\tslotPattern: this.#safeSlotRegex(possibleSlot),\n\t\t\t\t\tvalue,\n\t\t\t\t\tfallback: fallbackValue,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t#safeSlotRegex(slot: string) {\n\t\t/**\n\t\t * Escape the first character to ensure it is treated literally in the regex\n\t\t * This is necessary because the first character could be a special regex character\n\t\t * such as $, ^, or \\, which would otherwise be interpreted by the regex engine.\n\t\t * For example, if the slot is \"$MY_VAR\", we want to match it literally as \"\\$MY_VAR\".\n\t\t * This ensures that the regex will match the slot name exactly as it appears in the string.\n\t\t */\n\t\tconst safe = slot.replace(/^./, (m) => `\\\\${m}`);\n\t\treturn new RegExp(safe, \"gm\");\n\t}\n}\n"],"mappings":";;AA0BA,IAAsB,SAAtB,MAA0D;CASzD,0BAA0B,EACzB,OACA,YACA,YACkC,EAAU;EAC5C,MAAM,QAAQ,KAAKA,iBAAiB;GACnC;GACA;EACA,EAAC;AAEF,MAAI,UAAU,KACb,QAAO;EAGR,IAAI,WAAW;AAEf,OAAK,MAAM,QAAQ,OAAO;GACzB,IAAIC;AAEJ,QAAK,MAAM,UAAU,KAAK,YAAY;IACrC,MAAMC,UAAQ,WAAW;AAEzB,QAAIA,SAAO;AACV,mBAAcA;AACd;IACA;GACD;AAED,mBAAgB,KAAK;AAErB,OAAI,YACH,YAAW,SAAS,QAAQ,KAAK,aAAa,YAAY;OAE1D,SAAQ,KACP,uBACC,0BAA0B,KAAK,WAAW,6EAC3C;EAEF;AAED,SAAO;CACP;CAED,iBAAiB,EAChB,YACA,OACgE,EAEzD;;;;;EAKP,MAAM,iBAAiB,IAAI,QAAQ,IAAI,WAAW,OAAO;;;;;EAKzD,MAAM,iBAAiB,IAAI,QAAQ,IAAI,WAAW,OAAO;EAEzD,MAAM,eAAe,MAAM,MAAM,eAAe;EAChD,MAAM,eAAe,MAAM,MAAM,eAAe;AAEhD,OAAK,iBAAiB,aACrB,QAAO;EAGR,MAAMC,SAA0B,CAAE;AAElC,MAAI,cAAc;GACjB,MAAM,cAAc,IAAI,IAAI;AAE5B,UAAO,KACN,GAAG,MAAM,KAAK,YAAY,CAAC,IAAI,CAAC,eAAe;IAC9C,YAAY,CAAC,UAAU,QAAQ,YAAY,GAAG,AAAC;IAC/C,aAAa,KAAKC,eAAe,UAAU;IAC3C;GACA,GAAE,CACH;EACD;AAED,MAAI,cAAc;GACjB,MAAM,sBAAsB,IAAI,IAAI;AAEpC,QAAK,MAAM,gBAAgB,qBAAqB;IAC/C,IAAIC;IAEJ,MAAM,SAAS,aACb,SAAS,EAAE,WAAW,IAAI,GAAG,CAC7B,QAAQ,KAAK,GAAG,CAChB,MAAM,IAAI;AAGZ,QAAI,OAAO,OAAO,SAAS,IAAI,SAAS,IAAI,CAC3C,iBAAgB,OAAO,KAAK,EAAE,MAAM,CAAC,QAAQ,KAAK,GAAG;AAGtD,WAAO,KAAK;KACX,YAAY;KACZ,aAAa,KAAKD,eAAe,aAAa;KAC9C;KACA,UAAU;IACV,EAAC;GACF;EACD;AAED,SAAO;CACP;CAED,eAAeE,MAAc;;;;;;;;EAQ5B,MAAM,OAAO,KAAK,QAAQ,MAAM,CAAC,OAAO,IAAI,EAAE,EAAE;AAChD,SAAO,IAAI,OAAO,MAAM;CACxB;AACD"}