Skip to content

Commit 6eb8da9

Browse files
committed
[Experimental] Generic file providers
1 parent 9d5e407 commit 6eb8da9

38 files changed

+940
-1428
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ var traits: Set<Trait> = [
2929
.trait(
3030
name: "ReloadingSupport",
3131
description:
32-
"Adds support for reloading built-in provider variants, such as ReloadingJSONProvider and ReloadingYAMLProvider (when their respective traits are enabled).",
32+
"Adds support for reloading built-in provider variants, such as ReloadingFileProvider.",
3333
enabledTraits: [
3434
"LoggingSupport"
3535
]

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ The example code below creates the two relevant providers, and resolves them in
4343
```swift
4444
let config = ConfigReader(providers: [
4545
EnvironmentVariablesProvider(),
46-
try await JSONProvider(filePath: "/etc/config.json")
46+
try await FileProvider<JSONSnapshot>(filePath: "/etc/config.json")
4747
])
4848
let httpTimeout = config.int(forKey: "http.timeout", default: 60)
4949
print(httpTimeout) // prints 15
@@ -100,11 +100,11 @@ To enable an additional trait on the package, update the package dependency:
100100
```
101101

102102
Available traits:
103-
- **`JSONSupport`** (default): Adds support for `JSONProvider`, a `ConfigProvider` for reading JSON files.
103+
- **`JSONSupport`** (default): Adds support for `FileProvider<JSONSnapshot>`, a `ConfigProvider` for reading JSON files.
104104
- **`LoggingSupport`** (opt-in): Adds support for `AccessLogger`, a way to emit access events into a `SwiftLog.Logger`.
105-
- **`ReloadingSupport`** (opt-in): Adds support for auto-reloading variants of file providers, such as `ReloadingJSONProvider` (when `JSONSupport` is enabled) and `ReloadingYAMLProvider` (when `YAMLSupport` is enabled).
105+
- **`ReloadingSupport`** (opt-in): Adds support for auto-reloading variants of file providers, such as `ReloadingFileProvider<JSONSnapshot>` (when `JSONSupport` is enabled) and `ReloadingFileProvider<YAMLSnapshot>` (when `YAMLSupport` is enabled).
106106
- **`CommandLineArgumentsSupport`** (opt-in): Adds support for `CommandLineArgumentsProvider` for parsing command line arguments.
107-
- **`YAMLSupport`** (opt-in): Adds support for `YAMLProvider`, a `ConfigProvider` for reading YAML files.
107+
- **`YAMLSupport`** (opt-in): Adds support for `FileProvider<YAMLSnapshot>`, a `ConfigProvider` for reading YAML files.
108108

109109
## Supported platforms and minimum versions
110110

@@ -120,8 +120,8 @@ The library includes comprehensive built-in provider support:
120120

121121
- Environment variables: [`EnvironmentVariablesProvider`](https://swiftpackageindex.com/apple/swift-configuration/documentation/configuration/environmentvariablesprovider)
122122
- Command-line arguments: [`CommandLineArgumentsProvider`](https://swiftpackageindex.com/apple/swift-configuration/documentation/configuration/commandlineargumentsprovider)
123-
- JSON file: [`JSONProvider`](https://swiftpackageindex.com/apple/swift-configuration/documentation/configuration/jsonprovider) and [`ReloadingJSONProvider`](https://swiftpackageindex.com/apple/swift-configuration/documentation/configuration/reloadingjsonprovider)
124-
- YAML file: [`YAMLProvider`](https://swiftpackageindex.com/apple/swift-configuration/documentation/configuration/yamlprovider) and [`ReloadingYAMLProvider`](https://swiftpackageindex.com/apple/swift-configuration/documentation/configuration/reloadingyamlprovider)
123+
- JSON file: [`FileProvider<JSONSnapshot>`](https://swiftpackageindex.com/apple/swift-configuration/documentation/configuration/fileprovider) and [`ReloadingFileProvider<JSONSnapshot>`](https://swiftpackageindex.com/apple/swift-configuration/documentation/configuration/reloadingfileprovider)
124+
- YAML file: [`FileProvider<YAMLSnapshot>`](https://swiftpackageindex.com/apple/swift-configuration/documentation/configuration/fileprovider) and [`ReloadingFileProvider<YAMLSnapshot>`](https://swiftpackageindex.com/apple/swift-configuration/documentation/configuration/reloadingfileprovider)
125125
- Directory of files: [`DirectoryFilesProvider`](https://swiftpackageindex.com/apple/swift-configuration/documentation/configuration/directoryfilesprovider)
126126
- In-memory: [`InMemoryProvider`](https://swiftpackageindex.com/apple/swift-configuration/documentation/configuration/inmemoryprovider) and [`MutableInMemoryProvider`](https://swiftpackageindex.com/apple/swift-configuration/documentation/configuration/mutableinmemoryprovider)
127127
- Key transforming: [`KeyMappingProvider`](https://swiftpackageindex.com/apple/swift-configuration/documentation/configuration/keymappingprovider)

Sources/Configuration/ConfigReader.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ import Foundation
4444
/// // First, check environment variables
4545
/// EnvironmentVariablesProvider(),
4646
/// // Then, check a JSON config file
47-
/// try await JSONProvider(filePath: "/etc/config.json"),
47+
/// try await FileProvider<JSONSnapshot>(filePath: "/etc/config.json"),
4848
/// // Finally, fall back to in-memory defaults
4949
/// InMemoryProvider(values: [
5050
/// "http.timeout": 60,

Sources/Configuration/Documentation.docc/Documentation.md

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ For example, to read the timeout configuration value for an HTTP client, check o
4444
}
4545
```
4646
```swift
47-
let provider = try await JSONProvider(
47+
let provider = try await FileProvider<JSONSnapshot>(
4848
filePath: "/etc/config.json"
4949
)
5050
let config = ConfigReader(provider: provider)
@@ -61,7 +61,7 @@ For example, to read the timeout configuration value for an HTTP client, check o
6161
}
6262
```
6363
```swift
64-
let provider = try await ReloadingJSONProvider(
64+
let provider = try await ReloadingFileProvider<JSONSnapshot>(
6565
filePath: "/etc/config.json"
6666
)
6767
// Omitted: Add `provider` to a ServiceGroup
@@ -76,7 +76,7 @@ For example, to read the timeout configuration value for an HTTP client, check o
7676
timeout: 30
7777
```
7878
```swift
79-
let provider = try await YAMLProvider(
79+
let provider = try await FileProvider<YAMLSnapshot>(
8080
filePath: "/etc/config.yaml"
8181
)
8282
let config = ConfigReader(provider: provider)
@@ -90,7 +90,7 @@ For example, to read the timeout configuration value for an HTTP client, check o
9090
timeout: 30
9191
```
9292
```swift
93-
let provider = try await ReloadingYAMLProvider(
93+
let provider = try await ReloadingFileProvider<YAMLSnapshot>(
9494
filePath: "/etc/config.yaml"
9595
)
9696
// Omitted: Add `provider` to a ServiceGroup
@@ -187,11 +187,11 @@ To enable an additional trait on the package, update the package dependency:
187187
```
188188

189189
Available traits:
190-
- **`JSONSupport`** (default): Adds support for ``JSONProvider``, a ``ConfigProvider`` for reading JSON files.
190+
- **`JSONSupport`** (default): Adds support for ``JSONSnapshot``, which enables using ``FileProvider`` and ``ReloadingFileProvider`` with JSON files.
191191
- **`LoggingSupport`** (opt-in): Adds support for ``AccessLogger``, a way to emit access events into a `SwiftLog.Logger`.
192-
- **`ReloadingSupport`** (opt-in): Adds support for auto-reloading variants of file providers, such as ``ReloadingJSONProvider`` (when `JSONSupport` is enabled) and ``ReloadingYAMLProvider`` (when `YAMLSupport` is enabled).
192+
- **`ReloadingSupport`** (opt-in): Adds support for ``ReloadingFileProvider``, which provides auto-reloading capability for file-based configuration.
193193
- **`CommandLineArgumentsSupport`** (opt-in): Adds support for ``CommandLineArgumentsProvider`` for parsing command line arguments.
194-
- **`YAMLSupport`** (opt-in): Adds support for ``YAMLProvider``, a ``ConfigProvider`` for reading YAML files.
194+
- **`YAMLSupport`** (opt-in): Adds support for ``YAMLSnapshot``, which enables using ``FileProvider`` and ``ReloadingFileProvider`` with YAML files.
195195

196196
### Supported platforms and minimum versions
197197

@@ -235,8 +235,8 @@ The library includes comprehensive built-in provider support:
235235

236236
- Environment variables: ``EnvironmentVariablesProvider``
237237
- Command-line arguments: ``CommandLineArgumentsProvider``
238-
- JSON file: ``JSONProvider`` and ``ReloadingJSONProvider``
239-
- YAML file: ``YAMLProvider`` and ``ReloadingYAMLProvider``
238+
- JSON file: ``FileProvider`` and ``ReloadingFileProvider`` with ``JSONSnapshot``
239+
- YAML file: ``FileProvider`` and ``ReloadingFileProvider`` with ``YAMLSnapshot``
240240
- Directory of files: ``DirectoryFilesProvider``
241241
- In-memory: ``InMemoryProvider`` and ``MutableInMemoryProvider``
242242
- Key transforming: ``KeyMappingProvider``
@@ -259,7 +259,7 @@ let config = ConfigReader(providers: [
259259
// Then, check command-line options.
260260
CommandLineArgumentsProvider(),
261261
// Then, check a JSON config file.
262-
try await JSONProvider(filePath: "/etc/config.json"),
262+
try await FileProvider<JSONSnapshot>(filePath: "/etc/config.json"),
263263
// Finally, fall back to in-memory defaults.
264264
InMemoryProvider(values: [
265265
"http.timeout": 60,
@@ -272,10 +272,10 @@ let timeout = config.int(forKey: "http.timeout", default: 15)
272272

273273
#### Hot reloading
274274

275-
Long-running services can periodically reload configuration with ``ReloadingJSONProvider`` and ``ReloadingYAMLProvider``:
275+
Long-running services can periodically reload configuration with ``ReloadingFileProvider``:
276276

277277
```swift
278-
let provider = try await ReloadingJSONProvider(filePath: "/etc/config.json")
278+
let provider = try await ReloadingFileProvider<JSONSnapshot>(filePath: "/etc/config.json")
279279
// Omitted: add provider to a ServiceGroup
280280
let config = ConfigReader(provider: provider)
281281

@@ -407,18 +407,17 @@ Any package can implement a ``ConfigProvider``, making the ecosystem extensible
407407
- ``ConfigReader``
408408
- ``ConfigProvider``
409409
- ``ConfigSnapshotReader``
410-
- ``ConfigSnapshotProtocol``
411410
- <doc:Choosing-access-patterns>
412411
- <doc:Choosing-reader-methods>
413412
- <doc:Handling-secrets-correctly>
414413

415414
### Built-in providers
416415
- ``EnvironmentVariablesProvider``
417416
- ``CommandLineArgumentsProvider``
418-
- ``JSONProvider``
419-
- ``YAMLProvider``
420-
- ``ReloadingJSONProvider``
421-
- ``ReloadingYAMLProvider``
417+
- ``FileProvider``
418+
- ``ReloadingFileProvider``
419+
- ``JSONSnapshot``
420+
- ``YAMLSnapshot``
422421
- <doc:Using-reloading-providers>
423422
- ``DirectoryFilesProvider``
424423
- <doc:Using-in-memory-providers>
@@ -427,6 +426,8 @@ Any package can implement a ``ConfigProvider``, making the ecosystem extensible
427426
- ``KeyMappingProvider``
428427

429428
### Creating a custom provider
429+
- ``ConfigSnapshotProtocol``
430+
- ``FileParsingOptionsProtocol``
430431
- ``ConfigProvider``
431432
- ``ConfigContent``
432433
- ``ConfigValue``

Sources/Configuration/Documentation.docc/Guides/Choosing-access-patterns.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ Use the "watch" pattern when:
122122

123123
- Immediately emits the initial value, then subsequent updates.
124124
- Continues monitoring until the task is cancelled.
125-
- Works with providers like ``ReloadingJSONProvider`` and ``ReloadingYAMLProvider``.
125+
- Works with providers like ``ReloadingFileProvider``.
126126

127127
For details on reloading providers, check out <doc:Using-reloading-providers>.
128128

Sources/Configuration/Documentation.docc/Guides/Configuring-applications.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ let logger: Logger = ...
3535

3636
let config = ConfigReader(
3737
providers: [
38-
EnvironmentVariablesProvider(),
39-
try await JSONProvider(filePath: "/etc/myapp/config.json"),
38+
EnvironmentVariablesProvider(),
39+
try await FileProvider<JSONSnapshot>(filePath: "/etc/myapp/config.json"),
4040
InMemoryProvider(values: [
4141
"http.server.port": 8080,
4242
"http.server.host": "127.0.0.1",

Sources/Configuration/Documentation.docc/Guides/Example-use-cases.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ variable name above `SERVER_PORT`.
2424

2525
### Reading from a JSON configuration file
2626

27-
You can store multiple configuration values together in a JSON file and read them from the fileystem using ``JSONProvider``.
27+
You can store multiple configuration values together in a JSON file and read them from the fileystem using ``FileProvider`` with ``JSONSnapshot``.
2828
The following example creates a ``ConfigReader`` for a JSON file at the path `/etc/config.json`, and reads a url and port
2929
number collected as properties of the `database` JSON object:
3030

3131
```swift
3232
import Configuration
3333

3434
let config = ConfigReader(
35-
provider: try await JSONProvider(filePath: "/etc/config.json")
35+
provider: try await FileProvider<JSONSnapshot>(filePath: "/etc/config.json")
3636
)
3737

3838
// Access nested values using dot notation.
@@ -92,7 +92,7 @@ let config = ConfigReader(providers: [
9292
// First check environment variables.
9393
EnvironmentVariablesProvider(),
9494
// Then check the config file.
95-
try await JSONProvider(filePath: "/etc/config.json"),
95+
try await FileProvider<JSONSnapshot>(filePath: "/etc/config.json"),
9696
// Finally, use hardcoded defaults.
9797
InMemoryProvider(values: [
9898
"app.name": "MyApp",
@@ -131,7 +131,7 @@ import Configuration
131131
import ServiceLifecycle
132132

133133
// Create a reloading YAML provider
134-
let provider = try await ReloadingYAMLProvider(
134+
let provider = try await ReloadingFileProvider<YAMLSnapshot>(
135135
filePath: "/etc/app-config.yaml",
136136
pollInterval: .seconds(30)
137137
)

Sources/Configuration/Documentation.docc/Guides/Handling-secrets-correctly.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ The following example marks keys as secret based on the closure you provide.
8181
In this case, keys that contain `password`, `secret`, or `token` are all marked as secret:
8282

8383
```swift
84-
let provider = JSONProvider(
84+
let provider = FileProvider<JSONSnapshot>(
8585
filePath: "/etc/config.json",
8686
secretsSpecifier: .dynamic { key, value in
8787
key.lowercased().contains("password") ||
@@ -96,7 +96,7 @@ let provider = JSONProvider(
9696
The following example asserts that none of the values returned from the provider are considered secret:
9797

9898
```swift
99-
let provider = JSONProvider(
99+
let provider = FileProvider<JSONSnapshot>(
100100
filePath: "/etc/config.json",
101101
secretsSpecifier: .none
102102
)

Sources/Configuration/Documentation.docc/Guides/Troubleshooting.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,12 @@ Common ServiceGroup problems:
9999

100100
```swift
101101
// Incorrect: Provider not included in ServiceGroup
102-
let provider = try await ReloadingJSONProvider(filePath: "/etc/config.json")
102+
let provider = try await ReloadingFileProvider<JSONSnapshot>(filePath: "/etc/config.json")
103103
let config = ConfigReader(provider: provider)
104104
// File monitoring won't work
105105

106106
// Correct: Provider runs in ServiceGroup
107-
let provider = try await ReloadingJSONProvider(filePath: "/etc/config.json")
107+
let provider = try await ReloadingFileProvider<JSONSnapshot>(filePath: "/etc/config.json")
108108
let serviceGroup = ServiceGroup(services: [provider], logger: logger)
109109
try await serviceGroup.run()
110110
```

Sources/Configuration/Documentation.docc/Guides/Using-reloading-providers.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ Automatically reload configuration from files when they change.
66

77
A reloading provider monitors configuration files for changes and automatically updates your application's configuration without requiring restarts. Swift Configuration provides:
88

9-
- ``ReloadingJSONProvider`` for JSON configuration files.
10-
- ``ReloadingYAMLProvider`` for YAML configuration files.
9+
- ``ReloadingFileProvider`` with ``JSONSnapshot`` for JSON configuration files.
10+
- ``ReloadingFileProvider`` with ``YAMLSnapshot`` for YAML configuration files.
1111

1212
### Basic usage
1313

@@ -18,7 +18,7 @@ Reloading providers run in a [`ServiceGroup`](https://swiftpackageindex.com/swif
1818
```swift
1919
import ServiceLifecycle
2020

21-
let provider = try await ReloadingJSONProvider(
21+
let provider = try await ReloadingFileProvider<JSONSnapshot>(
2222
filePath: "/etc/config.json",
2323
pollInterval: .seconds(15)
2424
)
@@ -109,8 +109,8 @@ and interval to watch for a JSON file that contains the configuration for your a
109109
let envProvider = EnvironmentVariablesProvider()
110110
let envConfig = ConfigReader(provider: envProvider)
111111

112-
let jsonProvider = try await ReloadingJSONProvider(
113-
config: envConfig.scoped(to: "json")
112+
let jsonProvider = try await ReloadingFileProvider<JSONSnapshot>(
113+
config: envConfig.scoped(to: "json")
114114
// Reads JSON_FILE_PATH and JSON_POLL_INTERVAL_SECONDS
115115
)
116116
```
@@ -120,10 +120,10 @@ let jsonProvider = try await ReloadingJSONProvider(
120120
1. **Replace initialization**:
121121
```swift
122122
// Before
123-
let provider = try await JSONProvider(filePath: "/etc/config.json")
123+
let provider = try await FileProvider<JSONSnapshot>(filePath: "/etc/config.json")
124124

125125
// After
126-
let provider = try await ReloadingJSONProvider(filePath: "/etc/config.json")
126+
let provider = try await ReloadingFileProvider<JSONSnapshot>(filePath: "/etc/config.json")
127127
```
128128

129129
2. **Add the provider to a ServiceGroup**:

0 commit comments

Comments
 (0)