@optique/zod 0.7.0-dev.1
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 +199 -0
- package/dist/index.cjs +123 -0
- package/dist/index.d.cts +96 -0
- package/dist/index.d.ts +96 -0
- package/dist/index.js +100 -0
- package/package.json +79 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright 2025 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,199 @@
|
|
|
1
|
+
@optique/zod
|
|
2
|
+
============
|
|
3
|
+
|
|
4
|
+
> [!WARNING]
|
|
5
|
+
> The API is stabilizing, but may change before the 1.0 release.
|
|
6
|
+
|
|
7
|
+
Zod value parsers for Optique. This package provides seamless integration
|
|
8
|
+
between [Zod] schemas and *@optique/core*, enabling powerful validation and
|
|
9
|
+
type-safe parsing of command-line arguments.
|
|
10
|
+
|
|
11
|
+
[Zod]: https://zod.dev/
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
Installation
|
|
15
|
+
------------
|
|
16
|
+
|
|
17
|
+
~~~~ bash
|
|
18
|
+
deno add jsr:@optique/zod jsr:@optique/run jsr:@optique/core zod
|
|
19
|
+
npm add @optique/zod @optique/run @optique/core zod
|
|
20
|
+
pnpm add @optique/zod @optique/run @optique/core zod
|
|
21
|
+
yarn add @optique/zod @optique/run @optique/core zod
|
|
22
|
+
bun add @optique/zod @optique/run @optique/core zod
|
|
23
|
+
~~~~
|
|
24
|
+
|
|
25
|
+
This package supports Zod versions 3.25.0 and above, including Zod v4.
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
Quick example
|
|
29
|
+
-------------
|
|
30
|
+
|
|
31
|
+
The following example uses the `zod()` value parser to validate an email
|
|
32
|
+
address.
|
|
33
|
+
|
|
34
|
+
~~~~ typescript
|
|
35
|
+
import { run } from "@optique/run";
|
|
36
|
+
import { option } from "@optique/core/parser";
|
|
37
|
+
import { zod } from "@optique/zod";
|
|
38
|
+
import { z } from "zod";
|
|
39
|
+
|
|
40
|
+
const cli = run({
|
|
41
|
+
email: option("--email", zod(z.string().email())),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
console.log(`Welcome, ${cli.email}!`);
|
|
45
|
+
~~~~
|
|
46
|
+
|
|
47
|
+
Run it:
|
|
48
|
+
|
|
49
|
+
~~~~ bash
|
|
50
|
+
$ node cli.js --email user@example.com
|
|
51
|
+
Welcome, user@example.com!
|
|
52
|
+
|
|
53
|
+
$ node cli.js --email invalid-email
|
|
54
|
+
Error: Invalid email
|
|
55
|
+
~~~~
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
Common use cases
|
|
59
|
+
----------------
|
|
60
|
+
|
|
61
|
+
### Email validation
|
|
62
|
+
|
|
63
|
+
~~~~ typescript
|
|
64
|
+
import { zod } from "@optique/zod";
|
|
65
|
+
import { z } from "zod";
|
|
66
|
+
|
|
67
|
+
const email = option("--email", zod(z.string().email()));
|
|
68
|
+
~~~~
|
|
69
|
+
|
|
70
|
+
### URL validation
|
|
71
|
+
|
|
72
|
+
~~~~ typescript
|
|
73
|
+
import { zod } from "@optique/zod";
|
|
74
|
+
import { z } from "zod";
|
|
75
|
+
|
|
76
|
+
const url = option("--url", zod(z.string().url()));
|
|
77
|
+
~~~~
|
|
78
|
+
|
|
79
|
+
### Port numbers with range validation
|
|
80
|
+
|
|
81
|
+
> [!IMPORTANT]
|
|
82
|
+
> Always use `z.coerce` for non-string types, since CLI arguments are
|
|
83
|
+
> always strings.
|
|
84
|
+
|
|
85
|
+
~~~~ typescript
|
|
86
|
+
import { zod } from "@optique/zod";
|
|
87
|
+
import { z } from "zod";
|
|
88
|
+
|
|
89
|
+
const port = option("-p", "--port",
|
|
90
|
+
zod(z.coerce.number().int().min(1024).max(65535))
|
|
91
|
+
);
|
|
92
|
+
~~~~
|
|
93
|
+
|
|
94
|
+
### Enum choices
|
|
95
|
+
|
|
96
|
+
~~~~ typescript
|
|
97
|
+
import { zod } from "@optique/zod";
|
|
98
|
+
import { z } from "zod";
|
|
99
|
+
|
|
100
|
+
const logLevel = option("--log-level",
|
|
101
|
+
zod(z.enum(["debug", "info", "warn", "error"]))
|
|
102
|
+
);
|
|
103
|
+
~~~~
|
|
104
|
+
|
|
105
|
+
### Date transformations
|
|
106
|
+
|
|
107
|
+
~~~~ typescript
|
|
108
|
+
import { zod } from "@optique/zod";
|
|
109
|
+
import { z } from "zod";
|
|
110
|
+
|
|
111
|
+
const startDate = argument(
|
|
112
|
+
zod(z.string().transform((s) => new Date(s)))
|
|
113
|
+
);
|
|
114
|
+
~~~~
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
Custom error messages
|
|
118
|
+
---------------------
|
|
119
|
+
|
|
120
|
+
You can customize error messages using the `errors` option:
|
|
121
|
+
|
|
122
|
+
~~~~ typescript
|
|
123
|
+
import { zod } from "@optique/zod";
|
|
124
|
+
import { message } from "@optique/core/message";
|
|
125
|
+
import { z } from "zod";
|
|
126
|
+
|
|
127
|
+
const email = option("--email", zod(z.string().email(), {
|
|
128
|
+
metavar: "EMAIL",
|
|
129
|
+
errors: {
|
|
130
|
+
zodError: (error, input) =>
|
|
131
|
+
message`Please provide a valid email address, got ${input}.`
|
|
132
|
+
}
|
|
133
|
+
}));
|
|
134
|
+
~~~~
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
Important notes
|
|
138
|
+
---------------
|
|
139
|
+
|
|
140
|
+
### Always use `z.coerce` for non-string types
|
|
141
|
+
|
|
142
|
+
CLI arguments are always strings. If you want to parse numbers, booleans,
|
|
143
|
+
or other types, you must use `z.coerce`:
|
|
144
|
+
|
|
145
|
+
~~~~ typescript
|
|
146
|
+
// ✅ Correct
|
|
147
|
+
const port = option("-p", zod(z.coerce.number()));
|
|
148
|
+
|
|
149
|
+
// ❌ Won't work (CLI arguments are always strings)
|
|
150
|
+
const port = option("-p", zod(z.number()));
|
|
151
|
+
~~~~
|
|
152
|
+
|
|
153
|
+
### Async refinements are not supported
|
|
154
|
+
|
|
155
|
+
Optique's `ValueParser.parse()` is synchronous, so async Zod features like
|
|
156
|
+
async refinements cannot be supported:
|
|
157
|
+
|
|
158
|
+
~~~~ typescript
|
|
159
|
+
// ❌ Not supported
|
|
160
|
+
const email = option("--email",
|
|
161
|
+
zod(z.string().refine(async (val) => await checkDB(val)))
|
|
162
|
+
);
|
|
163
|
+
~~~~
|
|
164
|
+
|
|
165
|
+
If you need async validation, perform it after parsing the CLI arguments.
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
Zod version compatibility
|
|
169
|
+
--------------------------
|
|
170
|
+
|
|
171
|
+
This package supports both Zod v3 (3.25.0+) and Zod v4 (4.0.0+). The basic
|
|
172
|
+
functionality works identically in both versions.
|
|
173
|
+
|
|
174
|
+
- **Zod v3**: Uses standard error messages from `error.issues[0].message`
|
|
175
|
+
- **Zod v4**: Automatically uses `prettifyError()` when available for better
|
|
176
|
+
error formatting
|
|
177
|
+
|
|
178
|
+
### Testing with different Zod versions
|
|
179
|
+
|
|
180
|
+
For contributors and users who want to test compatibility:
|
|
181
|
+
|
|
182
|
+
~~~~ bash
|
|
183
|
+
# Test with Zod v3
|
|
184
|
+
pnpm run test:zod3
|
|
185
|
+
|
|
186
|
+
# Test with Zod v4
|
|
187
|
+
pnpm run test:zod4
|
|
188
|
+
|
|
189
|
+
# Test with both versions sequentially
|
|
190
|
+
pnpm run test:all-versions
|
|
191
|
+
~~~~
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
For more resources
|
|
195
|
+
------------------
|
|
196
|
+
|
|
197
|
+
- [Optique documentation](https://optique.dev/)
|
|
198
|
+
- [Zod documentation](https://zod.dev/)
|
|
199
|
+
- [Examples directory](/examples/)
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
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));
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
const __optique_core_message = __toESM(require("@optique/core/message"));
|
|
25
|
+
|
|
26
|
+
//#region src/index.ts
|
|
27
|
+
/**
|
|
28
|
+
* Creates a value parser from a Zod schema.
|
|
29
|
+
*
|
|
30
|
+
* This parser validates CLI argument strings using Zod schemas, enabling
|
|
31
|
+
* powerful validation and transformation capabilities for command-line
|
|
32
|
+
* interfaces.
|
|
33
|
+
*
|
|
34
|
+
* @template T The output type of the Zod schema.
|
|
35
|
+
* @param schema A Zod schema to validate input against.
|
|
36
|
+
* @param options Optional configuration for the parser.
|
|
37
|
+
* @returns A value parser that validates inputs using the provided schema.
|
|
38
|
+
*
|
|
39
|
+
* @example Basic string validation
|
|
40
|
+
* ```typescript
|
|
41
|
+
* import { z } from "zod";
|
|
42
|
+
* import { zod } from "@optique/zod";
|
|
43
|
+
* import { option } from "@optique/core/primitives";
|
|
44
|
+
*
|
|
45
|
+
* const email = option("--email", zod(z.string().email()));
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @example Number validation with coercion
|
|
49
|
+
* ```typescript
|
|
50
|
+
* import { z } from "zod";
|
|
51
|
+
* import { zod } from "@optique/zod";
|
|
52
|
+
* import { option } from "@optique/core/primitives";
|
|
53
|
+
*
|
|
54
|
+
* // Use z.coerce for non-string types since CLI args are always strings
|
|
55
|
+
* const port = option("-p", "--port",
|
|
56
|
+
* zod(z.coerce.number().int().min(1024).max(65535))
|
|
57
|
+
* );
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @example Enum validation
|
|
61
|
+
* ```typescript
|
|
62
|
+
* import { z } from "zod";
|
|
63
|
+
* import { zod } from "@optique/zod";
|
|
64
|
+
* import { option } from "@optique/core/primitives";
|
|
65
|
+
*
|
|
66
|
+
* const logLevel = option("--log-level",
|
|
67
|
+
* zod(z.enum(["debug", "info", "warn", "error"]))
|
|
68
|
+
* );
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* @example Custom error messages
|
|
72
|
+
* ```typescript
|
|
73
|
+
* import { z } from "zod";
|
|
74
|
+
* import { zod } from "@optique/zod";
|
|
75
|
+
* import { message } from "@optique/core/message";
|
|
76
|
+
* import { option } from "@optique/core/primitives";
|
|
77
|
+
*
|
|
78
|
+
* const email = option("--email", zod(z.string().email(), {
|
|
79
|
+
* metavar: "EMAIL",
|
|
80
|
+
* errors: {
|
|
81
|
+
* zodError: (error, input) =>
|
|
82
|
+
* message`Please provide a valid email address, got ${input}.`
|
|
83
|
+
* }
|
|
84
|
+
* }));
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* @since 0.7.0
|
|
88
|
+
*/
|
|
89
|
+
function zod(schema, options = {}) {
|
|
90
|
+
return {
|
|
91
|
+
metavar: options.metavar ?? "VALUE",
|
|
92
|
+
parse(input) {
|
|
93
|
+
const result = schema.safeParse(input);
|
|
94
|
+
if (result.success) return {
|
|
95
|
+
success: true,
|
|
96
|
+
value: result.data
|
|
97
|
+
};
|
|
98
|
+
if (options.errors?.zodError) return {
|
|
99
|
+
success: false,
|
|
100
|
+
error: typeof options.errors.zodError === "function" ? options.errors.zodError(result.error, input) : options.errors.zodError
|
|
101
|
+
};
|
|
102
|
+
const zodModule = schema;
|
|
103
|
+
if (typeof zodModule.constructor?.prettifyError === "function") try {
|
|
104
|
+
const pretty = zodModule.constructor.prettifyError(result.error);
|
|
105
|
+
return {
|
|
106
|
+
success: false,
|
|
107
|
+
error: __optique_core_message.message`${pretty}`
|
|
108
|
+
};
|
|
109
|
+
} catch {}
|
|
110
|
+
const firstError = result.error.issues[0];
|
|
111
|
+
return {
|
|
112
|
+
success: false,
|
|
113
|
+
error: __optique_core_message.message`${firstError?.message ?? "Validation failed"}`
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
format(value) {
|
|
117
|
+
return String(value);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
//#endregion
|
|
123
|
+
exports.zod = zod;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { ValueParser } from "@optique/core/valueparser";
|
|
2
|
+
import { Message } from "@optique/core/message";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
//#region src/index.d.ts
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Options for creating a Zod value parser.
|
|
9
|
+
* @since 0.7.0
|
|
10
|
+
*/
|
|
11
|
+
interface ZodParserOptions {
|
|
12
|
+
/**
|
|
13
|
+
* The metavariable name for this parser. This is used in help messages to
|
|
14
|
+
* indicate what kind of value this parser expects. Usually a single
|
|
15
|
+
* word in uppercase, like `VALUE` or `SCHEMA`.
|
|
16
|
+
* @default `"VALUE"`
|
|
17
|
+
*/
|
|
18
|
+
readonly metavar?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Custom error messages for Zod validation failures.
|
|
21
|
+
*/
|
|
22
|
+
readonly errors?: {
|
|
23
|
+
/**
|
|
24
|
+
* Custom error message when input fails Zod validation.
|
|
25
|
+
* Can be a static message or a function that receives the Zod error
|
|
26
|
+
* and input string.
|
|
27
|
+
* @since 0.7.0
|
|
28
|
+
*/
|
|
29
|
+
zodError?: Message | ((error: z.ZodError, input: string) => Message);
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Creates a value parser from a Zod schema.
|
|
34
|
+
*
|
|
35
|
+
* This parser validates CLI argument strings using Zod schemas, enabling
|
|
36
|
+
* powerful validation and transformation capabilities for command-line
|
|
37
|
+
* interfaces.
|
|
38
|
+
*
|
|
39
|
+
* @template T The output type of the Zod schema.
|
|
40
|
+
* @param schema A Zod schema to validate input against.
|
|
41
|
+
* @param options Optional configuration for the parser.
|
|
42
|
+
* @returns A value parser that validates inputs using the provided schema.
|
|
43
|
+
*
|
|
44
|
+
* @example Basic string validation
|
|
45
|
+
* ```typescript
|
|
46
|
+
* import { z } from "zod";
|
|
47
|
+
* import { zod } from "@optique/zod";
|
|
48
|
+
* import { option } from "@optique/core/primitives";
|
|
49
|
+
*
|
|
50
|
+
* const email = option("--email", zod(z.string().email()));
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @example Number validation with coercion
|
|
54
|
+
* ```typescript
|
|
55
|
+
* import { z } from "zod";
|
|
56
|
+
* import { zod } from "@optique/zod";
|
|
57
|
+
* import { option } from "@optique/core/primitives";
|
|
58
|
+
*
|
|
59
|
+
* // Use z.coerce for non-string types since CLI args are always strings
|
|
60
|
+
* const port = option("-p", "--port",
|
|
61
|
+
* zod(z.coerce.number().int().min(1024).max(65535))
|
|
62
|
+
* );
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* @example Enum validation
|
|
66
|
+
* ```typescript
|
|
67
|
+
* import { z } from "zod";
|
|
68
|
+
* import { zod } from "@optique/zod";
|
|
69
|
+
* import { option } from "@optique/core/primitives";
|
|
70
|
+
*
|
|
71
|
+
* const logLevel = option("--log-level",
|
|
72
|
+
* zod(z.enum(["debug", "info", "warn", "error"]))
|
|
73
|
+
* );
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* @example Custom error messages
|
|
77
|
+
* ```typescript
|
|
78
|
+
* import { z } from "zod";
|
|
79
|
+
* import { zod } from "@optique/zod";
|
|
80
|
+
* import { message } from "@optique/core/message";
|
|
81
|
+
* import { option } from "@optique/core/primitives";
|
|
82
|
+
*
|
|
83
|
+
* const email = option("--email", zod(z.string().email(), {
|
|
84
|
+
* metavar: "EMAIL",
|
|
85
|
+
* errors: {
|
|
86
|
+
* zodError: (error, input) =>
|
|
87
|
+
* message`Please provide a valid email address, got ${input}.`
|
|
88
|
+
* }
|
|
89
|
+
* }));
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* @since 0.7.0
|
|
93
|
+
*/
|
|
94
|
+
declare function zod<T>(schema: z.Schema<T>, options?: ZodParserOptions): ValueParser<T>;
|
|
95
|
+
//#endregion
|
|
96
|
+
export { ZodParserOptions, zod };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { Message } from "@optique/core/message";
|
|
2
|
+
import { ValueParser } from "@optique/core/valueparser";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
//#region src/index.d.ts
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Options for creating a Zod value parser.
|
|
9
|
+
* @since 0.7.0
|
|
10
|
+
*/
|
|
11
|
+
interface ZodParserOptions {
|
|
12
|
+
/**
|
|
13
|
+
* The metavariable name for this parser. This is used in help messages to
|
|
14
|
+
* indicate what kind of value this parser expects. Usually a single
|
|
15
|
+
* word in uppercase, like `VALUE` or `SCHEMA`.
|
|
16
|
+
* @default `"VALUE"`
|
|
17
|
+
*/
|
|
18
|
+
readonly metavar?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Custom error messages for Zod validation failures.
|
|
21
|
+
*/
|
|
22
|
+
readonly errors?: {
|
|
23
|
+
/**
|
|
24
|
+
* Custom error message when input fails Zod validation.
|
|
25
|
+
* Can be a static message or a function that receives the Zod error
|
|
26
|
+
* and input string.
|
|
27
|
+
* @since 0.7.0
|
|
28
|
+
*/
|
|
29
|
+
zodError?: Message | ((error: z.ZodError, input: string) => Message);
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Creates a value parser from a Zod schema.
|
|
34
|
+
*
|
|
35
|
+
* This parser validates CLI argument strings using Zod schemas, enabling
|
|
36
|
+
* powerful validation and transformation capabilities for command-line
|
|
37
|
+
* interfaces.
|
|
38
|
+
*
|
|
39
|
+
* @template T The output type of the Zod schema.
|
|
40
|
+
* @param schema A Zod schema to validate input against.
|
|
41
|
+
* @param options Optional configuration for the parser.
|
|
42
|
+
* @returns A value parser that validates inputs using the provided schema.
|
|
43
|
+
*
|
|
44
|
+
* @example Basic string validation
|
|
45
|
+
* ```typescript
|
|
46
|
+
* import { z } from "zod";
|
|
47
|
+
* import { zod } from "@optique/zod";
|
|
48
|
+
* import { option } from "@optique/core/primitives";
|
|
49
|
+
*
|
|
50
|
+
* const email = option("--email", zod(z.string().email()));
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @example Number validation with coercion
|
|
54
|
+
* ```typescript
|
|
55
|
+
* import { z } from "zod";
|
|
56
|
+
* import { zod } from "@optique/zod";
|
|
57
|
+
* import { option } from "@optique/core/primitives";
|
|
58
|
+
*
|
|
59
|
+
* // Use z.coerce for non-string types since CLI args are always strings
|
|
60
|
+
* const port = option("-p", "--port",
|
|
61
|
+
* zod(z.coerce.number().int().min(1024).max(65535))
|
|
62
|
+
* );
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* @example Enum validation
|
|
66
|
+
* ```typescript
|
|
67
|
+
* import { z } from "zod";
|
|
68
|
+
* import { zod } from "@optique/zod";
|
|
69
|
+
* import { option } from "@optique/core/primitives";
|
|
70
|
+
*
|
|
71
|
+
* const logLevel = option("--log-level",
|
|
72
|
+
* zod(z.enum(["debug", "info", "warn", "error"]))
|
|
73
|
+
* );
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* @example Custom error messages
|
|
77
|
+
* ```typescript
|
|
78
|
+
* import { z } from "zod";
|
|
79
|
+
* import { zod } from "@optique/zod";
|
|
80
|
+
* import { message } from "@optique/core/message";
|
|
81
|
+
* import { option } from "@optique/core/primitives";
|
|
82
|
+
*
|
|
83
|
+
* const email = option("--email", zod(z.string().email(), {
|
|
84
|
+
* metavar: "EMAIL",
|
|
85
|
+
* errors: {
|
|
86
|
+
* zodError: (error, input) =>
|
|
87
|
+
* message`Please provide a valid email address, got ${input}.`
|
|
88
|
+
* }
|
|
89
|
+
* }));
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* @since 0.7.0
|
|
93
|
+
*/
|
|
94
|
+
declare function zod<T>(schema: z.Schema<T>, options?: ZodParserOptions): ValueParser<T>;
|
|
95
|
+
//#endregion
|
|
96
|
+
export { ZodParserOptions, zod };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { message } from "@optique/core/message";
|
|
2
|
+
|
|
3
|
+
//#region src/index.ts
|
|
4
|
+
/**
|
|
5
|
+
* Creates a value parser from a Zod schema.
|
|
6
|
+
*
|
|
7
|
+
* This parser validates CLI argument strings using Zod schemas, enabling
|
|
8
|
+
* powerful validation and transformation capabilities for command-line
|
|
9
|
+
* interfaces.
|
|
10
|
+
*
|
|
11
|
+
* @template T The output type of the Zod schema.
|
|
12
|
+
* @param schema A Zod schema to validate input against.
|
|
13
|
+
* @param options Optional configuration for the parser.
|
|
14
|
+
* @returns A value parser that validates inputs using the provided schema.
|
|
15
|
+
*
|
|
16
|
+
* @example Basic string validation
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { z } from "zod";
|
|
19
|
+
* import { zod } from "@optique/zod";
|
|
20
|
+
* import { option } from "@optique/core/primitives";
|
|
21
|
+
*
|
|
22
|
+
* const email = option("--email", zod(z.string().email()));
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @example Number validation with coercion
|
|
26
|
+
* ```typescript
|
|
27
|
+
* import { z } from "zod";
|
|
28
|
+
* import { zod } from "@optique/zod";
|
|
29
|
+
* import { option } from "@optique/core/primitives";
|
|
30
|
+
*
|
|
31
|
+
* // Use z.coerce for non-string types since CLI args are always strings
|
|
32
|
+
* const port = option("-p", "--port",
|
|
33
|
+
* zod(z.coerce.number().int().min(1024).max(65535))
|
|
34
|
+
* );
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example Enum validation
|
|
38
|
+
* ```typescript
|
|
39
|
+
* import { z } from "zod";
|
|
40
|
+
* import { zod } from "@optique/zod";
|
|
41
|
+
* import { option } from "@optique/core/primitives";
|
|
42
|
+
*
|
|
43
|
+
* const logLevel = option("--log-level",
|
|
44
|
+
* zod(z.enum(["debug", "info", "warn", "error"]))
|
|
45
|
+
* );
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @example Custom error messages
|
|
49
|
+
* ```typescript
|
|
50
|
+
* import { z } from "zod";
|
|
51
|
+
* import { zod } from "@optique/zod";
|
|
52
|
+
* import { message } from "@optique/core/message";
|
|
53
|
+
* import { option } from "@optique/core/primitives";
|
|
54
|
+
*
|
|
55
|
+
* const email = option("--email", zod(z.string().email(), {
|
|
56
|
+
* metavar: "EMAIL",
|
|
57
|
+
* errors: {
|
|
58
|
+
* zodError: (error, input) =>
|
|
59
|
+
* message`Please provide a valid email address, got ${input}.`
|
|
60
|
+
* }
|
|
61
|
+
* }));
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @since 0.7.0
|
|
65
|
+
*/
|
|
66
|
+
function zod(schema, options = {}) {
|
|
67
|
+
return {
|
|
68
|
+
metavar: options.metavar ?? "VALUE",
|
|
69
|
+
parse(input) {
|
|
70
|
+
const result = schema.safeParse(input);
|
|
71
|
+
if (result.success) return {
|
|
72
|
+
success: true,
|
|
73
|
+
value: result.data
|
|
74
|
+
};
|
|
75
|
+
if (options.errors?.zodError) return {
|
|
76
|
+
success: false,
|
|
77
|
+
error: typeof options.errors.zodError === "function" ? options.errors.zodError(result.error, input) : options.errors.zodError
|
|
78
|
+
};
|
|
79
|
+
const zodModule = schema;
|
|
80
|
+
if (typeof zodModule.constructor?.prettifyError === "function") try {
|
|
81
|
+
const pretty = zodModule.constructor.prettifyError(result.error);
|
|
82
|
+
return {
|
|
83
|
+
success: false,
|
|
84
|
+
error: message`${pretty}`
|
|
85
|
+
};
|
|
86
|
+
} catch {}
|
|
87
|
+
const firstError = result.error.issues[0];
|
|
88
|
+
return {
|
|
89
|
+
success: false,
|
|
90
|
+
error: message`${firstError?.message ?? "Validation failed"}`
|
|
91
|
+
};
|
|
92
|
+
},
|
|
93
|
+
format(value) {
|
|
94
|
+
return String(value);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
//#endregion
|
|
100
|
+
export { zod };
|
package/package.json
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@optique/zod",
|
|
3
|
+
"version": "0.7.0-dev.1",
|
|
4
|
+
"description": "Zod value parsers for Optique",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"CLI",
|
|
7
|
+
"command-line",
|
|
8
|
+
"commandline",
|
|
9
|
+
"parser",
|
|
10
|
+
"zod",
|
|
11
|
+
"validation"
|
|
12
|
+
],
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"author": {
|
|
15
|
+
"name": "Hong Minhee",
|
|
16
|
+
"email": "hong@minhee.org",
|
|
17
|
+
"url": "https://hongminhee.org/"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://optique.dev/",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/dahlia/optique.git",
|
|
23
|
+
"directory": "packages/zod/"
|
|
24
|
+
},
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/dahlia/optique/issues"
|
|
27
|
+
},
|
|
28
|
+
"funding": [
|
|
29
|
+
"https://github.com/sponsors/dahlia"
|
|
30
|
+
],
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=20.0.0",
|
|
33
|
+
"bun": ">=1.2.0",
|
|
34
|
+
"deno": ">=2.3.0"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist/",
|
|
38
|
+
"package.json",
|
|
39
|
+
"README.md"
|
|
40
|
+
],
|
|
41
|
+
"type": "module",
|
|
42
|
+
"module": "./dist/index.js",
|
|
43
|
+
"main": "./dist/index.cjs",
|
|
44
|
+
"types": "./dist/index.d.ts",
|
|
45
|
+
"exports": {
|
|
46
|
+
".": {
|
|
47
|
+
"types": {
|
|
48
|
+
"import": "./dist/index.d.ts",
|
|
49
|
+
"require": "./dist/index.d.cts"
|
|
50
|
+
},
|
|
51
|
+
"import": "./dist/index.js",
|
|
52
|
+
"require": "./dist/index.cjs"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"sideEffects": false,
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"zod": "^3.25.0 || ^4.0.0"
|
|
58
|
+
},
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"@optique/core": ""
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@types/node": "^20.19.9",
|
|
64
|
+
"tsdown": "^0.13.0",
|
|
65
|
+
"typescript": "^5.8.3",
|
|
66
|
+
"zod": "^4.0.1"
|
|
67
|
+
},
|
|
68
|
+
"scripts": {
|
|
69
|
+
"build": "tsdown",
|
|
70
|
+
"prepublish": "tsdown",
|
|
71
|
+
"test": "tsdown && node --experimental-transform-types --test",
|
|
72
|
+
"test:bun": "tsdown && bun test",
|
|
73
|
+
"test:deno": "deno test",
|
|
74
|
+
"test:zod3": "cp package.json .package.json.bak && pnpm add -D zod@^3.25.0 && pnpm test && mv .package.json.bak package.json && pnpm install",
|
|
75
|
+
"test:zod4": "cp package.json .package.json.bak && pnpm add -D zod@^4.0.0 && pnpm test && mv .package.json.bak package.json && pnpm install",
|
|
76
|
+
"test:all-versions": "pnpm run test:zod3 && pnpm run test:zod4",
|
|
77
|
+
"test-all": "tsdown && node --experimental-transform-types --test && bun test && deno test"
|
|
78
|
+
}
|
|
79
|
+
}
|