| 21 | |
| 22 | /** @internal */ |
| 23 | export const makeProvider = (fileName: string, options?: { |
| 24 | readonly formats?: ReadonlyArray<ConfigFile.Kind> |
| 25 | readonly searchPaths?: ReadonlyArray<string> |
| 26 | }): Effect.Effect<ConfigProvider.ConfigProvider, ConfigFile.ConfigFileError, Path.Path | FileSystem.FileSystem> => |
| 27 | Effect.gen(function*() { |
| 28 | const path = yield* Path.Path |
| 29 | const fs = yield* FileSystem.FileSystem |
| 30 | const searchPaths = options?.searchPaths && options.searchPaths.length ? options.searchPaths : ["."] |
| 31 | const extensions = options?.formats && options.formats.length |
| 32 | ? options.formats.flatMap((_) => fileExtensions[_]) |
| 33 | : allFileExtensions |
| 34 | const filePaths = yield* Effect.filter( |
| 35 | searchPaths.flatMap( |
| 36 | (searchPath) => extensions.map((ext) => path.join(searchPath, `${fileName}.${ext}`)) |
| 37 | ), |
| 38 | (path) => Effect.orElseSucceed(fs.exists(path), () => false) |
| 39 | ) |
| 40 | const providers = yield* Effect.forEach(filePaths, (path) => |
| 41 | pipe( |
| 42 | fs.readFileString(path), |
| 43 | Effect.mapError((_) => ConfigFileError(`Could not read file (${path})`)), |
| 44 | Effect.flatMap((content) => |
| 45 | Effect.mapError( |
| 46 | InternalFiles.parse(path, content), |
| 47 | (message) => ConfigFileError(message) |
| 48 | ) |
| 49 | ), |
| 50 | Effect.map((data) => ConfigProvider.fromJson(data)) |
| 51 | )) |
| 52 | |
| 53 | if (providers.length === 0) { |
| 54 | return ConfigProvider.fromMap(new Map()) |
| 55 | } |
| 56 | |
| 57 | return providers.reduce((acc, provider) => ConfigProvider.orElse(acc, () => provider)) |
| 58 | }) |
| 59 | |
| 60 | /** @internal */ |
| 61 | export const layer = (fileName: string, options?: { |