alink-cli 0.7.2 → 0.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -6
- package/bin/agentlink-account.js +133 -0
- package/bin/agentlink.js +95 -12
- package/dist/Config-Bj2ZPCsP.mjs +1221 -0
- package/dist/Config-Bj2ZPCsP.mjs.map +1 -0
- package/dist/NodeHttpServer-BGJlR_Kf.mjs +826 -0
- package/dist/NodeHttpServer-BGJlR_Kf.mjs.map +1 -0
- package/dist/NodeServices-DDZTiw5K.mjs +1984 -0
- package/dist/NodeServices-DDZTiw5K.mjs.map +1 -0
- package/dist/NodeSocket-08w4osAf.mjs +11198 -0
- package/dist/NodeSocket-08w4osAf.mjs.map +1 -0
- package/dist/NodeSqliteClient-Byu521pt.mjs +578 -0
- package/dist/NodeSqliteClient-Byu521pt.mjs.map +1 -0
- package/dist/Schema-B3i-HrZQ.mjs +40423 -0
- package/dist/Schema-B3i-HrZQ.mjs.map +1 -0
- package/dist/SqlClient-DcM69ZvI.mjs +1554 -0
- package/dist/SqlClient-DcM69ZvI.mjs.map +1 -0
- package/dist/bin.mjs +47577 -26766
- package/dist/bin.mjs.map +1 -1
- package/package.json +4 -3
- package/dist/NodeSqliteClient-BUlNQAY0.mjs +0 -191
- package/dist/NodeSqliteClient-BUlNQAY0.mjs.map +0 -1
|
@@ -0,0 +1,1221 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { $a as flatMapEager, B as Union, C as Number$1, Co as mapEager, D as String$1, E as Record$1, En as transformOrFail, F as URL, Fu as map$2, Ga as die, Io as orDie, Jt as _is, Kn as Pointer, Ld as assignProperty, Md as Prototype, Na as catchDefect, Nd as PipeInspectableProto, Pa as catchEager, Pt as toCodecStringTree, Qd as hasProperty, Qs as TaggedError, So as map$1, Td as some, To as mapErrorEager, Tt as make$2, Xu as Reference, Ya as fail, Yt as decodeUnknownEffect, Z as decodeTo$1, Zt as SchemaError, _n as Transformation, en as applyToSelfOrLastLinkEncoding, g as Literals, gn as unknown, hf as flow, hn as toEncoded, m as Int, mf as dual, no as fnUntraced, ns as succeed, r as Boolean$1, tn as decodeTo, ut as isBetween, vn as splitKeyValue, wd as none, wn as passthrough, xa as all$1, yn as transform } from "./Schema-B3i-HrZQ.mjs";
|
|
4
|
+
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9/node_modules/effect/dist/ConfigProvider.js
|
|
5
|
+
/**
|
|
6
|
+
* Data sources used by `Config` to load raw configuration values. A
|
|
7
|
+
* `ConfigProvider` reads paths from places such as environment variables,
|
|
8
|
+
* JavaScript objects, `.env` contents, or directories, and returns a uniform
|
|
9
|
+
* `Node` shape that config schemas can decode. The module also includes helpers
|
|
10
|
+
* for composing providers, changing paths, and installing providers through
|
|
11
|
+
* layers.
|
|
12
|
+
*
|
|
13
|
+
* @since 4.0.0
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Creates a `Value` node representing a terminal string leaf.
|
|
17
|
+
*
|
|
18
|
+
* **When to use**
|
|
19
|
+
*
|
|
20
|
+
* Use when building nodes inside a custom `ConfigProvider`'s `get`
|
|
21
|
+
* callback.
|
|
22
|
+
*
|
|
23
|
+
* **Details**
|
|
24
|
+
*
|
|
25
|
+
* The function returns a new plain object.
|
|
26
|
+
*
|
|
27
|
+
* **Example** (Creating a value node)
|
|
28
|
+
*
|
|
29
|
+
* ```ts import.meta.vitest
|
|
30
|
+
* import { ConfigProvider } from "effect"
|
|
31
|
+
*
|
|
32
|
+
* ConfigProvider.makeValue("3000") // => { _tag: "Value", value: "3000" }
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @see {@link makeRecord} – for object-like containers
|
|
36
|
+
* @see {@link makeArray} – for array-like containers
|
|
37
|
+
*
|
|
38
|
+
* @category constructors
|
|
39
|
+
* @since 4.0.0
|
|
40
|
+
*/
|
|
41
|
+
function makeValue(value) {
|
|
42
|
+
return {
|
|
43
|
+
_tag: "Value",
|
|
44
|
+
value
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Creates a `Record` node representing an object-like container with known
|
|
49
|
+
* child keys.
|
|
50
|
+
*
|
|
51
|
+
* **When to use**
|
|
52
|
+
*
|
|
53
|
+
* Use when you need to describe a directory or JSON object inside a custom
|
|
54
|
+
* provider.
|
|
55
|
+
*
|
|
56
|
+
* **Details**
|
|
57
|
+
*
|
|
58
|
+
* The optional `value` allows a node to be both a container and a leaf at the
|
|
59
|
+
* same time (for example, an env var `A=x` that also has children `A_FOO` and
|
|
60
|
+
* `A_BAR`).
|
|
61
|
+
*
|
|
62
|
+
* **Example** (Creating a record node)
|
|
63
|
+
*
|
|
64
|
+
* ```ts import.meta.vitest
|
|
65
|
+
* import { ConfigProvider } from "effect"
|
|
66
|
+
*
|
|
67
|
+
* const node = ConfigProvider.makeRecord(new Set(["host", "port"]))
|
|
68
|
+
* node._tag // => "Record"
|
|
69
|
+
* if (node._tag === "Record") {
|
|
70
|
+
* node.keys // => new Set(["host", "port"])
|
|
71
|
+
* node.value // => undefined
|
|
72
|
+
* }
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* @see {@link makeValue} – for terminal leaves
|
|
76
|
+
* @see {@link makeArray} – for array-like containers
|
|
77
|
+
*
|
|
78
|
+
* @category constructors
|
|
79
|
+
* @since 4.0.0
|
|
80
|
+
*/
|
|
81
|
+
function makeRecord(keys, value) {
|
|
82
|
+
return {
|
|
83
|
+
_tag: "Record",
|
|
84
|
+
keys,
|
|
85
|
+
value
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Creates an `Array` node representing an indexed container with a known
|
|
90
|
+
* length.
|
|
91
|
+
*
|
|
92
|
+
* **When to use**
|
|
93
|
+
*
|
|
94
|
+
* Use when you need to describe a JSON array or numerically indexed env vars
|
|
95
|
+
* inside a custom provider.
|
|
96
|
+
*
|
|
97
|
+
* **Details**
|
|
98
|
+
*
|
|
99
|
+
* The optional `value` allows a node to be both a container and a leaf at the
|
|
100
|
+
* same time.
|
|
101
|
+
*
|
|
102
|
+
* **Example** (Creating an array node)
|
|
103
|
+
*
|
|
104
|
+
* ```ts import.meta.vitest
|
|
105
|
+
* import { ConfigProvider } from "effect"
|
|
106
|
+
*
|
|
107
|
+
* ConfigProvider.makeArray(3) // => { _tag: "Array", length: 3, value: undefined }
|
|
108
|
+
* ```
|
|
109
|
+
*
|
|
110
|
+
* @see {@link makeValue} – for terminal leaves
|
|
111
|
+
* @see {@link makeRecord} – for object-like containers
|
|
112
|
+
*
|
|
113
|
+
* @category constructors
|
|
114
|
+
* @since 4.0.0
|
|
115
|
+
*/
|
|
116
|
+
function makeArray(length, value) {
|
|
117
|
+
return {
|
|
118
|
+
_tag: "Array",
|
|
119
|
+
length,
|
|
120
|
+
value
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Typed error indicating that a configuration source could not be read.
|
|
125
|
+
*
|
|
126
|
+
* **When to use**
|
|
127
|
+
*
|
|
128
|
+
* Use when you need to report that a custom provider's underlying store is
|
|
129
|
+
* unreachable or produced an I/O error while reading configuration data.
|
|
130
|
+
*
|
|
131
|
+
* **Gotchas**
|
|
132
|
+
*
|
|
133
|
+
* Do not use `SourceError` for "key not found". That case is represented by
|
|
134
|
+
* returning `undefined` from `load`.
|
|
135
|
+
*
|
|
136
|
+
* **Example** (Failing with a SourceError)
|
|
137
|
+
*
|
|
138
|
+
* ```ts import.meta.vitest
|
|
139
|
+
* import { ConfigProvider, Effect } from "effect"
|
|
140
|
+
*
|
|
141
|
+
* const provider = ConfigProvider.make((_path) =>
|
|
142
|
+
* Effect.fail(
|
|
143
|
+
* new ConfigProvider.SourceError({ message: "connection refused" })
|
|
144
|
+
* )
|
|
145
|
+
* )
|
|
146
|
+
*
|
|
147
|
+
* Effect.runSync(Effect.flip(provider.load(["host"]))).message // => "connection refused"
|
|
148
|
+
* ```
|
|
149
|
+
*
|
|
150
|
+
* @see {@link ConfigProvider} – the interface whose `load` may fail with this
|
|
151
|
+
* error
|
|
152
|
+
*
|
|
153
|
+
* @category errors
|
|
154
|
+
* @since 4.0.0
|
|
155
|
+
*/
|
|
156
|
+
var SourceError = class extends TaggedError("SourceError") {};
|
|
157
|
+
/**
|
|
158
|
+
* Context reference for the active raw configuration provider, registered in the context with a
|
|
159
|
+
* default value of `fromEnv()`. Because it is a `Context.Reference`, it is
|
|
160
|
+
* available without explicit provision; `Config` schemas automatically resolve
|
|
161
|
+
* it.
|
|
162
|
+
*
|
|
163
|
+
* **When to use**
|
|
164
|
+
*
|
|
165
|
+
* Use to override the active raw configuration provider for an entire program,
|
|
166
|
+
* or retrieve the current provider inside an Effect.
|
|
167
|
+
*
|
|
168
|
+
* **Example** (Providing a custom provider)
|
|
169
|
+
*
|
|
170
|
+
* ```ts import.meta.vitest
|
|
171
|
+
* import { ConfigProvider, Effect } from "effect"
|
|
172
|
+
*
|
|
173
|
+
* const provider = ConfigProvider.fromUnknown({ port: 8080 })
|
|
174
|
+
*
|
|
175
|
+
* const program = Effect.gen(function*() {
|
|
176
|
+
* const current = yield* ConfigProvider.ConfigProvider
|
|
177
|
+
* return current
|
|
178
|
+
* }).pipe(
|
|
179
|
+
* Effect.provideService(ConfigProvider.ConfigProvider, provider)
|
|
180
|
+
* )
|
|
181
|
+
*
|
|
182
|
+
* Effect.runSync(program) === provider // => true
|
|
183
|
+
* ```
|
|
184
|
+
*
|
|
185
|
+
* @see {@link layer} – install a provider as a Layer
|
|
186
|
+
* @see {@link layerAdd} – add a fallback provider as a Layer
|
|
187
|
+
*
|
|
188
|
+
* @category services
|
|
189
|
+
* @since 4.0.0
|
|
190
|
+
*/
|
|
191
|
+
const ConfigProvider = /*#__PURE__*/ Reference("effect/ConfigProvider", { defaultValue: () => fromEnv() });
|
|
192
|
+
const Proto$1 = {
|
|
193
|
+
...PipeInspectableProto,
|
|
194
|
+
toJSON() {
|
|
195
|
+
return { _id: "ConfigProvider" };
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
const identityPath = (path) => path;
|
|
199
|
+
function makeProvider(load, mapInput) {
|
|
200
|
+
const self = Object.create(Proto$1);
|
|
201
|
+
self.load = load;
|
|
202
|
+
self.mapInput = mapInput;
|
|
203
|
+
return self;
|
|
204
|
+
}
|
|
205
|
+
function makeSource(get, transform) {
|
|
206
|
+
return makeProvider((path) => get(transform(path)), (f) => makeSource(get, flow(transform, f)));
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Creates a `ConfigProvider` from a raw lookup function.
|
|
210
|
+
*
|
|
211
|
+
* **When to use**
|
|
212
|
+
*
|
|
213
|
+
* Use when implementing a provider backed by a custom store, such as a
|
|
214
|
+
* database, remote API, or in-memory map.
|
|
215
|
+
*
|
|
216
|
+
* **Details**
|
|
217
|
+
*
|
|
218
|
+
* The `get` callback receives a `Path` and must return
|
|
219
|
+
* `Effect<Node | undefined, SourceError>`. Return `undefined` when the path does
|
|
220
|
+
* not exist, a `Node` when it does, and fail with `SourceError` only when the
|
|
221
|
+
* source cannot be read.
|
|
222
|
+
*
|
|
223
|
+
* Providers created by `make` also implement the path-transformation
|
|
224
|
+
* capability used by {@link mapInput}, {@link constantCase}, and
|
|
225
|
+
* {@link nested}.
|
|
226
|
+
*
|
|
227
|
+
* **Example** (Creating a simple in-memory provider)
|
|
228
|
+
*
|
|
229
|
+
* ```ts import.meta.vitest
|
|
230
|
+
* import { ConfigProvider, Effect } from "effect"
|
|
231
|
+
*
|
|
232
|
+
* const data: Record<string, string> = {
|
|
233
|
+
* host: "localhost",
|
|
234
|
+
* port: "5432"
|
|
235
|
+
* }
|
|
236
|
+
*
|
|
237
|
+
* const provider = ConfigProvider.make((path) => {
|
|
238
|
+
* const key = path.join(".")
|
|
239
|
+
* const value = data[key]
|
|
240
|
+
* return Effect.succeed(
|
|
241
|
+
* value !== undefined ? ConfigProvider.makeValue(value) : undefined
|
|
242
|
+
* )
|
|
243
|
+
* })
|
|
244
|
+
*
|
|
245
|
+
* Effect.runSync(provider.load(["host"])) // => ConfigProvider.makeValue("localhost")
|
|
246
|
+
* ```
|
|
247
|
+
*
|
|
248
|
+
* @see {@link fromEnv} – pre-built provider for environment variables
|
|
249
|
+
* @see {@link fromUnknown} – pre-built provider for JSON objects
|
|
250
|
+
*
|
|
251
|
+
* @category constructors
|
|
252
|
+
* @since 4.0.0
|
|
253
|
+
*/
|
|
254
|
+
function make$1(get) {
|
|
255
|
+
return makeSource(get, identityPath);
|
|
256
|
+
}
|
|
257
|
+
function emptyStringAsMissing(value, preserveEmptyStrings) {
|
|
258
|
+
return value === "" && !preserveEmptyStrings ? void 0 : value;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Creates a `ConfigProvider` backed by environment variables.
|
|
262
|
+
*
|
|
263
|
+
* **When to use**
|
|
264
|
+
*
|
|
265
|
+
* Use to read configuration from `process.env`, which is the default when no
|
|
266
|
+
* provider is explicitly set, or pass a custom env record for testing or
|
|
267
|
+
* non-Node runtimes.
|
|
268
|
+
*
|
|
269
|
+
* **Details**
|
|
270
|
+
*
|
|
271
|
+
* Path segments are joined with `_` for direct lookup, and env var names are
|
|
272
|
+
* also split on `_` to build a trie for child key discovery. This means
|
|
273
|
+
* `DATABASE_HOST=localhost` is accessible at both path `["DATABASE_HOST"]`
|
|
274
|
+
* and `["DATABASE", "HOST"]`. If all immediate children of a trie node have
|
|
275
|
+
* purely numeric names, the node is reported as an `Array`; otherwise as a
|
|
276
|
+
* `Record`.
|
|
277
|
+
*
|
|
278
|
+
* The default environment merges `process.env` and `import.meta.env` (when
|
|
279
|
+
* available). Override by passing `{ env: { ... } }`.
|
|
280
|
+
*
|
|
281
|
+
* Literal empty strings are treated as missing values when loaded as values by
|
|
282
|
+
* default. Pass `{ preserveEmptyStrings: true }` to keep empty strings as
|
|
283
|
+
* explicit values. Child discovery still reflects the environment variable
|
|
284
|
+
* names present in the source.
|
|
285
|
+
*
|
|
286
|
+
* Never fails with `SourceError` — all lookups are synchronous.
|
|
287
|
+
*
|
|
288
|
+
* **Example** (Reading from a custom env record)
|
|
289
|
+
*
|
|
290
|
+
* ```ts import.meta.vitest
|
|
291
|
+
* import { Config, ConfigProvider, Effect } from "effect"
|
|
292
|
+
*
|
|
293
|
+
* const provider = ConfigProvider.fromEnv({
|
|
294
|
+
* env: {
|
|
295
|
+
* DATABASE_HOST: "localhost",
|
|
296
|
+
* DATABASE_PORT: "5432"
|
|
297
|
+
* }
|
|
298
|
+
* })
|
|
299
|
+
*
|
|
300
|
+
* const host = Config.string("HOST").parse(
|
|
301
|
+
* provider.pipe(ConfigProvider.nested("DATABASE"))
|
|
302
|
+
* )
|
|
303
|
+
*
|
|
304
|
+
* Effect.runSync(host) // => "localhost"
|
|
305
|
+
* ```
|
|
306
|
+
*
|
|
307
|
+
* @see {@link fromUnknown} – for JSON objects
|
|
308
|
+
* @see {@link constantCase} – bridge camelCase keys to SCREAMING_SNAKE_CASE
|
|
309
|
+
*
|
|
310
|
+
* @category constructors
|
|
311
|
+
* @since 2.0.0
|
|
312
|
+
*/
|
|
313
|
+
function fromEnv(options) {
|
|
314
|
+
const env = options?.env ?? {
|
|
315
|
+
...globalThis.process?.env,
|
|
316
|
+
...import.meta.env
|
|
317
|
+
};
|
|
318
|
+
const preserveEmptyStrings = options?.preserveEmptyStrings === true;
|
|
319
|
+
const trie = buildEnvTrie(env);
|
|
320
|
+
return make$1((path) => succeed(nodeAtEnv(trie, env, path, preserveEmptyStrings)));
|
|
321
|
+
}
|
|
322
|
+
function buildEnvTrie(env) {
|
|
323
|
+
const trie = {};
|
|
324
|
+
for (const [name, value] of Object.entries(env)) {
|
|
325
|
+
if (value === void 0) continue;
|
|
326
|
+
const segments = name.split("_");
|
|
327
|
+
let node = trie;
|
|
328
|
+
for (const seg of segments) {
|
|
329
|
+
const children = node.children ??= Object.create(null);
|
|
330
|
+
node = children[seg] ??= {};
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return trie;
|
|
334
|
+
}
|
|
335
|
+
const NUMERIC_INDEX = /^(0|[1-9][0-9]*)$/;
|
|
336
|
+
function nodeAtEnv(trie, env, path, preserveEmptyStrings) {
|
|
337
|
+
const key = path.map(String).join("_");
|
|
338
|
+
const leafValue = emptyStringAsMissing(Object.hasOwn(env, key) ? env[key] : void 0, preserveEmptyStrings);
|
|
339
|
+
const trieNode = trieNodeAt(trie, path);
|
|
340
|
+
const children = trieNode?.children ? Object.keys(trieNode.children) : [];
|
|
341
|
+
if (children.length === 0) return leafValue === void 0 ? void 0 : makeValue(leafValue);
|
|
342
|
+
if (children.every((k) => NUMERIC_INDEX.test(k))) return makeArray(Math.max(...children.map((k) => parseInt(k, 10))) + 1, leafValue);
|
|
343
|
+
return makeRecord(new Set(children), leafValue);
|
|
344
|
+
}
|
|
345
|
+
function trieNodeAt(root, path) {
|
|
346
|
+
if (path.length === 0) return root;
|
|
347
|
+
let node = root;
|
|
348
|
+
for (const seg of path) {
|
|
349
|
+
node = node?.children?.[String(seg)];
|
|
350
|
+
if (!node) return void 0;
|
|
351
|
+
}
|
|
352
|
+
return node;
|
|
353
|
+
}
|
|
354
|
+
//#endregion
|
|
355
|
+
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9/node_modules/effect/dist/LogLevel.js
|
|
356
|
+
/**
|
|
357
|
+
* Returns all `LogLevel` values in order from `All` through the concrete severities to
|
|
358
|
+
* `None`.
|
|
359
|
+
*
|
|
360
|
+
* **When to use**
|
|
361
|
+
*
|
|
362
|
+
* Use to enumerate or validate all accepted `LogLevel` string values, including
|
|
363
|
+
* the `All` and `None` sentinel levels.
|
|
364
|
+
*
|
|
365
|
+
* **Details**
|
|
366
|
+
*
|
|
367
|
+
* The array order matches the module severity order: `All`, concrete
|
|
368
|
+
* severities from `Fatal` to `Trace`, then `None`.
|
|
369
|
+
*
|
|
370
|
+
* **Gotchas**
|
|
371
|
+
*
|
|
372
|
+
* This list includes `All` and `None`, so it is not limited to concrete emitted
|
|
373
|
+
* severities.
|
|
374
|
+
*
|
|
375
|
+
* @see {@link Severity} for the concrete message severity type that excludes `All` and `None`
|
|
376
|
+
* @see {@link Order} for comparing these levels by severity order
|
|
377
|
+
*
|
|
378
|
+
* @category constants
|
|
379
|
+
* @since 4.0.0
|
|
380
|
+
*/
|
|
381
|
+
const values = [
|
|
382
|
+
"All",
|
|
383
|
+
"Fatal",
|
|
384
|
+
"Error",
|
|
385
|
+
"Warn",
|
|
386
|
+
"Info",
|
|
387
|
+
"Debug",
|
|
388
|
+
"Trace",
|
|
389
|
+
"None"
|
|
390
|
+
];
|
|
391
|
+
//#endregion
|
|
392
|
+
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=a18f963109656ddbeb2a99ca45f942ecf54830986259eb01ce6a970421c9c6a9/node_modules/effect/dist/Config.js
|
|
393
|
+
const TypeId = "~effect/Config";
|
|
394
|
+
/**
|
|
395
|
+
* Returns `true` if `u` is a `Config` instance.
|
|
396
|
+
*
|
|
397
|
+
* **When to use**
|
|
398
|
+
*
|
|
399
|
+
* Use when you need to distinguish a `Config` from an unknown value before
|
|
400
|
+
* calling `.parse` or {@link unwrap}.
|
|
401
|
+
*
|
|
402
|
+
* **Example** (Checking Config values)
|
|
403
|
+
*
|
|
404
|
+
* ```ts import.meta.vitest
|
|
405
|
+
* import { Config } from "effect"
|
|
406
|
+
*
|
|
407
|
+
* Config.isConfig(Config.string("HOST")) // => true
|
|
408
|
+
* Config.isConfig("not a config") // => false
|
|
409
|
+
* ```
|
|
410
|
+
*
|
|
411
|
+
* @category guards
|
|
412
|
+
* @since 2.0.0
|
|
413
|
+
*/
|
|
414
|
+
const isConfig = (u) => hasProperty(u, TypeId);
|
|
415
|
+
/**
|
|
416
|
+
* Represents the error type produced when config loading or validation fails.
|
|
417
|
+
*
|
|
418
|
+
* **When to use**
|
|
419
|
+
*
|
|
420
|
+
* Use when you need to inspect config loading or validation failures.
|
|
421
|
+
*
|
|
422
|
+
* **Details**
|
|
423
|
+
*
|
|
424
|
+
* Wraps either:
|
|
425
|
+
* - A `SourceError` — the provider could not read data (I/O failure).
|
|
426
|
+
* - A `SchemaError` — the data was found but did not match the schema
|
|
427
|
+
* (wrong type, out of range, missing key, etc.).
|
|
428
|
+
*
|
|
429
|
+
* @see {@link orElse} – recover from a ConfigError
|
|
430
|
+
* @see {@link withDefault} – provide a fallback when relevant input is absent
|
|
431
|
+
*
|
|
432
|
+
* @category errors
|
|
433
|
+
* @since 4.0.0
|
|
434
|
+
*/
|
|
435
|
+
var ConfigError = class {
|
|
436
|
+
_tag = "ConfigError";
|
|
437
|
+
name = "ConfigError";
|
|
438
|
+
cause;
|
|
439
|
+
constructor(cause) {
|
|
440
|
+
this.cause = cause;
|
|
441
|
+
}
|
|
442
|
+
get message() {
|
|
443
|
+
return this.cause.toString();
|
|
444
|
+
}
|
|
445
|
+
toString() {
|
|
446
|
+
return `ConfigError(${this.message})`;
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
const Proto = {
|
|
450
|
+
.../*#__PURE__*/ Prototype({
|
|
451
|
+
label: "Config",
|
|
452
|
+
evaluate(fiber) {
|
|
453
|
+
return this.parse(fiber.getRef(ConfigProvider));
|
|
454
|
+
}
|
|
455
|
+
}),
|
|
456
|
+
[TypeId]: TypeId,
|
|
457
|
+
toJSON() {
|
|
458
|
+
return { _id: "Config" };
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
function make(evaluator) {
|
|
462
|
+
const self = Object.create(Proto);
|
|
463
|
+
self.evaluator = evaluator;
|
|
464
|
+
self.parse = (provider) => evaluator(provider, []).pipe(mapErrorEager((failure) => failure.error), flatMapEager((resolution) => resolution._tag === "Resolved" ? succeed(resolution.value) : fail(resolution.error)));
|
|
465
|
+
return self;
|
|
466
|
+
}
|
|
467
|
+
const evaluateAt = (self, provider, pathPrefix) => self.evaluator(provider, pathPrefix);
|
|
468
|
+
const resolved = (value, hasInput) => ({
|
|
469
|
+
_tag: "Resolved",
|
|
470
|
+
value,
|
|
471
|
+
hasInput
|
|
472
|
+
});
|
|
473
|
+
const absent = (error) => ({
|
|
474
|
+
_tag: "Absent",
|
|
475
|
+
error
|
|
476
|
+
});
|
|
477
|
+
const evaluationFailure = (error, hasInput) => ({
|
|
478
|
+
error,
|
|
479
|
+
hasInput
|
|
480
|
+
});
|
|
481
|
+
const catchSourceError = (self, hasInput) => self.pipe(catchDefect((defect) => defect instanceof SourceError ? fail(evaluationFailure(new ConfigError(defect), hasInput)) : die(defect)));
|
|
482
|
+
/**
|
|
483
|
+
* Transforms the parsed value of a config with a pure function.
|
|
484
|
+
*
|
|
485
|
+
* **When to use**
|
|
486
|
+
*
|
|
487
|
+
* Use when you need to transform a parsed config value with a function that
|
|
488
|
+
* cannot fail.
|
|
489
|
+
*
|
|
490
|
+
* **Example** (Uppercasing a string config)
|
|
491
|
+
*
|
|
492
|
+
* ```ts import.meta.vitest
|
|
493
|
+
* import { Config, ConfigProvider, Effect } from "effect"
|
|
494
|
+
*
|
|
495
|
+
* const upper = Config.string("name").pipe(
|
|
496
|
+
* Config.map((s) => s.toUpperCase())
|
|
497
|
+
* )
|
|
498
|
+
*
|
|
499
|
+
* const provider = ConfigProvider.fromUnknown({ name: "alice" })
|
|
500
|
+
* Effect.runSync(upper.parse(provider)) // => "ALICE"
|
|
501
|
+
* ```
|
|
502
|
+
*
|
|
503
|
+
* @see {@link mapOrFail} – when the transformation can fail
|
|
504
|
+
*
|
|
505
|
+
* @category mapping
|
|
506
|
+
* @since 2.0.0
|
|
507
|
+
*/
|
|
508
|
+
const map = /*#__PURE__*/ dual(2, (self, f) => {
|
|
509
|
+
return make((provider, pathPrefix) => map$1(evaluateAt(self, provider, pathPrefix), (resolution) => resolution._tag === "Resolved" ? resolved(f(resolution.value), resolution.hasInput) : resolution));
|
|
510
|
+
});
|
|
511
|
+
/**
|
|
512
|
+
* Combines multiple configs into a single config that parses all of them.
|
|
513
|
+
*
|
|
514
|
+
* **When to use**
|
|
515
|
+
*
|
|
516
|
+
* Use when you need to group related configs into a tuple or named struct.
|
|
517
|
+
*
|
|
518
|
+
* **Details**
|
|
519
|
+
*
|
|
520
|
+
* Accepts a tuple (preserves positions), an iterable, or a record of configs.
|
|
521
|
+
* Returns a config whose parsed value mirrors the input shape.
|
|
522
|
+
*
|
|
523
|
+
* A combined config is absent when at least one child cannot resolve and none
|
|
524
|
+
* of the other children read provider input. This lets {@link withDefault} and
|
|
525
|
+
* {@link option} handle a wholly absent group. Once any child reads input, a
|
|
526
|
+
* missing sibling makes the group incomplete and parsing fails. Values supplied
|
|
527
|
+
* by child defaults do not count as provider input.
|
|
528
|
+
*
|
|
529
|
+
* Unlike a `Schema.Struct` passed to {@link schema}, `all` only considers input
|
|
530
|
+
* read by its children. An explicitly present but empty parent container does
|
|
531
|
+
* not by itself make the group present.
|
|
532
|
+
*
|
|
533
|
+
* **Example** (Combining configs as a struct)
|
|
534
|
+
*
|
|
535
|
+
* ```ts import.meta.vitest
|
|
536
|
+
* import { Config, ConfigProvider, Effect } from "effect"
|
|
537
|
+
*
|
|
538
|
+
* const dbConfig = Config.all({
|
|
539
|
+
* host: Config.string("host"),
|
|
540
|
+
* port: Config.number("port")
|
|
541
|
+
* })
|
|
542
|
+
*
|
|
543
|
+
* const provider = ConfigProvider.fromUnknown({ host: "localhost", port: 5432 })
|
|
544
|
+
* Effect.runSync(dbConfig.parse(provider)) // => { host: "localhost", port: 5432 }
|
|
545
|
+
* ```
|
|
546
|
+
*
|
|
547
|
+
* @category combinators
|
|
548
|
+
* @since 2.0.0
|
|
549
|
+
*/
|
|
550
|
+
function all(arg) {
|
|
551
|
+
const configs = Array.isArray(arg) ? arg : Symbol.iterator in arg ? [...arg] : arg;
|
|
552
|
+
if (Array.isArray(configs)) return make((provider, pathPrefix) => flatMapEager(all$1(configs.map((config) => evaluateAt(config, provider, pathPrefix))), resolveArray));
|
|
553
|
+
else return make((provider, pathPrefix) => flatMapEager(all$1(map$2(configs, (config) => evaluateAt(config, provider, pathPrefix))), resolveRecord));
|
|
554
|
+
}
|
|
555
|
+
const resolveArray = (resolutions) => {
|
|
556
|
+
const values = [];
|
|
557
|
+
let firstAbsent;
|
|
558
|
+
let hasInput = false;
|
|
559
|
+
for (const resolution of resolutions) if (resolution._tag === "Absent") firstAbsent ??= resolution;
|
|
560
|
+
else {
|
|
561
|
+
values.push(resolution.value);
|
|
562
|
+
hasInput = hasInput || resolution.hasInput;
|
|
563
|
+
}
|
|
564
|
+
if (firstAbsent !== void 0) return hasInput ? fail(evaluationFailure(firstAbsent.error, true)) : succeed(firstAbsent);
|
|
565
|
+
return succeed(resolved(values, hasInput));
|
|
566
|
+
};
|
|
567
|
+
const resolveRecord = (resolutions) => {
|
|
568
|
+
const values = {};
|
|
569
|
+
let firstAbsent;
|
|
570
|
+
let hasInput = false;
|
|
571
|
+
for (const key in resolutions) {
|
|
572
|
+
const resolution = resolutions[key];
|
|
573
|
+
if (resolution._tag === "Absent") firstAbsent ??= resolution;
|
|
574
|
+
else {
|
|
575
|
+
assignProperty(values, key, resolution.value);
|
|
576
|
+
hasInput = hasInput || resolution.hasInput;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
if (firstAbsent !== void 0) return hasInput ? fail(evaluationFailure(firstAbsent.error, true)) : succeed(firstAbsent);
|
|
580
|
+
return succeed(resolved(values, hasInput));
|
|
581
|
+
};
|
|
582
|
+
/**
|
|
583
|
+
* Provides a fallback value when the config cannot resolve because none of its
|
|
584
|
+
* relevant input is present.
|
|
585
|
+
*
|
|
586
|
+
* **When to use**
|
|
587
|
+
*
|
|
588
|
+
* Use when you need to make a config key optional with a sensible default.
|
|
589
|
+
*
|
|
590
|
+
* **Gotchas**
|
|
591
|
+
*
|
|
592
|
+
* Validation errors and partially supplied groups still propagate. A schema
|
|
593
|
+
* that successfully decodes absent input also keeps its decoded value instead
|
|
594
|
+
* of using the default. Schema configs first represent a missing or
|
|
595
|
+
* incompatible provider shape as `undefined`; the default is used only when
|
|
596
|
+
* the schema rejects that value and no relevant input was found.
|
|
597
|
+
*
|
|
598
|
+
* **Example** (Defaulting a missing port)
|
|
599
|
+
*
|
|
600
|
+
* ```ts import.meta.vitest
|
|
601
|
+
* import { Config, ConfigProvider, Effect } from "effect"
|
|
602
|
+
*
|
|
603
|
+
* const port = Config.number("port").pipe(Config.withDefault(3000))
|
|
604
|
+
*
|
|
605
|
+
* const provider = ConfigProvider.fromUnknown({})
|
|
606
|
+
* Effect.runSync(port.parse(provider)) // => 3000
|
|
607
|
+
* ```
|
|
608
|
+
*
|
|
609
|
+
* @see {@link option} – returns `Option` instead of a default value
|
|
610
|
+
* @see {@link orElse} – catches all errors, not just absent input
|
|
611
|
+
*
|
|
612
|
+
* @category combinators
|
|
613
|
+
* @since 2.0.0
|
|
614
|
+
*/
|
|
615
|
+
const withDefault = /*#__PURE__*/ dual(2, (self, defaultValue) => {
|
|
616
|
+
return make((provider, pathPrefix) => mapEager(evaluateAt(self, provider, pathPrefix), (resolution) => resolution._tag === "Absent" ? resolved(defaultValue, false) : resolution));
|
|
617
|
+
});
|
|
618
|
+
/**
|
|
619
|
+
* Makes a config optional: returns `Some(value)` on success and `None` when the
|
|
620
|
+
* config cannot resolve because none of its relevant input is present.
|
|
621
|
+
*
|
|
622
|
+
* **When to use**
|
|
623
|
+
*
|
|
624
|
+
* Use when you need to handle a config key that may or may not be present.
|
|
625
|
+
*
|
|
626
|
+
* **Gotchas**
|
|
627
|
+
*
|
|
628
|
+
* Validation errors and partially supplied groups still propagate. Successful
|
|
629
|
+
* values are always wrapped in `Some`, including `undefined` when the schema
|
|
630
|
+
* explicitly accepts it. Schema configs first represent a missing or
|
|
631
|
+
* incompatible provider shape as `undefined`; `None` is returned only when the
|
|
632
|
+
* schema rejects that value and no relevant input was found.
|
|
633
|
+
*
|
|
634
|
+
* **Example** (Reading optional config)
|
|
635
|
+
*
|
|
636
|
+
* ```ts import.meta.vitest
|
|
637
|
+
* import { Config, ConfigProvider, Effect, Option } from "effect"
|
|
638
|
+
*
|
|
639
|
+
* const maybePort = Config.option(Config.number("port"))
|
|
640
|
+
*
|
|
641
|
+
* const provider = ConfigProvider.fromUnknown({})
|
|
642
|
+
* Effect.runSync(maybePort.parse(provider)) // => Option.none()
|
|
643
|
+
* ```
|
|
644
|
+
*
|
|
645
|
+
* @see {@link withDefault} – provide a concrete fallback value instead
|
|
646
|
+
*
|
|
647
|
+
* @category combinators
|
|
648
|
+
* @since 2.0.0
|
|
649
|
+
*/
|
|
650
|
+
const option = (self) => self.pipe(map(some), withDefault(none()));
|
|
651
|
+
/**
|
|
652
|
+
* Constructs a `Config<T>` from a value matching `Wrap<T>`.
|
|
653
|
+
*
|
|
654
|
+
* **When to use**
|
|
655
|
+
*
|
|
656
|
+
* Use when accepting config from callers who may pass either a single `Config` or a
|
|
657
|
+
* record of individual `Config`s.
|
|
658
|
+
*
|
|
659
|
+
* **Details**
|
|
660
|
+
*
|
|
661
|
+
* If the input is already a `Config`, it is returned as-is. Otherwise, each
|
|
662
|
+
* key is recursively unwrapped and combined.
|
|
663
|
+
*
|
|
664
|
+
* **Example** (Unwrapping a record of configs)
|
|
665
|
+
*
|
|
666
|
+
* ```ts import.meta.vitest
|
|
667
|
+
* import { Config, ConfigProvider, Effect } from "effect"
|
|
668
|
+
*
|
|
669
|
+
* interface Options {
|
|
670
|
+
* key: string
|
|
671
|
+
* }
|
|
672
|
+
*
|
|
673
|
+
* const makeConfig = (config: Config.Wrap<Options>): Config.Config<Options> =>
|
|
674
|
+
* Config.unwrap(config)
|
|
675
|
+
*
|
|
676
|
+
* const config = makeConfig({ key: Config.string("key") })
|
|
677
|
+
* const provider = ConfigProvider.fromUnknown({ key: "value" })
|
|
678
|
+
* Effect.runSync(config.parse(provider)) // => { key: "value" }
|
|
679
|
+
* ```
|
|
680
|
+
*
|
|
681
|
+
* @see {@link Wrap} – the utility type accepted by this function
|
|
682
|
+
*
|
|
683
|
+
* @category converting
|
|
684
|
+
* @since 2.0.0
|
|
685
|
+
*/
|
|
686
|
+
const unwrap = (wrapped) => {
|
|
687
|
+
if (isConfig(wrapped)) return wrapped;
|
|
688
|
+
return all(map$2(wrapped, (config) => unwrap(config)));
|
|
689
|
+
};
|
|
690
|
+
const cursorToString = () => "<configuration>";
|
|
691
|
+
const loadCursor = (provider, path) => provider.load(path).pipe(orDie, mapEager((node) => ({
|
|
692
|
+
provider,
|
|
693
|
+
path,
|
|
694
|
+
node,
|
|
695
|
+
toString: cursorToString
|
|
696
|
+
})));
|
|
697
|
+
const loadChildCursor = (cursor, segment) => loadCursor(cursor.provider, [...cursor.path, segment]);
|
|
698
|
+
const getScalar = (node) => node?.value;
|
|
699
|
+
const decodeFromCursor = (ast, decode) => decodeTo(unknown, ast, new Transformation(transformOrFail((input) => decode(input)), passthrough()));
|
|
700
|
+
const isScalarInput = (ast) => {
|
|
701
|
+
switch (ast._tag) {
|
|
702
|
+
case "Union": return ast.types.every(isScalarInput);
|
|
703
|
+
case "Objects":
|
|
704
|
+
case "Arrays":
|
|
705
|
+
case "Suspend": return false;
|
|
706
|
+
default: return true;
|
|
707
|
+
}
|
|
708
|
+
};
|
|
709
|
+
const hasProviderInput = (ast, node) => {
|
|
710
|
+
switch (ast._tag) {
|
|
711
|
+
case "Objects": return node?._tag === "Record";
|
|
712
|
+
case "Arrays": return node?._tag === "Array";
|
|
713
|
+
case "Union": return ast.types.some((ast) => hasProviderInput(ast, node));
|
|
714
|
+
case "Suspend": return hasProviderInput(ast.thunk(), node);
|
|
715
|
+
default: return getScalar(node) !== void 0;
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
const toConfigCursorAST = (root) => {
|
|
719
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
720
|
+
const recur = applyToSelfOrLastLinkEncoding((ast) => {
|
|
721
|
+
seen.add(ast);
|
|
722
|
+
switch (ast._tag) {
|
|
723
|
+
case "Objects": {
|
|
724
|
+
const matchesIndex = ast.indexSignatures.map((is) => _is(is.parameter));
|
|
725
|
+
const materialize = fnUntraced(function* (cursor) {
|
|
726
|
+
if (cursor.node?._tag !== "Record") return;
|
|
727
|
+
const node = cursor.node;
|
|
728
|
+
const keys = /* @__PURE__ */ new Set();
|
|
729
|
+
for (const property of ast.propertySignatures) if (typeof property.name === "string") keys.add(property.name);
|
|
730
|
+
if (matchesIndex.length > 0) {
|
|
731
|
+
for (const key of node.keys) if (matchesIndex.some((matches) => matches(key))) keys.add(key);
|
|
732
|
+
}
|
|
733
|
+
const out = {};
|
|
734
|
+
for (const key of keys) {
|
|
735
|
+
const child = yield* loadChildCursor(cursor, key);
|
|
736
|
+
if (child.node !== void 0) assignProperty(out, key, child);
|
|
737
|
+
}
|
|
738
|
+
return out;
|
|
739
|
+
});
|
|
740
|
+
return decodeFromCursor(ast.recur(recur, (ast) => ast), materialize);
|
|
741
|
+
}
|
|
742
|
+
case "Arrays": {
|
|
743
|
+
const materialize = fnUntraced(function* (cursor) {
|
|
744
|
+
if (cursor.node?._tag !== "Array") return;
|
|
745
|
+
const out = [];
|
|
746
|
+
for (let i = 0; i < cursor.node.length; i++) out.push(yield* loadChildCursor(cursor, i));
|
|
747
|
+
return out;
|
|
748
|
+
});
|
|
749
|
+
return decodeFromCursor(ast.recur(recur), materialize);
|
|
750
|
+
}
|
|
751
|
+
case "Union":
|
|
752
|
+
for (const member of ast.types) recur(member);
|
|
753
|
+
return isScalarInput(ast) ? decodeFromCursor(ast, (cursor) => succeed(getScalar(cursor.node))) : ast.recur(recur);
|
|
754
|
+
case "Suspend": {
|
|
755
|
+
const target = ast.thunk();
|
|
756
|
+
if (!seen.has(target)) recur(target);
|
|
757
|
+
return ast.recur(recur);
|
|
758
|
+
}
|
|
759
|
+
case "Declaration":
|
|
760
|
+
case "Any": throw new globalThis.Error("Config.schema does not support opaque StringTree encodings", { cause: ast });
|
|
761
|
+
default: return decodeFromCursor(ast, (cursor) => succeed(getScalar(cursor.node)));
|
|
762
|
+
}
|
|
763
|
+
});
|
|
764
|
+
return recur(root);
|
|
765
|
+
};
|
|
766
|
+
/**
|
|
767
|
+
* Creates a `Config<T>` from a `Schema.Codec`.
|
|
768
|
+
*
|
|
769
|
+
* **When to use**
|
|
770
|
+
*
|
|
771
|
+
* Use when you need to read structured or schema-validated configuration.
|
|
772
|
+
*
|
|
773
|
+
* **Details**
|
|
774
|
+
*
|
|
775
|
+
* The optional `path` sets the local path segment(s) for the config lookup.
|
|
776
|
+
* It is appended to the logical path prefix accumulated from outer
|
|
777
|
+
* {@link nested} calls. Pass a single string for a flat key or an array for
|
|
778
|
+
* nested paths.
|
|
779
|
+
*
|
|
780
|
+
* Convenience constructors such as `string`, `number`, and `boolean` delegate
|
|
781
|
+
* to this API.
|
|
782
|
+
*
|
|
783
|
+
* The codec is converted to its canonical `StringTree` form. Its encoded shape
|
|
784
|
+
* determines how provider data is loaded: scalar schemas read a co-located
|
|
785
|
+
* scalar value, object schemas read declared properties and matching record
|
|
786
|
+
* keys, and array schemas read indexed children. A mixed-shape union loads each
|
|
787
|
+
* member according to that member's shape before applying the union's mode and
|
|
788
|
+
* checks.
|
|
789
|
+
*
|
|
790
|
+
* At the config's lookup path, a missing node or a node that cannot provide the
|
|
791
|
+
* representation required by the schema is decoded as `undefined`. Missing
|
|
792
|
+
* object properties remain omitted so the schema's property semantics still
|
|
793
|
+
* apply. Decoding success always wins, even when no provider input was found.
|
|
794
|
+
* For example,
|
|
795
|
+
* `Schema.UndefinedOr(Schema.String)` decodes to `undefined` and is not replaced
|
|
796
|
+
* by {@link withDefault}. If decoding fails and no relevant representation was
|
|
797
|
+
* found, the config is absent. Invalid data in a relevant representation is a
|
|
798
|
+
* validation failure. Provider `SourceError`s are always failures.
|
|
799
|
+
*
|
|
800
|
+
* **Gotchas**
|
|
801
|
+
*
|
|
802
|
+
* Plain `Schema.Array` and `Schema.Record` schemas use structural provider
|
|
803
|
+
* input. Use {@link Array} or {@link Record} when a flat separated string must
|
|
804
|
+
* also be accepted.
|
|
805
|
+
*
|
|
806
|
+
* `Schema.Struct` and {@link all} describe different lookup models. An
|
|
807
|
+
* explicitly present empty object is relevant input for a struct and required
|
|
808
|
+
* fields are validated. The same empty parent container does not make an
|
|
809
|
+
* `all` group present when all of its child configs are absent.
|
|
810
|
+
*
|
|
811
|
+
* The canonical `StringTree` encoding must expose a concrete scalar, object,
|
|
812
|
+
* array, or union shape. Opaque encodings such as `Schema.Any`,
|
|
813
|
+
* `Schema.Unknown`, `Schema.ObjectKeyword`, `Schema.Json`, and
|
|
814
|
+
* `Schema.MutableJson` are rejected synchronously when this config is
|
|
815
|
+
* constructed, including when they are nested in another schema. Suspended
|
|
816
|
+
* recursive schemas remain supported when their eventual shape is concrete.
|
|
817
|
+
* Declarations such as `Schema.URL` also remain supported when their canonical
|
|
818
|
+
* encoding has a concrete shape. To read arbitrary JSON from one scalar value,
|
|
819
|
+
* use `Schema.fromJsonString(Schema.Json)`.
|
|
820
|
+
*
|
|
821
|
+
* **Example** (Reading a structured config)
|
|
822
|
+
*
|
|
823
|
+
* ```ts import.meta.vitest
|
|
824
|
+
* import { Config, ConfigProvider, Effect, Schema } from "effect"
|
|
825
|
+
*
|
|
826
|
+
* const DbConfig = Config.schema(
|
|
827
|
+
* Schema.Struct({
|
|
828
|
+
* host: Schema.String,
|
|
829
|
+
* port: Schema.Int
|
|
830
|
+
* }),
|
|
831
|
+
* "db"
|
|
832
|
+
* )
|
|
833
|
+
*
|
|
834
|
+
* const provider = ConfigProvider.fromUnknown({
|
|
835
|
+
* db: { host: "localhost", port: 5432 }
|
|
836
|
+
* })
|
|
837
|
+
*
|
|
838
|
+
* Effect.runSync(DbConfig.parse(provider)) // => { host: "localhost", port: 5432 }
|
|
839
|
+
* ```
|
|
840
|
+
*
|
|
841
|
+
* @see {@link string} / {@link number} / {@link boolean} – shortcuts for
|
|
842
|
+
* single-value configs
|
|
843
|
+
*
|
|
844
|
+
* @category schemas
|
|
845
|
+
* @since 4.0.0
|
|
846
|
+
*/
|
|
847
|
+
function schema(codec, path) {
|
|
848
|
+
const codecStringTree = toCodecStringTree(codec);
|
|
849
|
+
const encodedAst = toEncoded(codecStringTree.ast);
|
|
850
|
+
const decodeCursor = decodeUnknownEffect(make$2(toConfigCursorAST(codecStringTree.ast)));
|
|
851
|
+
const localPath = typeof path === "string" ? [path] : path ?? [];
|
|
852
|
+
return make((provider, pathPrefix) => {
|
|
853
|
+
const fullPath = [...pathPrefix, ...localPath];
|
|
854
|
+
return catchSourceError(loadCursor(provider, fullPath), false).pipe(flatMapEager((cursor) => {
|
|
855
|
+
const hasInput = hasProviderInput(encodedAst, cursor.node);
|
|
856
|
+
return catchSourceError(decodeCursor(cursor).pipe(mapEager((value) => resolved(value, hasInput)), catchEager((issue) => {
|
|
857
|
+
const error = new ConfigError(new SchemaError(fullPath.length > 0 ? new Pointer(fullPath, issue) : issue));
|
|
858
|
+
return hasInput ? fail(evaluationFailure(error, true)) : succeed(absent(error));
|
|
859
|
+
})), hasInput);
|
|
860
|
+
}));
|
|
861
|
+
});
|
|
862
|
+
}
|
|
863
|
+
/** @internal */
|
|
864
|
+
const TrueValues = /*#__PURE__*/ Literals([
|
|
865
|
+
"true",
|
|
866
|
+
"yes",
|
|
867
|
+
"on",
|
|
868
|
+
"1",
|
|
869
|
+
"y"
|
|
870
|
+
]);
|
|
871
|
+
/** @internal */
|
|
872
|
+
const FalseValues = /*#__PURE__*/ Literals([
|
|
873
|
+
"false",
|
|
874
|
+
"no",
|
|
875
|
+
"off",
|
|
876
|
+
"0",
|
|
877
|
+
"n"
|
|
878
|
+
]);
|
|
879
|
+
/**
|
|
880
|
+
* Schema for boolean values encoded as strings.
|
|
881
|
+
*
|
|
882
|
+
* **When to use**
|
|
883
|
+
*
|
|
884
|
+
* Use when you need the reusable boolean schema value for `Config.schema` with
|
|
885
|
+
* custom paths.
|
|
886
|
+
*
|
|
887
|
+
* **Details**
|
|
888
|
+
*
|
|
889
|
+
* Accepted string values: `true`, `false`, `yes`, `no`, `on`, `off`, `1`,
|
|
890
|
+
* `0`, `y`, `n` (case-sensitive).
|
|
891
|
+
*
|
|
892
|
+
* @see {@link boolean} – convenience constructor
|
|
893
|
+
*
|
|
894
|
+
* @category schemas
|
|
895
|
+
* @since 4.0.0
|
|
896
|
+
*/
|
|
897
|
+
const Boolean = /*#__PURE__*/ Literals([...TrueValues.literals, ...FalseValues.literals]).pipe(/*#__PURE__*/ decodeTo$1(Boolean$1, /*#__PURE__*/ transform({
|
|
898
|
+
decode: (value) => value === "true" || value === "yes" || value === "on" || value === "1" || value === "y",
|
|
899
|
+
encode: (value) => value ? "true" : "false"
|
|
900
|
+
})));
|
|
901
|
+
/**
|
|
902
|
+
* Schema for port numbers (integers in 1–65535).
|
|
903
|
+
*
|
|
904
|
+
* **When to use**
|
|
905
|
+
*
|
|
906
|
+
* Use when you need the reusable port schema value for `Config.schema` with
|
|
907
|
+
* custom paths.
|
|
908
|
+
*
|
|
909
|
+
* @see {@link port} – convenience constructor
|
|
910
|
+
*
|
|
911
|
+
* @category schemas
|
|
912
|
+
* @since 4.0.0
|
|
913
|
+
*/
|
|
914
|
+
const Port = /*#__PURE__*/ Int.check(/*#__PURE__*/ isBetween({
|
|
915
|
+
minimum: 1,
|
|
916
|
+
maximum: 65535
|
|
917
|
+
}));
|
|
918
|
+
/**
|
|
919
|
+
* Schema for `LogLevel` string literals.
|
|
920
|
+
*
|
|
921
|
+
* **When to use**
|
|
922
|
+
*
|
|
923
|
+
* Use when you need the reusable log-level schema value for `Config.schema`
|
|
924
|
+
* with custom paths.
|
|
925
|
+
*
|
|
926
|
+
* **Details**
|
|
927
|
+
*
|
|
928
|
+
* Accepted values: `"All"`, `"Fatal"`, `"Error"`, `"Warn"`, `"Info"`,
|
|
929
|
+
* `"Debug"`, `"Trace"`, `"None"`.
|
|
930
|
+
*
|
|
931
|
+
* @see {@link logLevel} – convenience constructor
|
|
932
|
+
*
|
|
933
|
+
* @category schemas
|
|
934
|
+
* @since 4.0.0
|
|
935
|
+
*/
|
|
936
|
+
const LogLevel = /*#__PURE__*/ Literals(values);
|
|
937
|
+
/**
|
|
938
|
+
* Schema for key-value record types that can also be parsed from
|
|
939
|
+
* a flat comma-separated string.
|
|
940
|
+
*
|
|
941
|
+
* **When to use**
|
|
942
|
+
*
|
|
943
|
+
* Use when reading key-value maps from a single env var (e.g. OpenTelemetry
|
|
944
|
+
* resource attributes).
|
|
945
|
+
*
|
|
946
|
+
* **Details**
|
|
947
|
+
*
|
|
948
|
+
* Accepts either a JSON-like record from the provider or a flat string like
|
|
949
|
+
* `"key1=val1,key2=val2"`. The `separator` (default `","`) and
|
|
950
|
+
* `keyValueSeparator` (default `"="`) can be customized.
|
|
951
|
+
*
|
|
952
|
+
* **Example** (Parsing a comma-separated record)
|
|
953
|
+
*
|
|
954
|
+
* ```ts import.meta.vitest
|
|
955
|
+
* import { Config, ConfigProvider, Effect, Schema } from "effect"
|
|
956
|
+
*
|
|
957
|
+
* const schema = Config.Record(Schema.String, Schema.String)
|
|
958
|
+
* const config = Config.schema(schema, "OTEL_RESOURCE_ATTRIBUTES")
|
|
959
|
+
*
|
|
960
|
+
* const provider = ConfigProvider.fromEnv({
|
|
961
|
+
* env: {
|
|
962
|
+
* OTEL_RESOURCE_ATTRIBUTES:
|
|
963
|
+
* "service.name=my-service,service.version=1.0.0,custom.attribute=value"
|
|
964
|
+
* }
|
|
965
|
+
* })
|
|
966
|
+
*
|
|
967
|
+
* const result = Effect.runSync(config.parse(provider))
|
|
968
|
+
* result["service.name"] // => "my-service"
|
|
969
|
+
* result["service.version"] // => "1.0.0"
|
|
970
|
+
* result["custom.attribute"] // => "value"
|
|
971
|
+
* ```
|
|
972
|
+
*
|
|
973
|
+
* @see {@link Array} for separated or structural array input
|
|
974
|
+
*
|
|
975
|
+
* @category schemas
|
|
976
|
+
* @since 4.0.0
|
|
977
|
+
*/
|
|
978
|
+
const Record = (key, value, options) => {
|
|
979
|
+
const record = Record$1(key, value);
|
|
980
|
+
const split = splitKeyValue(options);
|
|
981
|
+
return Union([record, String$1.pipe(decodeTo$1(toCodecStringTree(record), {
|
|
982
|
+
decode: split.decode,
|
|
983
|
+
encode: passthrough({ strict: false }).compose(split.encode)
|
|
984
|
+
}))]);
|
|
985
|
+
};
|
|
986
|
+
/**
|
|
987
|
+
* Creates a config for a single string value.
|
|
988
|
+
*
|
|
989
|
+
* **When to use**
|
|
990
|
+
*
|
|
991
|
+
* Use when reading a single string env var or config key.
|
|
992
|
+
*
|
|
993
|
+
* **Details**
|
|
994
|
+
*
|
|
995
|
+
* Shortcut for `Config.schema(Schema.String, name)`.
|
|
996
|
+
*
|
|
997
|
+
* **Example** (Reading a string config)
|
|
998
|
+
*
|
|
999
|
+
* ```ts import.meta.vitest
|
|
1000
|
+
* import { Config, ConfigProvider, Effect } from "effect"
|
|
1001
|
+
*
|
|
1002
|
+
* const host = Config.string("HOST")
|
|
1003
|
+
*
|
|
1004
|
+
* const provider = ConfigProvider.fromUnknown({ HOST: "localhost" })
|
|
1005
|
+
* Effect.runSync(host.parse(provider)) // => "localhost"
|
|
1006
|
+
* ```
|
|
1007
|
+
*
|
|
1008
|
+
* @see {@link nonEmptyString} – rejects empty strings
|
|
1009
|
+
* @see {@link schema} – for more complex types
|
|
1010
|
+
*
|
|
1011
|
+
* @category constructors
|
|
1012
|
+
* @since 2.0.0
|
|
1013
|
+
*/
|
|
1014
|
+
function string(name) {
|
|
1015
|
+
return schema(String$1, name);
|
|
1016
|
+
}
|
|
1017
|
+
/**
|
|
1018
|
+
* Creates a config for a numeric value (including `NaN`, `Infinity`).
|
|
1019
|
+
*
|
|
1020
|
+
* **When to use**
|
|
1021
|
+
*
|
|
1022
|
+
* Use when you need config input to accept JavaScript's full number domain,
|
|
1023
|
+
* including NaN and infinities, rather than reject non-finite values.
|
|
1024
|
+
*
|
|
1025
|
+
* **Details**
|
|
1026
|
+
*
|
|
1027
|
+
* Shortcut for `Config.schema(Schema.Number, name)`.
|
|
1028
|
+
*
|
|
1029
|
+
* @see {@link finite} for rejecting `NaN` and `Infinity`
|
|
1030
|
+
* @see {@link int} for accepting only integers
|
|
1031
|
+
*
|
|
1032
|
+
* @category constructors
|
|
1033
|
+
* @since 2.0.0
|
|
1034
|
+
*/
|
|
1035
|
+
function number(name) {
|
|
1036
|
+
return schema(Number$1, name);
|
|
1037
|
+
}
|
|
1038
|
+
/**
|
|
1039
|
+
* Creates a config for an integer value. Rejects floats.
|
|
1040
|
+
*
|
|
1041
|
+
* **When to use**
|
|
1042
|
+
*
|
|
1043
|
+
* Use to read a numeric config value that must be an integer.
|
|
1044
|
+
*
|
|
1045
|
+
* **Details**
|
|
1046
|
+
*
|
|
1047
|
+
* Shortcut for `Config.schema(Schema.Int, name)`.
|
|
1048
|
+
*
|
|
1049
|
+
* @see {@link number} for accepting any number
|
|
1050
|
+
* @see {@link port} for accepting only integers in `1` through `65535`
|
|
1051
|
+
*
|
|
1052
|
+
* @category constructors
|
|
1053
|
+
* @since 4.0.0
|
|
1054
|
+
*/
|
|
1055
|
+
function int(name) {
|
|
1056
|
+
return schema(Int, name);
|
|
1057
|
+
}
|
|
1058
|
+
/**
|
|
1059
|
+
* Creates a config for a boolean value parsed from common string
|
|
1060
|
+
* representations.
|
|
1061
|
+
*
|
|
1062
|
+
* **When to use**
|
|
1063
|
+
*
|
|
1064
|
+
* Use to read boolean flags from string-like config sources.
|
|
1065
|
+
*
|
|
1066
|
+
* **Details**
|
|
1067
|
+
*
|
|
1068
|
+
* Shortcut for `Config.schema(Config.Boolean, name)`.
|
|
1069
|
+
*
|
|
1070
|
+
* Accepted values: `true`, `false`, `yes`, `no`, `on`, `off`, `1`, `0`,
|
|
1071
|
+
* `y`, `n`.
|
|
1072
|
+
*
|
|
1073
|
+
* **Example** (Reading a boolean flag)
|
|
1074
|
+
*
|
|
1075
|
+
* ```ts import.meta.vitest
|
|
1076
|
+
* import { Config, ConfigProvider, Effect } from "effect"
|
|
1077
|
+
*
|
|
1078
|
+
* const program = Config.boolean("FEATURE_FLAG")
|
|
1079
|
+
*
|
|
1080
|
+
* const provider = ConfigProvider.fromEnv({
|
|
1081
|
+
* env: {
|
|
1082
|
+
* FEATURE_FLAG: "yes"
|
|
1083
|
+
* }
|
|
1084
|
+
* })
|
|
1085
|
+
*
|
|
1086
|
+
* Effect.runSync(
|
|
1087
|
+
* program.pipe(Effect.provideService(ConfigProvider.ConfigProvider, provider))
|
|
1088
|
+
* ) // => true
|
|
1089
|
+
* ```
|
|
1090
|
+
*
|
|
1091
|
+
* @see {@link Boolean} for the underlying boolean codec
|
|
1092
|
+
*
|
|
1093
|
+
* @category constructors
|
|
1094
|
+
* @since 2.0.0
|
|
1095
|
+
*/
|
|
1096
|
+
function boolean(name) {
|
|
1097
|
+
return schema(Boolean, name);
|
|
1098
|
+
}
|
|
1099
|
+
/**
|
|
1100
|
+
* Creates a config for a port number (integer in 1–65535).
|
|
1101
|
+
*
|
|
1102
|
+
* **When to use**
|
|
1103
|
+
*
|
|
1104
|
+
* Use to read network port settings that must be valid port numbers.
|
|
1105
|
+
*
|
|
1106
|
+
* **Details**
|
|
1107
|
+
*
|
|
1108
|
+
* Shortcut for `Config.schema(Config.Port, name)`.
|
|
1109
|
+
*
|
|
1110
|
+
* **Example** (Reading a port)
|
|
1111
|
+
*
|
|
1112
|
+
* ```ts import.meta.vitest
|
|
1113
|
+
* import { Config, ConfigProvider, Effect } from "effect"
|
|
1114
|
+
*
|
|
1115
|
+
* const program = Config.port("PORT")
|
|
1116
|
+
*
|
|
1117
|
+
* const provider = ConfigProvider.fromEnv({
|
|
1118
|
+
* env: {
|
|
1119
|
+
* PORT: "8080"
|
|
1120
|
+
* }
|
|
1121
|
+
* })
|
|
1122
|
+
*
|
|
1123
|
+
* Effect.runSync(
|
|
1124
|
+
* program.pipe(Effect.provideService(ConfigProvider.ConfigProvider, provider))
|
|
1125
|
+
* ) // => 8080
|
|
1126
|
+
* ```
|
|
1127
|
+
*
|
|
1128
|
+
* @see {@link int} for integer config values outside the port range
|
|
1129
|
+
* @see {@link Port} for the underlying port codec
|
|
1130
|
+
*
|
|
1131
|
+
* @category constructors
|
|
1132
|
+
* @since 3.16.0
|
|
1133
|
+
*/
|
|
1134
|
+
function port(name) {
|
|
1135
|
+
return schema(Port, name);
|
|
1136
|
+
}
|
|
1137
|
+
/**
|
|
1138
|
+
* Creates a config for a log level string.
|
|
1139
|
+
*
|
|
1140
|
+
* **When to use**
|
|
1141
|
+
*
|
|
1142
|
+
* Use to read Effect log-level settings from configuration.
|
|
1143
|
+
*
|
|
1144
|
+
* **Details**
|
|
1145
|
+
*
|
|
1146
|
+
* Shortcut for `Config.schema(Config.LogLevel, name)`.
|
|
1147
|
+
*
|
|
1148
|
+
* Accepted values: `"All"`, `"Fatal"`, `"Error"`, `"Warn"`, `"Info"`,
|
|
1149
|
+
* `"Debug"`, `"Trace"`, `"None"`.
|
|
1150
|
+
*
|
|
1151
|
+
* **Example** (Reading a log level)
|
|
1152
|
+
*
|
|
1153
|
+
* ```ts import.meta.vitest
|
|
1154
|
+
* import { Config, ConfigProvider, Effect } from "effect"
|
|
1155
|
+
*
|
|
1156
|
+
* const program = Config.logLevel("LOG_LEVEL")
|
|
1157
|
+
*
|
|
1158
|
+
* const provider = ConfigProvider.fromEnv({
|
|
1159
|
+
* env: {
|
|
1160
|
+
* LOG_LEVEL: "Info"
|
|
1161
|
+
* }
|
|
1162
|
+
* })
|
|
1163
|
+
*
|
|
1164
|
+
* Effect.runSync(
|
|
1165
|
+
* program.pipe(Effect.provideService(ConfigProvider.ConfigProvider, provider))
|
|
1166
|
+
* ) // => "Info"
|
|
1167
|
+
* ```
|
|
1168
|
+
*
|
|
1169
|
+
* @see {@link LogLevel} for the underlying log-level codec
|
|
1170
|
+
*
|
|
1171
|
+
* @category constructors
|
|
1172
|
+
* @since 2.0.0
|
|
1173
|
+
*/
|
|
1174
|
+
function logLevel(name) {
|
|
1175
|
+
return schema(LogLevel, name);
|
|
1176
|
+
}
|
|
1177
|
+
/**
|
|
1178
|
+
* Creates a config for a `URL` value parsed from a string.
|
|
1179
|
+
*
|
|
1180
|
+
* **When to use**
|
|
1181
|
+
*
|
|
1182
|
+
* Use to read configuration values that must be valid URL strings.
|
|
1183
|
+
*
|
|
1184
|
+
* **Details**
|
|
1185
|
+
*
|
|
1186
|
+
* This is a shortcut for `Config.schema(Schema.URL, name)`.
|
|
1187
|
+
*
|
|
1188
|
+
* **Gotchas**
|
|
1189
|
+
*
|
|
1190
|
+
* Fails if the string cannot be parsed by the `URL` constructor.
|
|
1191
|
+
*
|
|
1192
|
+
* **Example** (Reading a URL)
|
|
1193
|
+
*
|
|
1194
|
+
* ```ts import.meta.vitest
|
|
1195
|
+
* import { Config, ConfigProvider, Effect } from "effect"
|
|
1196
|
+
*
|
|
1197
|
+
* const program = Config.url("URL").pipe(Effect.map((url) => url.href))
|
|
1198
|
+
*
|
|
1199
|
+
* const provider = ConfigProvider.fromEnv({
|
|
1200
|
+
* env: {
|
|
1201
|
+
* URL: "https://example.com"
|
|
1202
|
+
* }
|
|
1203
|
+
* })
|
|
1204
|
+
*
|
|
1205
|
+
* Effect.runSync(
|
|
1206
|
+
* program.pipe(Effect.provideService(ConfigProvider.ConfigProvider, provider))
|
|
1207
|
+
* ) // => "https://example.com/"
|
|
1208
|
+
* ```
|
|
1209
|
+
*
|
|
1210
|
+
* @see {@link schema} for decoding configuration values with a custom codec
|
|
1211
|
+
*
|
|
1212
|
+
* @category constructors
|
|
1213
|
+
* @since 3.11.0
|
|
1214
|
+
*/
|
|
1215
|
+
function url(name) {
|
|
1216
|
+
return schema(URL, name);
|
|
1217
|
+
}
|
|
1218
|
+
//#endregion
|
|
1219
|
+
export { withDefault as _, all as a, logLevel as c, option as d, port as f, url as g, unwrap as h, TrueValues as i, map as l, string as m, FalseValues as n, boolean as o, schema as p, Record as r, int as s, Boolean as t, number as u };
|
|
1220
|
+
|
|
1221
|
+
//# sourceMappingURL=Config-Bj2ZPCsP.mjs.map
|