| 1 | import { OtlpHeadersFromString, OtlpProtocol } from "@t3tools/shared/observability"; |
| 2 | import * as Config from "effect/Config"; |
| 3 | import * as ConfigProvider from "effect/ConfigProvider"; |
| 4 | import * as Option from "effect/Option"; |
| 5 | |
| 6 | const trimNonEmptyOption = (value: string): Option.Option<string> => { |
| 7 | const trimmed = value.trim(); |
| 8 | return trimmed.length > 0 ? Option.some(trimmed) : Option.none(); |
| 9 | }; |
| 10 | |
| 11 | const trimmedString = (name: string) => |
| 12 | Config.String(name).pipe(Config.option, Config.map(Option.flatMap(trimNonEmptyOption))); |
| 13 | |
| 14 | const optionalBoolean = (name: string) => |
| 15 | Config.Boolean(name).pipe(Config.option, Config.map(Option.getOrElse(() => false))); |
| 16 | |
| 17 | const commaSeparatedStrings = (name: string) => |
| 18 | trimmedString(name).pipe( |
| 19 | Config.map( |
| 20 | Option.match({ |
| 21 | onNone: () => [], |
| 22 | onSome: (value) => |
| 23 | value |
| 24 | .split(",") |
| 25 | .map((entry) => entry.trim()) |
| 26 | .filter((entry) => entry.length > 0), |
| 27 | }), |
| 28 | ), |
| 29 | ); |
| 30 | |
| 31 | const compactEnv = (env: Readonly<Record<string, string | undefined>>): Record<string, string> => |
| 32 | Object.fromEntries( |
| 33 | Object.entries(env).filter((entry): entry is [string, string] => entry[1] !== undefined), |
| 34 | ); |
| 35 | |
| 36 | export const DesktopConfig = Config.all({ |
| 37 | appDataDirectory: trimmedString("APPDATA"), |
| 38 | xdgConfigHome: trimmedString("XDG_CONFIG_HOME"), |
| 39 | xdgDataHome: trimmedString("XDG_DATA_HOME"), |
| 40 | t3Home: trimmedString("T3CODE_HOME"), |
| 41 | devServerUrl: Config.URL("VITE_DEV_SERVER_URL").pipe(Config.option), |
| 42 | appUserModelIdOverride: trimmedString("T3CODE_DESKTOP_APP_USER_MODEL_ID"), |
| 43 | devRemoteT3ServerEntryPath: trimmedString("T3CODE_DEV_REMOTE_T3_SERVER_ENTRY_PATH"), |
| 44 | configuredBackendPort: Config.Port("T3CODE_PORT").pipe(Config.option), |
| 45 | commitHashOverride: trimmedString("T3CODE_COMMIT_HASH"), |
| 46 | desktopLanHostOverride: trimmedString("T3CODE_DESKTOP_LAN_HOST"), |
| 47 | desktopHttpsEndpointUrls: commaSeparatedStrings("T3CODE_DESKTOP_HTTPS_ENDPOINTS"), |
| 48 | otlpTracesUrl: trimmedString("T3CODE_OTLP_TRACES_URL"), |
| 49 | otlpMetricsUrl: trimmedString("T3CODE_OTLP_METRICS_URL"), |
| 50 | otlpLogsUrl: trimmedString("T3CODE_OTLP_LOGS_URL"), |
| 51 | otlpExportIntervalMs: Config.Int("T3CODE_OTLP_EXPORT_INTERVAL_MS").pipe( |
| 52 | Config.withDefault(10_000), |
| 53 | ), |
| 54 | otlpHeaders: Config.schema(OtlpHeadersFromString, "T3CODE_OTLP_HEADERS").pipe(Config.option), |
| 55 | otlpProtocol: Config.schema(OtlpProtocol, "T3CODE_OTLP_PROTOCOL").pipe( |
| 56 | Config.withDefault("http/json"), |
| 57 | ), |
| 58 | appImagePath: trimmedString("APPIMAGE"), |
| 59 | disableAutoUpdate: optionalBoolean("T3CODE_DISABLE_AUTO_UPDATE"), |
| 60 | mockUpdates: optionalBoolean("T3CODE_DESKTOP_MOCK_UPDATES"), |
| 61 | mockUpdateServerPort: Config.Port("T3CODE_DESKTOP_MOCK_UPDATE_SERVER_PORT").pipe( |
| 62 | Config.withDefault(3000), |
| 63 | ), |
| 64 | }); |
| 65 | |
| 66 | export const layerTest = (env: Readonly<Record<string, string | undefined>>) => |
| 67 | ConfigProvider.layer(ConfigProvider.fromEnv({ env: compactEnv(env) })); |