@optique/config 0.10.0-dev.0
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/LICENSE +20 -0
- package/README.md +102 -0
- package/dist/index-CZZEDay7.d.cts +167 -0
- package/dist/index-DiDpcijz.d.ts +167 -0
- package/dist/index.cjs +8 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/run.cjs +114 -0
- package/dist/run.d.cts +79 -0
- package/dist/run.d.ts +79 -0
- package/dist/run.js +114 -0
- package/dist/src-DVH5fJU9.cjs +295 -0
- package/dist/src-iXO5MxwN.js +231 -0
- package/package.json +87 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright 2025–2026 Hong Minhee
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
7
|
+
the Software without restriction, including without limitation the rights to
|
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
10
|
+
subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
@optique/config
|
|
2
|
+
===============
|
|
3
|
+
|
|
4
|
+
Configuration file support for [Optique] with type-safe validation using
|
|
5
|
+
[Standard Schema].
|
|
6
|
+
|
|
7
|
+
This package enables CLI applications to load default values from configuration
|
|
8
|
+
files with proper priority handling: CLI arguments > config file values >
|
|
9
|
+
defaults.
|
|
10
|
+
|
|
11
|
+
[Optique]: https://optique.dev/
|
|
12
|
+
[Standard Schema]: https://standardschema.dev/
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
Installation
|
|
16
|
+
------------
|
|
17
|
+
|
|
18
|
+
~~~~ bash [Deno]
|
|
19
|
+
deno add jsr:@optique/config npm:@standard-schema/spec npm:zod
|
|
20
|
+
npm add @optique/config @standard-schema/spec zod
|
|
21
|
+
pnpm add @optique/config @standard-schema/spec zod
|
|
22
|
+
bun add @optique/config @standard-schema/spec zod
|
|
23
|
+
~~~~
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
Quick start
|
|
27
|
+
-----------
|
|
28
|
+
|
|
29
|
+
~~~~ typescript
|
|
30
|
+
import { z } from "zod";
|
|
31
|
+
import { createConfigContext, bindConfig } from "@optique/config";
|
|
32
|
+
import { runWithConfig } from "@optique/config/run";
|
|
33
|
+
import { object } from "@optique/core/constructs";
|
|
34
|
+
import { option } from "@optique/core/primitives";
|
|
35
|
+
import { string, integer } from "@optique/core/valueparser";
|
|
36
|
+
import { withDefault } from "@optique/core/modifiers";
|
|
37
|
+
|
|
38
|
+
// 1. Define config schema
|
|
39
|
+
const configSchema = z.object({
|
|
40
|
+
host: z.string(),
|
|
41
|
+
port: z.number(),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const configContext = createConfigContext({ schema: configSchema });
|
|
45
|
+
|
|
46
|
+
// 2. Bind parsers to config values
|
|
47
|
+
const parser = object({
|
|
48
|
+
config: withDefault(option("--config", string()), "~/.myapp.json"),
|
|
49
|
+
host: bindConfig(option("--host", string()), {
|
|
50
|
+
context: configContext,
|
|
51
|
+
key: "host",
|
|
52
|
+
default: "localhost",
|
|
53
|
+
}),
|
|
54
|
+
port: bindConfig(option("--port", integer()), {
|
|
55
|
+
context: configContext,
|
|
56
|
+
key: "port",
|
|
57
|
+
default: 3000,
|
|
58
|
+
}),
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// 3. Run with config support
|
|
62
|
+
const result = await runWithConfig(parser, configContext, {
|
|
63
|
+
getConfigPath: (parsed) => parsed.config,
|
|
64
|
+
args: process.argv.slice(2),
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
console.log(`Connecting to ${result.host}:${result.port}`);
|
|
68
|
+
~~~~
|
|
69
|
+
|
|
70
|
+
With a config file `~/.myapp.json`:
|
|
71
|
+
|
|
72
|
+
~~~~ json
|
|
73
|
+
{
|
|
74
|
+
"host": "api.example.com",
|
|
75
|
+
"port": 8080
|
|
76
|
+
}
|
|
77
|
+
~~~~
|
|
78
|
+
|
|
79
|
+
Running `myapp --host localhost` will use `localhost` from CLI and `8080` from
|
|
80
|
+
the config file.
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
Features
|
|
84
|
+
--------
|
|
85
|
+
|
|
86
|
+
- *Type-safe validation* using Standard Schema (Zod, Valibot, ArkType, etc.)
|
|
87
|
+
- *Priority handling*: CLI > config file > defaults
|
|
88
|
+
- *Nested config values* with accessor functions
|
|
89
|
+
- *Custom file formats* with parser functions
|
|
90
|
+
- *Composable* with other data sources via `SourceContext` interface
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
Documentation
|
|
94
|
+
-------------
|
|
95
|
+
|
|
96
|
+
For complete documentation, visit <https://optique.dev/integrations/config>.
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
License
|
|
100
|
+
-------
|
|
101
|
+
|
|
102
|
+
MIT License. See [LICENSE](../../LICENSE) for details.
|
|
@@ -0,0 +1,167 @@
|
|
|
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
|
+
* Sets active config data for a context.
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
declare function setActiveConfig<T>(contextId: symbol, data: T): void;
|
|
17
|
+
/**
|
|
18
|
+
* Gets active config data for a context.
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
declare function getActiveConfig<T>(contextId: symbol): T | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Clears active config data for a context.
|
|
24
|
+
* @internal
|
|
25
|
+
*/
|
|
26
|
+
declare function clearActiveConfig(contextId: symbol): void;
|
|
27
|
+
/**
|
|
28
|
+
* Options for creating a config context.
|
|
29
|
+
*
|
|
30
|
+
* @template T The output type of the config schema.
|
|
31
|
+
* @since 0.10.0
|
|
32
|
+
*/
|
|
33
|
+
interface ConfigContextOptions<T> {
|
|
34
|
+
/**
|
|
35
|
+
* Standard Schema validator for the config file.
|
|
36
|
+
* Accepts any Standard Schema-compatible library (Zod, Valibot, ArkType, etc.).
|
|
37
|
+
*/
|
|
38
|
+
readonly schema: StandardSchemaV1<unknown, T>;
|
|
39
|
+
/**
|
|
40
|
+
* Custom parser function for reading config file contents.
|
|
41
|
+
* If not provided, defaults to JSON.parse.
|
|
42
|
+
*
|
|
43
|
+
* @param contents The raw file contents as Uint8Array.
|
|
44
|
+
* @returns The parsed config data (will be validated by schema).
|
|
45
|
+
*/
|
|
46
|
+
readonly parser?: (contents: Uint8Array) => unknown;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Required options for ConfigContext when used with runWith().
|
|
50
|
+
* The `ParserValuePlaceholder` will be substituted with the actual parser
|
|
51
|
+
* result type by runWith().
|
|
52
|
+
*
|
|
53
|
+
* @since 0.10.0
|
|
54
|
+
*/
|
|
55
|
+
interface ConfigContextRequiredOptions {
|
|
56
|
+
/**
|
|
57
|
+
* Function to extract config file path from parsed CLI arguments.
|
|
58
|
+
* The `parsed` parameter is typed as the parser's result type.
|
|
59
|
+
*
|
|
60
|
+
* @param parsed The parsed CLI arguments (typed from parser).
|
|
61
|
+
* @returns The config file path, or undefined if not specified.
|
|
62
|
+
*/
|
|
63
|
+
readonly getConfigPath: (parsed: ParserValuePlaceholder) => string | undefined;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* A config context that provides configuration data via annotations.
|
|
67
|
+
*
|
|
68
|
+
* When used with `runWith()`, the options must include `getConfigPath` with
|
|
69
|
+
* the correct parser result type. The `ParserValuePlaceholder` in
|
|
70
|
+
* `ConfigContextRequiredOptions` is substituted with the actual parser type.
|
|
71
|
+
*
|
|
72
|
+
* @template T The validated config data type.
|
|
73
|
+
* @since 0.10.0
|
|
74
|
+
*/
|
|
75
|
+
interface ConfigContext<T> extends SourceContext<ConfigContextRequiredOptions> {
|
|
76
|
+
/**
|
|
77
|
+
* The Standard Schema validator for the config file.
|
|
78
|
+
*/
|
|
79
|
+
readonly schema: StandardSchemaV1<unknown, T>;
|
|
80
|
+
/**
|
|
81
|
+
* Custom parser function for reading config file contents.
|
|
82
|
+
*/
|
|
83
|
+
readonly parser?: (contents: Uint8Array) => unknown;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Creates a config context for use with Optique parsers.
|
|
87
|
+
*
|
|
88
|
+
* The config context implements the SourceContext interface and can be used
|
|
89
|
+
* with runWith() or runWithConfig() to provide configuration file support.
|
|
90
|
+
*
|
|
91
|
+
* @template T The output type of the config schema.
|
|
92
|
+
* @param options Configuration options including schema and optional parser.
|
|
93
|
+
* @returns A config context that can be used with bindConfig() and runWithConfig().
|
|
94
|
+
* @since 0.10.0
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* import { z } from "zod";
|
|
99
|
+
* import { createConfigContext } from "@optique/config";
|
|
100
|
+
*
|
|
101
|
+
* const schema = z.object({
|
|
102
|
+
* host: z.string(),
|
|
103
|
+
* port: z.number(),
|
|
104
|
+
* });
|
|
105
|
+
*
|
|
106
|
+
* const configContext = createConfigContext({ schema });
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
declare function createConfigContext<T>(options: ConfigContextOptions<T>): ConfigContext<T>;
|
|
110
|
+
/**
|
|
111
|
+
* Options for binding a parser to config values.
|
|
112
|
+
*
|
|
113
|
+
* @template T The config data type.
|
|
114
|
+
* @template TValue The value type extracted from config.
|
|
115
|
+
* @since 0.10.0
|
|
116
|
+
*/
|
|
117
|
+
interface BindConfigOptions<T, TValue> {
|
|
118
|
+
/**
|
|
119
|
+
* The config context to use for fallback values.
|
|
120
|
+
*/
|
|
121
|
+
readonly context: ConfigContext<T>;
|
|
122
|
+
/**
|
|
123
|
+
* Key or accessor function to extract the value from config.
|
|
124
|
+
* Can be a property key (for top-level config values) or a function
|
|
125
|
+
* that extracts nested values.
|
|
126
|
+
*/
|
|
127
|
+
readonly key: keyof T | ((config: T) => TValue);
|
|
128
|
+
/**
|
|
129
|
+
* Default value to use when neither CLI nor config provides a value.
|
|
130
|
+
* If not specified, the parser will fail when no value is available.
|
|
131
|
+
*/
|
|
132
|
+
readonly default?: TValue;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Binds a parser to configuration values with fallback priority.
|
|
136
|
+
*
|
|
137
|
+
* The binding implements the following priority order:
|
|
138
|
+
* 1. CLI argument (if provided)
|
|
139
|
+
* 2. Config file value (if available)
|
|
140
|
+
* 3. Default value (if specified)
|
|
141
|
+
* 4. Error (if none of the above)
|
|
142
|
+
*
|
|
143
|
+
* @template M The parser mode (sync or async).
|
|
144
|
+
* @template TValue The parser value type.
|
|
145
|
+
* @template TState The parser state type.
|
|
146
|
+
* @template T The config data type.
|
|
147
|
+
* @param parser The parser to bind to config values.
|
|
148
|
+
* @param options Binding options including context, key, and default.
|
|
149
|
+
* @returns A new parser with config fallback behavior.
|
|
150
|
+
* @since 0.10.0
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```typescript
|
|
154
|
+
* import { bindConfig } from "@optique/config";
|
|
155
|
+
* import { option } from "@optique/core/primitives";
|
|
156
|
+
* import { string } from "@optique/core/valueparser";
|
|
157
|
+
*
|
|
158
|
+
* const hostParser = bindConfig(option("--host", string()), {
|
|
159
|
+
* context: configContext,
|
|
160
|
+
* key: "host",
|
|
161
|
+
* default: "localhost",
|
|
162
|
+
* });
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
declare function bindConfig<M extends "sync" | "async", TValue, TState, T>(parser: Parser<M, TValue, TState>, options: BindConfigOptions<T, TValue>): Parser<M, TValue, TState>;
|
|
166
|
+
//#endregion
|
|
167
|
+
export { BindConfigOptions, ConfigContext, ConfigContextOptions, ConfigContextRequiredOptions, bindConfig, clearActiveConfig, configKey, createConfigContext, getActiveConfig, setActiveConfig };
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { Parser } from "@optique/core/parser";
|
|
2
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
3
|
+
import { ParserValuePlaceholder, SourceContext } from "@optique/core/context";
|
|
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
|
+
* Sets active config data for a context.
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
declare function setActiveConfig<T>(contextId: symbol, data: T): void;
|
|
17
|
+
/**
|
|
18
|
+
* Gets active config data for a context.
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
declare function getActiveConfig<T>(contextId: symbol): T | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Clears active config data for a context.
|
|
24
|
+
* @internal
|
|
25
|
+
*/
|
|
26
|
+
declare function clearActiveConfig(contextId: symbol): void;
|
|
27
|
+
/**
|
|
28
|
+
* Options for creating a config context.
|
|
29
|
+
*
|
|
30
|
+
* @template T The output type of the config schema.
|
|
31
|
+
* @since 0.10.0
|
|
32
|
+
*/
|
|
33
|
+
interface ConfigContextOptions<T> {
|
|
34
|
+
/**
|
|
35
|
+
* Standard Schema validator for the config file.
|
|
36
|
+
* Accepts any Standard Schema-compatible library (Zod, Valibot, ArkType, etc.).
|
|
37
|
+
*/
|
|
38
|
+
readonly schema: StandardSchemaV1<unknown, T>;
|
|
39
|
+
/**
|
|
40
|
+
* Custom parser function for reading config file contents.
|
|
41
|
+
* If not provided, defaults to JSON.parse.
|
|
42
|
+
*
|
|
43
|
+
* @param contents The raw file contents as Uint8Array.
|
|
44
|
+
* @returns The parsed config data (will be validated by schema).
|
|
45
|
+
*/
|
|
46
|
+
readonly parser?: (contents: Uint8Array) => unknown;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Required options for ConfigContext when used with runWith().
|
|
50
|
+
* The `ParserValuePlaceholder` will be substituted with the actual parser
|
|
51
|
+
* result type by runWith().
|
|
52
|
+
*
|
|
53
|
+
* @since 0.10.0
|
|
54
|
+
*/
|
|
55
|
+
interface ConfigContextRequiredOptions {
|
|
56
|
+
/**
|
|
57
|
+
* Function to extract config file path from parsed CLI arguments.
|
|
58
|
+
* The `parsed` parameter is typed as the parser's result type.
|
|
59
|
+
*
|
|
60
|
+
* @param parsed The parsed CLI arguments (typed from parser).
|
|
61
|
+
* @returns The config file path, or undefined if not specified.
|
|
62
|
+
*/
|
|
63
|
+
readonly getConfigPath: (parsed: ParserValuePlaceholder) => string | undefined;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* A config context that provides configuration data via annotations.
|
|
67
|
+
*
|
|
68
|
+
* When used with `runWith()`, the options must include `getConfigPath` with
|
|
69
|
+
* the correct parser result type. The `ParserValuePlaceholder` in
|
|
70
|
+
* `ConfigContextRequiredOptions` is substituted with the actual parser type.
|
|
71
|
+
*
|
|
72
|
+
* @template T The validated config data type.
|
|
73
|
+
* @since 0.10.0
|
|
74
|
+
*/
|
|
75
|
+
interface ConfigContext<T> extends SourceContext<ConfigContextRequiredOptions> {
|
|
76
|
+
/**
|
|
77
|
+
* The Standard Schema validator for the config file.
|
|
78
|
+
*/
|
|
79
|
+
readonly schema: StandardSchemaV1<unknown, T>;
|
|
80
|
+
/**
|
|
81
|
+
* Custom parser function for reading config file contents.
|
|
82
|
+
*/
|
|
83
|
+
readonly parser?: (contents: Uint8Array) => unknown;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Creates a config context for use with Optique parsers.
|
|
87
|
+
*
|
|
88
|
+
* The config context implements the SourceContext interface and can be used
|
|
89
|
+
* with runWith() or runWithConfig() to provide configuration file support.
|
|
90
|
+
*
|
|
91
|
+
* @template T The output type of the config schema.
|
|
92
|
+
* @param options Configuration options including schema and optional parser.
|
|
93
|
+
* @returns A config context that can be used with bindConfig() and runWithConfig().
|
|
94
|
+
* @since 0.10.0
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* import { z } from "zod";
|
|
99
|
+
* import { createConfigContext } from "@optique/config";
|
|
100
|
+
*
|
|
101
|
+
* const schema = z.object({
|
|
102
|
+
* host: z.string(),
|
|
103
|
+
* port: z.number(),
|
|
104
|
+
* });
|
|
105
|
+
*
|
|
106
|
+
* const configContext = createConfigContext({ schema });
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
declare function createConfigContext<T>(options: ConfigContextOptions<T>): ConfigContext<T>;
|
|
110
|
+
/**
|
|
111
|
+
* Options for binding a parser to config values.
|
|
112
|
+
*
|
|
113
|
+
* @template T The config data type.
|
|
114
|
+
* @template TValue The value type extracted from config.
|
|
115
|
+
* @since 0.10.0
|
|
116
|
+
*/
|
|
117
|
+
interface BindConfigOptions<T, TValue> {
|
|
118
|
+
/**
|
|
119
|
+
* The config context to use for fallback values.
|
|
120
|
+
*/
|
|
121
|
+
readonly context: ConfigContext<T>;
|
|
122
|
+
/**
|
|
123
|
+
* Key or accessor function to extract the value from config.
|
|
124
|
+
* Can be a property key (for top-level config values) or a function
|
|
125
|
+
* that extracts nested values.
|
|
126
|
+
*/
|
|
127
|
+
readonly key: keyof T | ((config: T) => TValue);
|
|
128
|
+
/**
|
|
129
|
+
* Default value to use when neither CLI nor config provides a value.
|
|
130
|
+
* If not specified, the parser will fail when no value is available.
|
|
131
|
+
*/
|
|
132
|
+
readonly default?: TValue;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Binds a parser to configuration values with fallback priority.
|
|
136
|
+
*
|
|
137
|
+
* The binding implements the following priority order:
|
|
138
|
+
* 1. CLI argument (if provided)
|
|
139
|
+
* 2. Config file value (if available)
|
|
140
|
+
* 3. Default value (if specified)
|
|
141
|
+
* 4. Error (if none of the above)
|
|
142
|
+
*
|
|
143
|
+
* @template M The parser mode (sync or async).
|
|
144
|
+
* @template TValue The parser value type.
|
|
145
|
+
* @template TState The parser state type.
|
|
146
|
+
* @template T The config data type.
|
|
147
|
+
* @param parser The parser to bind to config values.
|
|
148
|
+
* @param options Binding options including context, key, and default.
|
|
149
|
+
* @returns A new parser with config fallback behavior.
|
|
150
|
+
* @since 0.10.0
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```typescript
|
|
154
|
+
* import { bindConfig } from "@optique/config";
|
|
155
|
+
* import { option } from "@optique/core/primitives";
|
|
156
|
+
* import { string } from "@optique/core/valueparser";
|
|
157
|
+
*
|
|
158
|
+
* const hostParser = bindConfig(option("--host", string()), {
|
|
159
|
+
* context: configContext,
|
|
160
|
+
* key: "host",
|
|
161
|
+
* default: "localhost",
|
|
162
|
+
* });
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
declare function bindConfig<M extends "sync" | "async", TValue, TState, T>(parser: Parser<M, TValue, TState>, options: BindConfigOptions<T, TValue>): Parser<M, TValue, TState>;
|
|
166
|
+
//#endregion
|
|
167
|
+
export { BindConfigOptions, ConfigContext, ConfigContextOptions, ConfigContextRequiredOptions, bindConfig, clearActiveConfig, configKey, createConfigContext, getActiveConfig, setActiveConfig };
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const require_src = require('./src-DVH5fJU9.cjs');
|
|
2
|
+
|
|
3
|
+
exports.bindConfig = require_src.bindConfig;
|
|
4
|
+
exports.clearActiveConfig = require_src.clearActiveConfig;
|
|
5
|
+
exports.configKey = require_src.configKey;
|
|
6
|
+
exports.createConfigContext = require_src.createConfigContext;
|
|
7
|
+
exports.getActiveConfig = require_src.getActiveConfig;
|
|
8
|
+
exports.setActiveConfig = require_src.setActiveConfig;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { BindConfigOptions, ConfigContext, ConfigContextOptions, ConfigContextRequiredOptions, bindConfig, clearActiveConfig, configKey, createConfigContext, getActiveConfig, setActiveConfig } from "./index-CZZEDay7.cjs";
|
|
2
|
+
export { BindConfigOptions, ConfigContext, ConfigContextOptions, ConfigContextRequiredOptions, bindConfig, clearActiveConfig, configKey, createConfigContext, getActiveConfig, setActiveConfig };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { BindConfigOptions, ConfigContext, ConfigContextOptions, ConfigContextRequiredOptions, bindConfig, clearActiveConfig, configKey, createConfigContext, getActiveConfig, setActiveConfig } from "./index-DiDpcijz.js";
|
|
2
|
+
export { BindConfigOptions, ConfigContext, ConfigContextOptions, ConfigContextRequiredOptions, bindConfig, clearActiveConfig, configKey, createConfigContext, getActiveConfig, setActiveConfig };
|
package/dist/index.js
ADDED
package/dist/run.cjs
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
const require_src = require('./src-DVH5fJU9.cjs');
|
|
2
|
+
const node_fs_promises = require_src.__toESM(require("node:fs/promises"));
|
|
3
|
+
const __optique_core_parser = require_src.__toESM(require("@optique/core/parser"));
|
|
4
|
+
|
|
5
|
+
//#region src/run.ts
|
|
6
|
+
/**
|
|
7
|
+
* Runs a parser with configuration file support using two-pass parsing.
|
|
8
|
+
*
|
|
9
|
+
* This function performs the following steps:
|
|
10
|
+
* 1. First pass: Parse arguments to extract the config file path
|
|
11
|
+
* 2. Load and validate: Read the config file and validate using Standard Schema
|
|
12
|
+
* 3. Second pass: Parse arguments again with config data as annotations
|
|
13
|
+
*
|
|
14
|
+
* The priority order for values is: CLI > config file > default.
|
|
15
|
+
*
|
|
16
|
+
* @template M The parser mode (sync or async).
|
|
17
|
+
* @template TValue The parser value type.
|
|
18
|
+
* @template TState The parser state type.
|
|
19
|
+
* @template T The config data type.
|
|
20
|
+
* @param parser The parser to execute.
|
|
21
|
+
* @param context The config context with schema and optional custom parser.
|
|
22
|
+
* @param options Run options including getConfigPath and args.
|
|
23
|
+
* @returns Promise that resolves to the parsed result.
|
|
24
|
+
* @throws Error if config file validation fails.
|
|
25
|
+
* @since 0.10.0
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* import { z } from "zod";
|
|
30
|
+
* import { runWithConfig } from "@optique/config/run";
|
|
31
|
+
* import { createConfigContext, bindConfig } from "@optique/config";
|
|
32
|
+
*
|
|
33
|
+
* const schema = z.object({
|
|
34
|
+
* host: z.string(),
|
|
35
|
+
* port: z.number(),
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* const context = createConfigContext({ schema });
|
|
39
|
+
*
|
|
40
|
+
* const parser = object({
|
|
41
|
+
* config: option("--config", string()),
|
|
42
|
+
* host: bindConfig(option("--host", string()), {
|
|
43
|
+
* context,
|
|
44
|
+
* key: "host",
|
|
45
|
+
* default: "localhost",
|
|
46
|
+
* }),
|
|
47
|
+
* });
|
|
48
|
+
*
|
|
49
|
+
* const result = await runWithConfig(parser, context, {
|
|
50
|
+
* getConfigPath: (parsed) => parsed.config,
|
|
51
|
+
* args: process.argv.slice(2),
|
|
52
|
+
* });
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
async function runWithConfig(parser, context, options) {
|
|
56
|
+
const args = options.args ?? [];
|
|
57
|
+
const firstPass = (0, __optique_core_parser.parse)(parser, args);
|
|
58
|
+
let firstPassResult;
|
|
59
|
+
if (firstPass instanceof Promise) firstPassResult = await firstPass;
|
|
60
|
+
else firstPassResult = firstPass;
|
|
61
|
+
if (!firstPassResult.success) {
|
|
62
|
+
const errorParts = firstPassResult.error.map((part) => {
|
|
63
|
+
if (part.type === "text") return part.text;
|
|
64
|
+
if (part.type === "optionName") return part.optionName;
|
|
65
|
+
if (part.type === "optionNames") return part.optionNames.join(", ");
|
|
66
|
+
if (part.type === "metavar") return part.metavar;
|
|
67
|
+
if (part.type === "value") return part.value;
|
|
68
|
+
if (part.type === "values") return part.values.join(", ");
|
|
69
|
+
if (part.type === "envVar") return part.envVar;
|
|
70
|
+
if (part.type === "commandLine") return part.commandLine;
|
|
71
|
+
if (part.type === "url") return part.url;
|
|
72
|
+
return "";
|
|
73
|
+
});
|
|
74
|
+
throw new Error(`Parsing failed: ${errorParts.join("")}`);
|
|
75
|
+
}
|
|
76
|
+
const configPath = options.getConfigPath(firstPassResult.value);
|
|
77
|
+
let configData;
|
|
78
|
+
if (configPath) try {
|
|
79
|
+
const contents = await (0, node_fs_promises.readFile)(configPath);
|
|
80
|
+
let rawData;
|
|
81
|
+
if (context.parser) rawData = context.parser(contents);
|
|
82
|
+
else {
|
|
83
|
+
const text = new TextDecoder().decode(contents);
|
|
84
|
+
rawData = JSON.parse(text);
|
|
85
|
+
}
|
|
86
|
+
const validation = context.schema["~standard"].validate(rawData);
|
|
87
|
+
let validationResult;
|
|
88
|
+
if (validation instanceof Promise) validationResult = await validation;
|
|
89
|
+
else validationResult = validation;
|
|
90
|
+
if (validationResult.issues) {
|
|
91
|
+
const firstIssue = validationResult.issues[0];
|
|
92
|
+
throw new Error(`Config validation failed: ${firstIssue?.message ?? "Unknown error"}`);
|
|
93
|
+
}
|
|
94
|
+
configData = validationResult.value;
|
|
95
|
+
} catch (error) {
|
|
96
|
+
if (error instanceof Error && error.message.includes("validation")) throw error;
|
|
97
|
+
configData = void 0;
|
|
98
|
+
}
|
|
99
|
+
const annotations = configData ? { [require_src.configKey]: configData } : {};
|
|
100
|
+
if (configData) require_src.setActiveConfig(context.id, configData);
|
|
101
|
+
try {
|
|
102
|
+
const secondPass = (0, __optique_core_parser.parse)(parser, args, { annotations });
|
|
103
|
+
let secondPassResult;
|
|
104
|
+
if (secondPass instanceof Promise) secondPassResult = await secondPass;
|
|
105
|
+
else secondPassResult = secondPass;
|
|
106
|
+
if (!secondPassResult.success) throw new Error(`Parsing failed: ${String(secondPassResult.error)}`);
|
|
107
|
+
return secondPassResult.value;
|
|
108
|
+
} finally {
|
|
109
|
+
require_src.clearActiveConfig(context.id);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
//#endregion
|
|
114
|
+
exports.runWithConfig = runWithConfig;
|
package/dist/run.d.cts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { ConfigContext } from "./index-CZZEDay7.cjs";
|
|
2
|
+
import { Parser } from "@optique/core/parser";
|
|
3
|
+
|
|
4
|
+
//#region src/run.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Options for runWithConfig.
|
|
8
|
+
*
|
|
9
|
+
* @template TValue The parser value type, inferred from the parser.
|
|
10
|
+
* @since 0.10.0
|
|
11
|
+
*/
|
|
12
|
+
interface RunWithConfigOptions<TValue> {
|
|
13
|
+
/**
|
|
14
|
+
* Function to extract the config file path from parsed CLI arguments.
|
|
15
|
+
* This function receives the result of the first parse pass and should
|
|
16
|
+
* return the config file path or undefined if no config file is specified.
|
|
17
|
+
*
|
|
18
|
+
* The `parsed` parameter is typed based on the parser's result type,
|
|
19
|
+
* providing full type safety without manual type assertions.
|
|
20
|
+
*/
|
|
21
|
+
readonly getConfigPath: (parsed: TValue) => string | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Command-line arguments to parse.
|
|
24
|
+
* If not provided, defaults to an empty array.
|
|
25
|
+
*/
|
|
26
|
+
readonly args?: readonly string[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Runs a parser with configuration file support using two-pass parsing.
|
|
30
|
+
*
|
|
31
|
+
* This function performs the following steps:
|
|
32
|
+
* 1. First pass: Parse arguments to extract the config file path
|
|
33
|
+
* 2. Load and validate: Read the config file and validate using Standard Schema
|
|
34
|
+
* 3. Second pass: Parse arguments again with config data as annotations
|
|
35
|
+
*
|
|
36
|
+
* The priority order for values is: CLI > config file > default.
|
|
37
|
+
*
|
|
38
|
+
* @template M The parser mode (sync or async).
|
|
39
|
+
* @template TValue The parser value type.
|
|
40
|
+
* @template TState The parser state type.
|
|
41
|
+
* @template T The config data type.
|
|
42
|
+
* @param parser The parser to execute.
|
|
43
|
+
* @param context The config context with schema and optional custom parser.
|
|
44
|
+
* @param options Run options including getConfigPath and args.
|
|
45
|
+
* @returns Promise that resolves to the parsed result.
|
|
46
|
+
* @throws Error if config file validation fails.
|
|
47
|
+
* @since 0.10.0
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* import { z } from "zod";
|
|
52
|
+
* import { runWithConfig } from "@optique/config/run";
|
|
53
|
+
* import { createConfigContext, bindConfig } from "@optique/config";
|
|
54
|
+
*
|
|
55
|
+
* const schema = z.object({
|
|
56
|
+
* host: z.string(),
|
|
57
|
+
* port: z.number(),
|
|
58
|
+
* });
|
|
59
|
+
*
|
|
60
|
+
* const context = createConfigContext({ schema });
|
|
61
|
+
*
|
|
62
|
+
* const parser = object({
|
|
63
|
+
* config: option("--config", string()),
|
|
64
|
+
* host: bindConfig(option("--host", string()), {
|
|
65
|
+
* context,
|
|
66
|
+
* key: "host",
|
|
67
|
+
* default: "localhost",
|
|
68
|
+
* }),
|
|
69
|
+
* });
|
|
70
|
+
*
|
|
71
|
+
* const result = await runWithConfig(parser, context, {
|
|
72
|
+
* getConfigPath: (parsed) => parsed.config,
|
|
73
|
+
* args: process.argv.slice(2),
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
declare function runWithConfig<M extends "sync" | "async", TValue, TState, T>(parser: Parser<M, TValue, TState>, context: ConfigContext<T>, options: RunWithConfigOptions<TValue>): Promise<TValue>;
|
|
78
|
+
//#endregion
|
|
79
|
+
export { RunWithConfigOptions, runWithConfig };
|