@optique/config 1.0.0-dev.429 → 1.0.0-dev.431
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 +4 -3
- package/dist/index.cjs +372 -11
- package/dist/index.d.cts +244 -2
- package/dist/index.d.ts +244 -2
- package/dist/index.js +339 -1
- package/package.json +2 -10
- package/dist/index-0XaZnIP1.d.ts +0 -192
- package/dist/index-BZLEbR0f.d.cts +0 -192
- package/dist/run.cjs +0 -127
- package/dist/run.d.cts +0 -323
- package/dist/run.d.ts +0 -323
- package/dist/run.js +0 -127
- package/dist/src-DaFxoeAp.js +0 -271
- package/dist/src-loxvrkxq.cjs +0 -359
package/README.md
CHANGED
|
@@ -29,11 +29,11 @@ Quick start
|
|
|
29
29
|
~~~~ typescript
|
|
30
30
|
import { z } from "zod";
|
|
31
31
|
import { createConfigContext, bindConfig } from "@optique/config";
|
|
32
|
-
import { runWithConfig } from "@optique/config/run";
|
|
33
32
|
import { object } from "@optique/core/constructs";
|
|
34
33
|
import { option } from "@optique/core/primitives";
|
|
35
34
|
import { string, integer } from "@optique/core/valueparser";
|
|
36
35
|
import { withDefault } from "@optique/core/modifiers";
|
|
36
|
+
import { runAsync } from "@optique/run";
|
|
37
37
|
|
|
38
38
|
// 1. Define config schema
|
|
39
39
|
const configSchema = z.object({
|
|
@@ -58,8 +58,9 @@ const parser = object({
|
|
|
58
58
|
}),
|
|
59
59
|
});
|
|
60
60
|
|
|
61
|
-
// 3. Run with config support
|
|
62
|
-
const result = await
|
|
61
|
+
// 3. Run with config support via contexts
|
|
62
|
+
const result = await runAsync(parser, {
|
|
63
|
+
contexts: [configContext],
|
|
63
64
|
getConfigPath: (parsed) => parsed.config,
|
|
64
65
|
args: process.argv.slice(2),
|
|
65
66
|
});
|
package/dist/index.cjs
CHANGED
|
@@ -1,12 +1,373 @@
|
|
|
1
|
-
|
|
1
|
+
//#region rolldown:runtime
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
2
22
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
23
|
+
//#endregion
|
|
24
|
+
const node_fs_promises = __toESM(require("node:fs/promises"));
|
|
25
|
+
const node_path = __toESM(require("node:path"));
|
|
26
|
+
const __optique_core_annotations = __toESM(require("@optique/core/annotations"));
|
|
27
|
+
const __optique_core_message = __toESM(require("@optique/core/message"));
|
|
28
|
+
|
|
29
|
+
//#region src/index.ts
|
|
30
|
+
/**
|
|
31
|
+
* Unique symbol for config data in annotations.
|
|
32
|
+
* @since 0.10.0
|
|
33
|
+
*/
|
|
34
|
+
const configKey = Symbol.for("@optique/config");
|
|
35
|
+
/**
|
|
36
|
+
* Unique symbol for config metadata in annotations.
|
|
37
|
+
* @since 1.0.0
|
|
38
|
+
*/
|
|
39
|
+
const configMetaKey = Symbol.for("@optique/config/meta");
|
|
40
|
+
/**
|
|
41
|
+
* Internal registry for active config data during config context execution.
|
|
42
|
+
* This is a workaround for the limitation that object() doesn't propagate
|
|
43
|
+
* annotations to child field parsers.
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
46
|
+
const activeConfigRegistry = /* @__PURE__ */ new Map();
|
|
47
|
+
/**
|
|
48
|
+
* Internal registry for active config metadata during config context execution.
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
51
|
+
const activeConfigMetaRegistry = /* @__PURE__ */ new Map();
|
|
52
|
+
/**
|
|
53
|
+
* Sets active config data for a context.
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
function setActiveConfig(contextId, data) {
|
|
57
|
+
activeConfigRegistry.set(contextId, data);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Gets active config data for a context.
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
function getActiveConfig(contextId) {
|
|
64
|
+
return activeConfigRegistry.get(contextId);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Clears active config data for a context.
|
|
68
|
+
* @internal
|
|
69
|
+
*/
|
|
70
|
+
function clearActiveConfig(contextId) {
|
|
71
|
+
activeConfigRegistry.delete(contextId);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Sets active config metadata for a context.
|
|
75
|
+
* @internal
|
|
76
|
+
*/
|
|
77
|
+
function setActiveConfigMeta(contextId, meta) {
|
|
78
|
+
activeConfigMetaRegistry.set(contextId, meta);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Gets active config metadata for a context.
|
|
82
|
+
* @internal
|
|
83
|
+
*/
|
|
84
|
+
function getActiveConfigMeta(contextId) {
|
|
85
|
+
return activeConfigMetaRegistry.get(contextId);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Clears active config metadata for a context.
|
|
89
|
+
* @internal
|
|
90
|
+
*/
|
|
91
|
+
function clearActiveConfigMeta(contextId) {
|
|
92
|
+
activeConfigMetaRegistry.delete(contextId);
|
|
93
|
+
}
|
|
94
|
+
function isErrnoException(error) {
|
|
95
|
+
return typeof error === "object" && error !== null && "code" in error;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Validates raw data against a Standard Schema and returns the validated value.
|
|
99
|
+
* @internal
|
|
100
|
+
*/
|
|
101
|
+
async function validateWithSchema(schema, rawData) {
|
|
102
|
+
const validation = schema["~standard"].validate(rawData);
|
|
103
|
+
const validationResult = validation instanceof Promise ? await validation : validation;
|
|
104
|
+
if (validationResult.issues) {
|
|
105
|
+
const firstIssue = validationResult.issues[0];
|
|
106
|
+
throw new Error(`Config validation failed: ${firstIssue?.message ?? "Unknown error"}`);
|
|
107
|
+
}
|
|
108
|
+
return validationResult.value;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Creates a config context for use with Optique parsers.
|
|
112
|
+
*
|
|
113
|
+
* The config context implements the `SourceContext` interface and can be used
|
|
114
|
+
* with `runWith()` from *@optique/core* or `run()`/`runAsync()` from
|
|
115
|
+
* *@optique/run* to provide configuration file support.
|
|
116
|
+
*
|
|
117
|
+
* @template T The output type of the config schema.
|
|
118
|
+
* @template TConfigMeta The metadata type for config sources.
|
|
119
|
+
* @param options Configuration options including schema and optional file
|
|
120
|
+
* parser.
|
|
121
|
+
* @returns A config context that can be used with `bindConfig()` and runners.
|
|
122
|
+
* @since 0.10.0
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* import { z } from "zod";
|
|
127
|
+
* import { createConfigContext } from "@optique/config";
|
|
128
|
+
*
|
|
129
|
+
* const schema = z.object({
|
|
130
|
+
* host: z.string(),
|
|
131
|
+
* port: z.number(),
|
|
132
|
+
* });
|
|
133
|
+
*
|
|
134
|
+
* const configContext = createConfigContext({ schema });
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
function createConfigContext(options) {
|
|
138
|
+
const contextId = Symbol.for(`@optique/config:${Math.random()}`);
|
|
139
|
+
return {
|
|
140
|
+
id: contextId,
|
|
141
|
+
schema: options.schema,
|
|
142
|
+
async getAnnotations(parsed, runtimeOptions) {
|
|
143
|
+
if (!parsed) return {};
|
|
144
|
+
const opts = runtimeOptions;
|
|
145
|
+
if (!opts || !opts.getConfigPath && !opts.load) throw new TypeError("Either getConfigPath or load must be provided in the runner options when using ConfigContext.");
|
|
146
|
+
let configData;
|
|
147
|
+
let configMeta;
|
|
148
|
+
const parsedValue = parsed;
|
|
149
|
+
if (opts.load) {
|
|
150
|
+
const loaded = await Promise.resolve(opts.load(parsedValue));
|
|
151
|
+
configData = await validateWithSchema(options.schema, loaded.config);
|
|
152
|
+
configMeta = loaded.meta;
|
|
153
|
+
} else if (opts.getConfigPath) {
|
|
154
|
+
const configPath = opts.getConfigPath(parsedValue);
|
|
155
|
+
if (configPath) {
|
|
156
|
+
const absoluteConfigPath = (0, node_path.resolve)(configPath);
|
|
157
|
+
const singleFileMeta = {
|
|
158
|
+
configDir: (0, node_path.dirname)(absoluteConfigPath),
|
|
159
|
+
configPath: absoluteConfigPath
|
|
160
|
+
};
|
|
161
|
+
try {
|
|
162
|
+
const contents = await (0, node_fs_promises.readFile)(absoluteConfigPath);
|
|
163
|
+
let rawData;
|
|
164
|
+
if (options.fileParser) rawData = options.fileParser(contents);
|
|
165
|
+
else {
|
|
166
|
+
const text = new TextDecoder().decode(contents);
|
|
167
|
+
rawData = JSON.parse(text);
|
|
168
|
+
}
|
|
169
|
+
configData = await validateWithSchema(options.schema, rawData);
|
|
170
|
+
configMeta = singleFileMeta;
|
|
171
|
+
} catch (error) {
|
|
172
|
+
if (isErrnoException(error) && error.code === "ENOENT") configData = void 0;
|
|
173
|
+
else if (error instanceof SyntaxError) throw new Error(`Failed to parse config file ${absoluteConfigPath}: ${error.message}`);
|
|
174
|
+
else throw error;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (configData !== void 0 && configData !== null) {
|
|
179
|
+
setActiveConfig(contextId, configData);
|
|
180
|
+
if (configMeta !== void 0) {
|
|
181
|
+
setActiveConfigMeta(contextId, configMeta);
|
|
182
|
+
return {
|
|
183
|
+
[configKey]: configData,
|
|
184
|
+
[configMetaKey]: configMeta
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
return { [configKey]: configData };
|
|
188
|
+
}
|
|
189
|
+
return {};
|
|
190
|
+
},
|
|
191
|
+
[Symbol.dispose]() {
|
|
192
|
+
clearActiveConfig(contextId);
|
|
193
|
+
clearActiveConfigMeta(contextId);
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Binds a parser to configuration values with fallback priority.
|
|
199
|
+
*
|
|
200
|
+
* The binding implements the following priority order:
|
|
201
|
+
* 1. CLI argument (if provided)
|
|
202
|
+
* 2. Config file value (if available)
|
|
203
|
+
* 3. Default value (if specified)
|
|
204
|
+
* 4. Error (if none of the above)
|
|
205
|
+
*
|
|
206
|
+
* @template M The parser mode (sync or async).
|
|
207
|
+
* @template TValue The parser value type.
|
|
208
|
+
* @template TState The parser state type.
|
|
209
|
+
* @template T The config data type.
|
|
210
|
+
* @param parser The parser to bind to config values.
|
|
211
|
+
* @param options Binding options including context, key, and default.
|
|
212
|
+
* @returns A new parser with config fallback behavior.
|
|
213
|
+
* @since 0.10.0
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* ```typescript
|
|
217
|
+
* import { bindConfig } from "@optique/config";
|
|
218
|
+
* import { option } from "@optique/core/primitives";
|
|
219
|
+
* import { string } from "@optique/core/valueparser";
|
|
220
|
+
*
|
|
221
|
+
* const hostParser = bindConfig(option("--host", string()), {
|
|
222
|
+
* context: configContext,
|
|
223
|
+
* key: "host",
|
|
224
|
+
* default: "localhost",
|
|
225
|
+
* });
|
|
226
|
+
* ```
|
|
227
|
+
*/
|
|
228
|
+
function bindConfig(parser, options) {
|
|
229
|
+
return {
|
|
230
|
+
$mode: parser.$mode,
|
|
231
|
+
$valueType: parser.$valueType,
|
|
232
|
+
$stateType: parser.$stateType,
|
|
233
|
+
priority: parser.priority,
|
|
234
|
+
usage: options.default !== void 0 ? [{
|
|
235
|
+
type: "optional",
|
|
236
|
+
terms: parser.usage
|
|
237
|
+
}] : parser.usage,
|
|
238
|
+
initialState: parser.initialState,
|
|
239
|
+
parse: (context) => {
|
|
240
|
+
const annotations = (0, __optique_core_annotations.getAnnotations)(context.state);
|
|
241
|
+
const result = parser.parse(context);
|
|
242
|
+
if (!(result instanceof Promise)) {
|
|
243
|
+
if (result.success) {
|
|
244
|
+
const newState$1 = {
|
|
245
|
+
hasCliValue: true,
|
|
246
|
+
cliState: result.next.state,
|
|
247
|
+
...annotations && { [__optique_core_annotations.annotationKey]: annotations }
|
|
248
|
+
};
|
|
249
|
+
return {
|
|
250
|
+
success: true,
|
|
251
|
+
next: {
|
|
252
|
+
...result.next,
|
|
253
|
+
state: newState$1
|
|
254
|
+
},
|
|
255
|
+
consumed: result.consumed
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
const newState = {
|
|
259
|
+
hasCliValue: false,
|
|
260
|
+
...annotations && { [__optique_core_annotations.annotationKey]: annotations }
|
|
261
|
+
};
|
|
262
|
+
return {
|
|
263
|
+
success: true,
|
|
264
|
+
next: {
|
|
265
|
+
...context,
|
|
266
|
+
state: newState
|
|
267
|
+
},
|
|
268
|
+
consumed: []
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
return result.then((res) => {
|
|
272
|
+
if (res.success) {
|
|
273
|
+
const newState$1 = {
|
|
274
|
+
hasCliValue: true,
|
|
275
|
+
cliState: res.next.state,
|
|
276
|
+
...annotations && { [__optique_core_annotations.annotationKey]: annotations }
|
|
277
|
+
};
|
|
278
|
+
return {
|
|
279
|
+
success: true,
|
|
280
|
+
next: {
|
|
281
|
+
...res.next,
|
|
282
|
+
state: newState$1
|
|
283
|
+
},
|
|
284
|
+
consumed: res.consumed
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
const newState = {
|
|
288
|
+
hasCliValue: false,
|
|
289
|
+
...annotations && { [__optique_core_annotations.annotationKey]: annotations }
|
|
290
|
+
};
|
|
291
|
+
return {
|
|
292
|
+
success: true,
|
|
293
|
+
next: {
|
|
294
|
+
...context,
|
|
295
|
+
state: newState
|
|
296
|
+
},
|
|
297
|
+
consumed: []
|
|
298
|
+
};
|
|
299
|
+
});
|
|
300
|
+
},
|
|
301
|
+
complete: (state) => {
|
|
302
|
+
const bindState = state;
|
|
303
|
+
if (bindState?.hasCliValue && bindState.cliState !== void 0) {
|
|
304
|
+
const innerResult = parser.complete(bindState.cliState);
|
|
305
|
+
if (innerResult instanceof Promise) return innerResult.then((res) => {
|
|
306
|
+
if (res.success) return {
|
|
307
|
+
success: true,
|
|
308
|
+
value: res.value
|
|
309
|
+
};
|
|
310
|
+
return res;
|
|
311
|
+
});
|
|
312
|
+
if (innerResult.success) return {
|
|
313
|
+
success: true,
|
|
314
|
+
value: innerResult.value
|
|
315
|
+
};
|
|
316
|
+
return innerResult;
|
|
317
|
+
}
|
|
318
|
+
return getConfigOrDefault(state, options);
|
|
319
|
+
},
|
|
320
|
+
suggest: parser.suggest,
|
|
321
|
+
getDocFragments(state, upperDefaultValue) {
|
|
322
|
+
const defaultValue = upperDefaultValue ?? options.default;
|
|
323
|
+
return parser.getDocFragments(state, defaultValue);
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Helper function to get value from config or default.
|
|
329
|
+
* Checks both annotations (for top-level parsers) and the active config
|
|
330
|
+
* registry (for parsers nested inside object() when used with context-aware
|
|
331
|
+
* runners).
|
|
332
|
+
*/
|
|
333
|
+
function getConfigOrDefault(state, options) {
|
|
334
|
+
const annotations = (0, __optique_core_annotations.getAnnotations)(state);
|
|
335
|
+
let configData = annotations?.[configKey];
|
|
336
|
+
let configMeta = annotations?.[configMetaKey];
|
|
337
|
+
if (configData === void 0 || configData === null) {
|
|
338
|
+
const contextId = options.context.id;
|
|
339
|
+
configData = getActiveConfig(contextId);
|
|
340
|
+
configMeta = getActiveConfigMeta(contextId);
|
|
341
|
+
}
|
|
342
|
+
let configValue;
|
|
343
|
+
if (configData !== void 0 && configData !== null) if (typeof options.key === "function") try {
|
|
344
|
+
configValue = options.key(configData, configMeta);
|
|
345
|
+
} catch {
|
|
346
|
+
configValue = void 0;
|
|
347
|
+
}
|
|
348
|
+
else configValue = configData[options.key];
|
|
349
|
+
if (configValue !== void 0) return {
|
|
350
|
+
success: true,
|
|
351
|
+
value: configValue
|
|
352
|
+
};
|
|
353
|
+
if (options.default !== void 0) return {
|
|
354
|
+
success: true,
|
|
355
|
+
value: options.default
|
|
356
|
+
};
|
|
357
|
+
return {
|
|
358
|
+
success: false,
|
|
359
|
+
error: __optique_core_message.message`Missing required configuration value.`
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
//#endregion
|
|
364
|
+
exports.bindConfig = bindConfig;
|
|
365
|
+
exports.clearActiveConfig = clearActiveConfig;
|
|
366
|
+
exports.clearActiveConfigMeta = clearActiveConfigMeta;
|
|
367
|
+
exports.configKey = configKey;
|
|
368
|
+
exports.configMetaKey = configMetaKey;
|
|
369
|
+
exports.createConfigContext = createConfigContext;
|
|
370
|
+
exports.getActiveConfig = getActiveConfig;
|
|
371
|
+
exports.getActiveConfigMeta = getActiveConfigMeta;
|
|
372
|
+
exports.setActiveConfig = setActiveConfig;
|
|
373
|
+
exports.setActiveConfigMeta = setActiveConfigMeta;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,2 +1,244 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
|
+
import { ParserValuePlaceholder, SourceContext } from "@optique/core/context";
|
|
3
|
+
import { Parser } from "@optique/core/parser";
|
|
4
|
+
|
|
5
|
+
//#region src/index.d.ts
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Unique symbol for config data in annotations.
|
|
9
|
+
* @since 0.10.0
|
|
10
|
+
*/
|
|
11
|
+
declare const configKey: unique symbol;
|
|
12
|
+
/**
|
|
13
|
+
* Unique symbol for config metadata in annotations.
|
|
14
|
+
* @since 1.0.0
|
|
15
|
+
*/
|
|
16
|
+
declare const configMetaKey: unique symbol;
|
|
17
|
+
/**
|
|
18
|
+
* Metadata about the loaded config source.
|
|
19
|
+
*
|
|
20
|
+
* @since 1.0.0
|
|
21
|
+
*/
|
|
22
|
+
interface ConfigMeta {
|
|
23
|
+
/**
|
|
24
|
+
* Directory containing the config file.
|
|
25
|
+
*/
|
|
26
|
+
readonly configDir: string;
|
|
27
|
+
/**
|
|
28
|
+
* Absolute path to the config file.
|
|
29
|
+
*/
|
|
30
|
+
readonly configPath: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Sets active config data for a context.
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
declare function setActiveConfig<T>(contextId: symbol, data: T): void;
|
|
37
|
+
/**
|
|
38
|
+
* Gets active config data for a context.
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
declare function getActiveConfig<T>(contextId: symbol): T | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* Clears active config data for a context.
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
46
|
+
declare function clearActiveConfig(contextId: symbol): void;
|
|
47
|
+
/**
|
|
48
|
+
* Sets active config metadata for a context.
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
51
|
+
declare function setActiveConfigMeta<T>(contextId: symbol, meta: T): void;
|
|
52
|
+
/**
|
|
53
|
+
* Gets active config metadata for a context.
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
declare function getActiveConfigMeta<T>(contextId: symbol): T | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Clears active config metadata for a context.
|
|
59
|
+
* @internal
|
|
60
|
+
*/
|
|
61
|
+
declare function clearActiveConfigMeta(contextId: symbol): void;
|
|
62
|
+
/**
|
|
63
|
+
* Options for creating a config context.
|
|
64
|
+
*
|
|
65
|
+
* @template T The output type of the config schema.
|
|
66
|
+
* @since 0.10.0
|
|
67
|
+
*/
|
|
68
|
+
interface ConfigContextOptions<T> {
|
|
69
|
+
/**
|
|
70
|
+
* Standard Schema validator for the config file.
|
|
71
|
+
* Accepts any Standard Schema-compatible library (Zod, Valibot, ArkType, etc.).
|
|
72
|
+
*/
|
|
73
|
+
readonly schema: StandardSchemaV1<unknown, T>;
|
|
74
|
+
/**
|
|
75
|
+
* Custom parser function for reading config file contents.
|
|
76
|
+
* If not provided, defaults to JSON.parse.
|
|
77
|
+
*
|
|
78
|
+
* This option is only used in single-file mode (with `getConfigPath`).
|
|
79
|
+
* When using the `load` callback, file parsing is handled by the loader.
|
|
80
|
+
*
|
|
81
|
+
* @param contents The raw file contents as Uint8Array.
|
|
82
|
+
* @returns The parsed config data (will be validated by schema).
|
|
83
|
+
* @since 1.0.0
|
|
84
|
+
*/
|
|
85
|
+
readonly fileParser?: (contents: Uint8Array) => unknown;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Result type for custom config loading.
|
|
89
|
+
*
|
|
90
|
+
* @template TConfigMeta Metadata type associated with loaded config data.
|
|
91
|
+
* @since 1.0.0
|
|
92
|
+
*/
|
|
93
|
+
interface ConfigLoadResult<TConfigMeta = ConfigMeta> {
|
|
94
|
+
/**
|
|
95
|
+
* Raw config data to validate against the schema.
|
|
96
|
+
*/
|
|
97
|
+
readonly config: unknown;
|
|
98
|
+
/**
|
|
99
|
+
* Metadata about where the config came from.
|
|
100
|
+
*/
|
|
101
|
+
readonly meta: TConfigMeta;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Required options for ConfigContext when used with `runWith()` or `run()`.
|
|
105
|
+
* The `ParserValuePlaceholder` will be substituted with the actual parser
|
|
106
|
+
* result type by `runWith()`.
|
|
107
|
+
*
|
|
108
|
+
* Provide *either* `getConfigPath` (single-file mode) *or* `load` (custom
|
|
109
|
+
* multi-file mode). At least one must be provided; a runtime error is
|
|
110
|
+
* thrown otherwise.
|
|
111
|
+
*
|
|
112
|
+
* @template TConfigMeta Metadata type for config sources.
|
|
113
|
+
* @since 0.10.0
|
|
114
|
+
*/
|
|
115
|
+
interface ConfigContextRequiredOptions<TConfigMeta = ConfigMeta> {
|
|
116
|
+
/**
|
|
117
|
+
* Function to extract config file path from parsed CLI arguments.
|
|
118
|
+
* Used in single-file mode. The `parsed` parameter is typed as the
|
|
119
|
+
* parser's result type.
|
|
120
|
+
*
|
|
121
|
+
* @param parsed The parsed CLI arguments (typed from parser).
|
|
122
|
+
* @returns The config file path, or undefined if not specified.
|
|
123
|
+
*/
|
|
124
|
+
readonly getConfigPath?: (parsed: ParserValuePlaceholder) => string | undefined;
|
|
125
|
+
/**
|
|
126
|
+
* Custom loader function that receives the first-pass parse result and
|
|
127
|
+
* returns the config data (or a Promise of it). This allows full control
|
|
128
|
+
* over file discovery, loading, merging, and error handling.
|
|
129
|
+
*
|
|
130
|
+
* The returned data will be validated against the schema.
|
|
131
|
+
*
|
|
132
|
+
* When `load` is provided, `getConfigPath` is ignored.
|
|
133
|
+
*
|
|
134
|
+
* @param parsed The result from the first parse pass.
|
|
135
|
+
* @returns Config data and metadata (config is validated by schema).
|
|
136
|
+
* @since 1.0.0
|
|
137
|
+
*/
|
|
138
|
+
readonly load?: (parsed: ParserValuePlaceholder) => Promise<ConfigLoadResult<TConfigMeta>> | ConfigLoadResult<TConfigMeta>;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* A config context that provides configuration data via annotations.
|
|
142
|
+
*
|
|
143
|
+
* When used with `runWith()` or `run()`, the options must include either
|
|
144
|
+
* `getConfigPath` or `load` with the correct parser result type. The
|
|
145
|
+
* `ParserValuePlaceholder` in `ConfigContextRequiredOptions` is substituted
|
|
146
|
+
* with the actual parser type.
|
|
147
|
+
*
|
|
148
|
+
* @template T The validated config data type.
|
|
149
|
+
* @template TConfigMeta Metadata type for config sources.
|
|
150
|
+
* @since 0.10.0
|
|
151
|
+
*/
|
|
152
|
+
interface ConfigContext<T, TConfigMeta = ConfigMeta> extends SourceContext<ConfigContextRequiredOptions<TConfigMeta>> {
|
|
153
|
+
/**
|
|
154
|
+
* The Standard Schema validator for the config file.
|
|
155
|
+
*/
|
|
156
|
+
readonly schema: StandardSchemaV1<unknown, T>;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Creates a config context for use with Optique parsers.
|
|
160
|
+
*
|
|
161
|
+
* The config context implements the `SourceContext` interface and can be used
|
|
162
|
+
* with `runWith()` from *@optique/core* or `run()`/`runAsync()` from
|
|
163
|
+
* *@optique/run* to provide configuration file support.
|
|
164
|
+
*
|
|
165
|
+
* @template T The output type of the config schema.
|
|
166
|
+
* @template TConfigMeta The metadata type for config sources.
|
|
167
|
+
* @param options Configuration options including schema and optional file
|
|
168
|
+
* parser.
|
|
169
|
+
* @returns A config context that can be used with `bindConfig()` and runners.
|
|
170
|
+
* @since 0.10.0
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```typescript
|
|
174
|
+
* import { z } from "zod";
|
|
175
|
+
* import { createConfigContext } from "@optique/config";
|
|
176
|
+
*
|
|
177
|
+
* const schema = z.object({
|
|
178
|
+
* host: z.string(),
|
|
179
|
+
* port: z.number(),
|
|
180
|
+
* });
|
|
181
|
+
*
|
|
182
|
+
* const configContext = createConfigContext({ schema });
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
declare function createConfigContext<T, TConfigMeta = ConfigMeta>(options: ConfigContextOptions<T>): ConfigContext<T, TConfigMeta>;
|
|
186
|
+
/**
|
|
187
|
+
* Options for binding a parser to config values.
|
|
188
|
+
*
|
|
189
|
+
* @template T The config data type.
|
|
190
|
+
* @template TValue The value type extracted from config.
|
|
191
|
+
* @since 0.10.0
|
|
192
|
+
*/
|
|
193
|
+
interface BindConfigOptions<T, TValue, TConfigMeta = ConfigMeta> {
|
|
194
|
+
/**
|
|
195
|
+
* The config context to use for fallback values.
|
|
196
|
+
*/
|
|
197
|
+
readonly context: ConfigContext<T, TConfigMeta>;
|
|
198
|
+
/**
|
|
199
|
+
* Key or accessor function to extract the value from config.
|
|
200
|
+
* Can be a property key (for top-level config values) or a function
|
|
201
|
+
* that extracts nested values. Accessor callbacks receive config metadata
|
|
202
|
+
* as the second argument.
|
|
203
|
+
*/
|
|
204
|
+
readonly key: keyof T | ((config: T, meta: TConfigMeta) => TValue);
|
|
205
|
+
/**
|
|
206
|
+
* Default value to use when neither CLI nor config provides a value.
|
|
207
|
+
* If not specified, the parser will fail when no value is available.
|
|
208
|
+
*/
|
|
209
|
+
readonly default?: TValue;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Binds a parser to configuration values with fallback priority.
|
|
213
|
+
*
|
|
214
|
+
* The binding implements the following priority order:
|
|
215
|
+
* 1. CLI argument (if provided)
|
|
216
|
+
* 2. Config file value (if available)
|
|
217
|
+
* 3. Default value (if specified)
|
|
218
|
+
* 4. Error (if none of the above)
|
|
219
|
+
*
|
|
220
|
+
* @template M The parser mode (sync or async).
|
|
221
|
+
* @template TValue The parser value type.
|
|
222
|
+
* @template TState The parser state type.
|
|
223
|
+
* @template T The config data type.
|
|
224
|
+
* @param parser The parser to bind to config values.
|
|
225
|
+
* @param options Binding options including context, key, and default.
|
|
226
|
+
* @returns A new parser with config fallback behavior.
|
|
227
|
+
* @since 0.10.0
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* ```typescript
|
|
231
|
+
* import { bindConfig } from "@optique/config";
|
|
232
|
+
* import { option } from "@optique/core/primitives";
|
|
233
|
+
* import { string } from "@optique/core/valueparser";
|
|
234
|
+
*
|
|
235
|
+
* const hostParser = bindConfig(option("--host", string()), {
|
|
236
|
+
* context: configContext,
|
|
237
|
+
* key: "host",
|
|
238
|
+
* default: "localhost",
|
|
239
|
+
* });
|
|
240
|
+
* ```
|
|
241
|
+
*/
|
|
242
|
+
declare function bindConfig<M extends "sync" | "async", TValue, TState, T, TConfigMeta = ConfigMeta>(parser: Parser<M, TValue, TState>, options: BindConfigOptions<T, TValue, TConfigMeta>): Parser<M, TValue, TState>;
|
|
243
|
+
//#endregion
|
|
244
|
+
export { BindConfigOptions, ConfigContext, ConfigContextOptions, ConfigContextRequiredOptions, ConfigLoadResult, ConfigMeta, bindConfig, clearActiveConfig, clearActiveConfigMeta, configKey, configMetaKey, createConfigContext, getActiveConfig, getActiveConfigMeta, setActiveConfig, setActiveConfigMeta };
|