@optique/valibot 1.1.0-dev.2146 → 1.1.0-dev.2148
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 +53 -8
- package/dist/index.cjs +85 -14
- package/dist/index.d.cts +26 -1
- package/dist/index.d.ts +26 -1
- package/dist/index.js +85 -15
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -142,6 +142,46 @@ const startDate = argument(
|
|
|
142
142
|
~~~~
|
|
143
143
|
|
|
144
144
|
|
|
145
|
+
Async schemas
|
|
146
|
+
-------------
|
|
147
|
+
|
|
148
|
+
Use `valibotAsync()` when a schema depends on async validations, and run the
|
|
149
|
+
containing parser with `runAsync()` or `await run()`:
|
|
150
|
+
|
|
151
|
+
~~~~ typescript
|
|
152
|
+
import { runAsync } from "@optique/run";
|
|
153
|
+
import { object } from "@optique/core/constructs";
|
|
154
|
+
import { option } from "@optique/core/primitives";
|
|
155
|
+
import { valibotAsync } from "@optique/valibot";
|
|
156
|
+
import * as v from "valibot";
|
|
157
|
+
|
|
158
|
+
async function checkProject(value: string): Promise<boolean> {
|
|
159
|
+
return await Promise.resolve(value.startsWith("project-"));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const parser = object({
|
|
163
|
+
project: option("--project",
|
|
164
|
+
valibotAsync(
|
|
165
|
+
v.pipeAsync(v.string(), v.checkAsync(checkProject, "Unknown project.")),
|
|
166
|
+
{ placeholder: "" },
|
|
167
|
+
),
|
|
168
|
+
),
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
const cli = await runAsync(parser);
|
|
172
|
+
~~~~
|
|
173
|
+
|
|
174
|
+
The `valibot()` helper remains synchronous and rejects schemas that require
|
|
175
|
+
Valibot's async parse path. `valibotAsync()` preserves metavar inference,
|
|
176
|
+
choices, suggestions, formatting, and custom errors. Fallback values from
|
|
177
|
+
`bindEnv()` or `bindConfig()` are validated by the same schema before they are
|
|
178
|
+
accepted.
|
|
179
|
+
|
|
180
|
+
Async validation can run during fallback resolution and other repeated parser
|
|
181
|
+
paths, including shell completion requests. Keep remote checks bounded and
|
|
182
|
+
cached when possible.
|
|
183
|
+
|
|
184
|
+
|
|
145
185
|
Custom error messages
|
|
146
186
|
---------------------
|
|
147
187
|
|
|
@@ -186,25 +226,30 @@ const port = option("-p",
|
|
|
186
226
|
// const port = option("-p", valibot(v.number()));
|
|
187
227
|
~~~~
|
|
188
228
|
|
|
189
|
-
###
|
|
229
|
+
### `valibot()` is synchronous
|
|
190
230
|
|
|
191
|
-
|
|
192
|
-
|
|
231
|
+
The `valibot()` helper returns a sync value parser, so async Valibot features
|
|
232
|
+
like `pipeAsync()` require `valibotAsync()`:
|
|
193
233
|
|
|
194
234
|
~~~~ typescript
|
|
195
235
|
import { option } from "@optique/core/primitives";
|
|
196
|
-
import { valibot } from "@optique/valibot";
|
|
236
|
+
import { valibot, valibotAsync } from "@optique/valibot";
|
|
197
237
|
import * as v from "valibot";
|
|
198
238
|
|
|
199
|
-
// ❌ Not supported
|
|
200
|
-
const
|
|
239
|
+
// ❌ Not supported by valibot()
|
|
240
|
+
const syncEmail = option("--email",
|
|
201
241
|
valibot(v.pipeAsync(v.string(),
|
|
202
242
|
v.checkAsync(async (val) => await checkDB(val))),
|
|
203
243
|
{ placeholder: "" }),
|
|
204
244
|
);
|
|
205
|
-
~~~~
|
|
206
245
|
|
|
207
|
-
|
|
246
|
+
// ✅ Use valibotAsync() and runAsync()
|
|
247
|
+
const asyncEmail = option("--email",
|
|
248
|
+
valibotAsync(v.pipeAsync(v.string(),
|
|
249
|
+
v.checkAsync(async (val) => await checkDB(val))),
|
|
250
|
+
{ placeholder: "" }),
|
|
251
|
+
);
|
|
252
|
+
~~~~
|
|
208
253
|
|
|
209
254
|
|
|
210
255
|
For more resources
|
package/dist/index.cjs
CHANGED
|
@@ -285,6 +285,23 @@ function inferChoices(schema) {
|
|
|
285
285
|
}
|
|
286
286
|
return void 0;
|
|
287
287
|
}
|
|
288
|
+
function validateOptions(functionName, options) {
|
|
289
|
+
if (options == null || typeof options !== "object") throw new TypeError(`${functionName}() requires an options object with a placeholder property.`);
|
|
290
|
+
if (!("placeholder" in options)) throw new TypeError(`${functionName}() options must include a placeholder property.`);
|
|
291
|
+
}
|
|
292
|
+
function formatValue(value, format) {
|
|
293
|
+
if (format) return format(value);
|
|
294
|
+
if (value instanceof Date) return Number.isNaN(value.getTime()) ? String(value) : value.toISOString();
|
|
295
|
+
if (typeof value !== "object" || value === null) return String(value);
|
|
296
|
+
if (Array.isArray(value)) return String(value);
|
|
297
|
+
const str = String(value);
|
|
298
|
+
if (str !== "[object Object]") return str;
|
|
299
|
+
const proto = Object.getPrototypeOf(value);
|
|
300
|
+
if (proto === Object.prototype || proto === null) try {
|
|
301
|
+
return JSON.stringify(value) ?? str;
|
|
302
|
+
} catch {}
|
|
303
|
+
return str;
|
|
304
|
+
}
|
|
288
305
|
/**
|
|
289
306
|
* Creates a value parser from a Valibot schema.
|
|
290
307
|
*
|
|
@@ -376,8 +393,7 @@ function inferChoices(schema) {
|
|
|
376
393
|
* @since 0.7.0
|
|
377
394
|
*/
|
|
378
395
|
function valibot$1(schema, options) {
|
|
379
|
-
|
|
380
|
-
if (!("placeholder" in options)) throw new TypeError("valibot() options must include a placeholder property.");
|
|
396
|
+
validateOptions("valibot", options);
|
|
381
397
|
if (containsAsyncSchema(schema)) throw new TypeError("Async Valibot schemas (e.g., async validations) are not supported by valibot(). Use synchronous schemas instead.");
|
|
382
398
|
const choices = inferChoices(schema);
|
|
383
399
|
const metavar = options.metavar ?? inferMetavar(schema);
|
|
@@ -413,21 +429,76 @@ function valibot$1(schema, options) {
|
|
|
413
429
|
};
|
|
414
430
|
},
|
|
415
431
|
format(value) {
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
432
|
+
return formatValue(value, options.format);
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
return parser;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Creates an async value parser from a Valibot schema.
|
|
439
|
+
*
|
|
440
|
+
* This parser validates CLI argument strings with Valibot's async safe-parse
|
|
441
|
+
* path, so schemas using `pipeAsync()`, `checkAsync()`, or other async actions
|
|
442
|
+
* can be reused directly in asynchronous Optique parsers.
|
|
443
|
+
*
|
|
444
|
+
* The metavar, choices, suggestions, formatting, and error customization
|
|
445
|
+
* follow the same rules as {@link valibot}. Because the returned parser runs
|
|
446
|
+
* asynchronously, use it with `parseAsync()`, `run()`, or `runAsync()`.
|
|
447
|
+
*
|
|
448
|
+
* @template T The output type of the Valibot schema.
|
|
449
|
+
* @param schema A Valibot schema to validate input against.
|
|
450
|
+
* @param options Configuration for the parser, including a required
|
|
451
|
+
* `placeholder` value used during deferred prompt resolution.
|
|
452
|
+
* @returns An async value parser that validates inputs using the provided
|
|
453
|
+
* schema.
|
|
454
|
+
*
|
|
455
|
+
* @throws {TypeError} If `options` is missing, not an object, or does not
|
|
456
|
+
* include `placeholder`.
|
|
457
|
+
* @throws {TypeError} If the resolved `metavar` is an empty string.
|
|
458
|
+
* @since 1.1.0
|
|
459
|
+
*/
|
|
460
|
+
function valibotAsync(schema, options) {
|
|
461
|
+
validateOptions("valibotAsync", options);
|
|
462
|
+
const syncSchema = schema;
|
|
463
|
+
const choices = inferChoices(syncSchema);
|
|
464
|
+
const metavar = options.metavar ?? inferMetavar(syncSchema);
|
|
465
|
+
(0, __optique_core_nonempty.ensureNonEmptyString)(metavar);
|
|
466
|
+
const parser = {
|
|
467
|
+
mode: "async",
|
|
468
|
+
metavar,
|
|
469
|
+
placeholder: options.placeholder,
|
|
470
|
+
...choices != null && choices.length > 0 ? {
|
|
471
|
+
choices: Object.freeze(choices),
|
|
472
|
+
async *suggest(prefix) {
|
|
473
|
+
for (const c of choices) if (c.startsWith(prefix)) yield {
|
|
474
|
+
kind: "literal",
|
|
475
|
+
text: c
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
} : {},
|
|
479
|
+
async parse(input) {
|
|
480
|
+
const result = await (0, valibot.safeParseAsync)(schema, input);
|
|
481
|
+
if (result.success) return {
|
|
482
|
+
success: true,
|
|
483
|
+
value: result.output
|
|
484
|
+
};
|
|
485
|
+
if (options.errors?.valibotError) return {
|
|
486
|
+
success: false,
|
|
487
|
+
error: typeof options.errors.valibotError === "function" ? options.errors.valibotError(result.issues, input) : options.errors.valibotError
|
|
488
|
+
};
|
|
489
|
+
const firstIssue = result.issues[0];
|
|
490
|
+
return {
|
|
491
|
+
success: false,
|
|
492
|
+
error: __optique_core_message.message`${firstIssue?.message ?? "Validation failed"}`
|
|
493
|
+
};
|
|
494
|
+
},
|
|
495
|
+
format(value) {
|
|
496
|
+
return formatValue(value, options.format);
|
|
427
497
|
}
|
|
428
498
|
};
|
|
429
499
|
return parser;
|
|
430
500
|
}
|
|
431
501
|
|
|
432
502
|
//#endregion
|
|
433
|
-
exports.valibot = valibot$1;
|
|
503
|
+
exports.valibot = valibot$1;
|
|
504
|
+
exports.valibotAsync = valibotAsync;
|
package/dist/index.d.cts
CHANGED
|
@@ -139,5 +139,30 @@ interface ValibotParserOptions<T = unknown> {
|
|
|
139
139
|
* @since 0.7.0
|
|
140
140
|
*/
|
|
141
141
|
declare function valibot<T>(schema: v.BaseSchema<unknown, T, v.BaseIssue<unknown>>, options: ValibotParserOptions<T>): ValueParser<"sync", T>;
|
|
142
|
+
type AnyValibotSchema<T> = v.BaseSchema<unknown, T, v.BaseIssue<unknown>> | v.BaseSchemaAsync<unknown, T, v.BaseIssue<unknown>>;
|
|
143
|
+
/**
|
|
144
|
+
* Creates an async value parser from a Valibot schema.
|
|
145
|
+
*
|
|
146
|
+
* This parser validates CLI argument strings with Valibot's async safe-parse
|
|
147
|
+
* path, so schemas using `pipeAsync()`, `checkAsync()`, or other async actions
|
|
148
|
+
* can be reused directly in asynchronous Optique parsers.
|
|
149
|
+
*
|
|
150
|
+
* The metavar, choices, suggestions, formatting, and error customization
|
|
151
|
+
* follow the same rules as {@link valibot}. Because the returned parser runs
|
|
152
|
+
* asynchronously, use it with `parseAsync()`, `run()`, or `runAsync()`.
|
|
153
|
+
*
|
|
154
|
+
* @template T The output type of the Valibot schema.
|
|
155
|
+
* @param schema A Valibot schema to validate input against.
|
|
156
|
+
* @param options Configuration for the parser, including a required
|
|
157
|
+
* `placeholder` value used during deferred prompt resolution.
|
|
158
|
+
* @returns An async value parser that validates inputs using the provided
|
|
159
|
+
* schema.
|
|
160
|
+
*
|
|
161
|
+
* @throws {TypeError} If `options` is missing, not an object, or does not
|
|
162
|
+
* include `placeholder`.
|
|
163
|
+
* @throws {TypeError} If the resolved `metavar` is an empty string.
|
|
164
|
+
* @since 1.1.0
|
|
165
|
+
*/
|
|
166
|
+
declare function valibotAsync<T>(schema: AnyValibotSchema<T>, options: ValibotParserOptions<T>): ValueParser<"async", T>;
|
|
142
167
|
//#endregion
|
|
143
|
-
export { ValibotParserOptions, valibot };
|
|
168
|
+
export { ValibotParserOptions, valibot, valibotAsync };
|
package/dist/index.d.ts
CHANGED
|
@@ -139,5 +139,30 @@ interface ValibotParserOptions<T = unknown> {
|
|
|
139
139
|
* @since 0.7.0
|
|
140
140
|
*/
|
|
141
141
|
declare function valibot<T>(schema: v.BaseSchema<unknown, T, v.BaseIssue<unknown>>, options: ValibotParserOptions<T>): ValueParser<"sync", T>;
|
|
142
|
+
type AnyValibotSchema<T> = v.BaseSchema<unknown, T, v.BaseIssue<unknown>> | v.BaseSchemaAsync<unknown, T, v.BaseIssue<unknown>>;
|
|
143
|
+
/**
|
|
144
|
+
* Creates an async value parser from a Valibot schema.
|
|
145
|
+
*
|
|
146
|
+
* This parser validates CLI argument strings with Valibot's async safe-parse
|
|
147
|
+
* path, so schemas using `pipeAsync()`, `checkAsync()`, or other async actions
|
|
148
|
+
* can be reused directly in asynchronous Optique parsers.
|
|
149
|
+
*
|
|
150
|
+
* The metavar, choices, suggestions, formatting, and error customization
|
|
151
|
+
* follow the same rules as {@link valibot}. Because the returned parser runs
|
|
152
|
+
* asynchronously, use it with `parseAsync()`, `run()`, or `runAsync()`.
|
|
153
|
+
*
|
|
154
|
+
* @template T The output type of the Valibot schema.
|
|
155
|
+
* @param schema A Valibot schema to validate input against.
|
|
156
|
+
* @param options Configuration for the parser, including a required
|
|
157
|
+
* `placeholder` value used during deferred prompt resolution.
|
|
158
|
+
* @returns An async value parser that validates inputs using the provided
|
|
159
|
+
* schema.
|
|
160
|
+
*
|
|
161
|
+
* @throws {TypeError} If `options` is missing, not an object, or does not
|
|
162
|
+
* include `placeholder`.
|
|
163
|
+
* @throws {TypeError} If the resolved `metavar` is an empty string.
|
|
164
|
+
* @since 1.1.0
|
|
165
|
+
*/
|
|
166
|
+
declare function valibotAsync<T>(schema: AnyValibotSchema<T>, options: ValibotParserOptions<T>): ValueParser<"async", T>;
|
|
142
167
|
//#endregion
|
|
143
|
-
export { ValibotParserOptions, valibot };
|
|
168
|
+
export { ValibotParserOptions, valibot, valibotAsync };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { message } from "@optique/core/message";
|
|
2
2
|
import { ensureNonEmptyString } from "@optique/core/nonempty";
|
|
3
|
-
import { safeParse } from "valibot";
|
|
3
|
+
import { safeParse, safeParseAsync } from "valibot";
|
|
4
4
|
|
|
5
5
|
//#region src/index.ts
|
|
6
6
|
/**
|
|
@@ -262,6 +262,23 @@ function inferChoices(schema) {
|
|
|
262
262
|
}
|
|
263
263
|
return void 0;
|
|
264
264
|
}
|
|
265
|
+
function validateOptions(functionName, options) {
|
|
266
|
+
if (options == null || typeof options !== "object") throw new TypeError(`${functionName}() requires an options object with a placeholder property.`);
|
|
267
|
+
if (!("placeholder" in options)) throw new TypeError(`${functionName}() options must include a placeholder property.`);
|
|
268
|
+
}
|
|
269
|
+
function formatValue(value, format) {
|
|
270
|
+
if (format) return format(value);
|
|
271
|
+
if (value instanceof Date) return Number.isNaN(value.getTime()) ? String(value) : value.toISOString();
|
|
272
|
+
if (typeof value !== "object" || value === null) return String(value);
|
|
273
|
+
if (Array.isArray(value)) return String(value);
|
|
274
|
+
const str = String(value);
|
|
275
|
+
if (str !== "[object Object]") return str;
|
|
276
|
+
const proto = Object.getPrototypeOf(value);
|
|
277
|
+
if (proto === Object.prototype || proto === null) try {
|
|
278
|
+
return JSON.stringify(value) ?? str;
|
|
279
|
+
} catch {}
|
|
280
|
+
return str;
|
|
281
|
+
}
|
|
265
282
|
/**
|
|
266
283
|
* Creates a value parser from a Valibot schema.
|
|
267
284
|
*
|
|
@@ -353,8 +370,7 @@ function inferChoices(schema) {
|
|
|
353
370
|
* @since 0.7.0
|
|
354
371
|
*/
|
|
355
372
|
function valibot(schema, options) {
|
|
356
|
-
|
|
357
|
-
if (!("placeholder" in options)) throw new TypeError("valibot() options must include a placeholder property.");
|
|
373
|
+
validateOptions("valibot", options);
|
|
358
374
|
if (containsAsyncSchema(schema)) throw new TypeError("Async Valibot schemas (e.g., async validations) are not supported by valibot(). Use synchronous schemas instead.");
|
|
359
375
|
const choices = inferChoices(schema);
|
|
360
376
|
const metavar = options.metavar ?? inferMetavar(schema);
|
|
@@ -390,21 +406,75 @@ function valibot(schema, options) {
|
|
|
390
406
|
};
|
|
391
407
|
},
|
|
392
408
|
format(value) {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
409
|
+
return formatValue(value, options.format);
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
return parser;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Creates an async value parser from a Valibot schema.
|
|
416
|
+
*
|
|
417
|
+
* This parser validates CLI argument strings with Valibot's async safe-parse
|
|
418
|
+
* path, so schemas using `pipeAsync()`, `checkAsync()`, or other async actions
|
|
419
|
+
* can be reused directly in asynchronous Optique parsers.
|
|
420
|
+
*
|
|
421
|
+
* The metavar, choices, suggestions, formatting, and error customization
|
|
422
|
+
* follow the same rules as {@link valibot}. Because the returned parser runs
|
|
423
|
+
* asynchronously, use it with `parseAsync()`, `run()`, or `runAsync()`.
|
|
424
|
+
*
|
|
425
|
+
* @template T The output type of the Valibot schema.
|
|
426
|
+
* @param schema A Valibot schema to validate input against.
|
|
427
|
+
* @param options Configuration for the parser, including a required
|
|
428
|
+
* `placeholder` value used during deferred prompt resolution.
|
|
429
|
+
* @returns An async value parser that validates inputs using the provided
|
|
430
|
+
* schema.
|
|
431
|
+
*
|
|
432
|
+
* @throws {TypeError} If `options` is missing, not an object, or does not
|
|
433
|
+
* include `placeholder`.
|
|
434
|
+
* @throws {TypeError} If the resolved `metavar` is an empty string.
|
|
435
|
+
* @since 1.1.0
|
|
436
|
+
*/
|
|
437
|
+
function valibotAsync(schema, options) {
|
|
438
|
+
validateOptions("valibotAsync", options);
|
|
439
|
+
const syncSchema = schema;
|
|
440
|
+
const choices = inferChoices(syncSchema);
|
|
441
|
+
const metavar = options.metavar ?? inferMetavar(syncSchema);
|
|
442
|
+
ensureNonEmptyString(metavar);
|
|
443
|
+
const parser = {
|
|
444
|
+
mode: "async",
|
|
445
|
+
metavar,
|
|
446
|
+
placeholder: options.placeholder,
|
|
447
|
+
...choices != null && choices.length > 0 ? {
|
|
448
|
+
choices: Object.freeze(choices),
|
|
449
|
+
async *suggest(prefix) {
|
|
450
|
+
for (const c of choices) if (c.startsWith(prefix)) yield {
|
|
451
|
+
kind: "literal",
|
|
452
|
+
text: c
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
} : {},
|
|
456
|
+
async parse(input) {
|
|
457
|
+
const result = await safeParseAsync(schema, input);
|
|
458
|
+
if (result.success) return {
|
|
459
|
+
success: true,
|
|
460
|
+
value: result.output
|
|
461
|
+
};
|
|
462
|
+
if (options.errors?.valibotError) return {
|
|
463
|
+
success: false,
|
|
464
|
+
error: typeof options.errors.valibotError === "function" ? options.errors.valibotError(result.issues, input) : options.errors.valibotError
|
|
465
|
+
};
|
|
466
|
+
const firstIssue = result.issues[0];
|
|
467
|
+
return {
|
|
468
|
+
success: false,
|
|
469
|
+
error: message`${firstIssue?.message ?? "Validation failed"}`
|
|
470
|
+
};
|
|
471
|
+
},
|
|
472
|
+
format(value) {
|
|
473
|
+
return formatValue(value, options.format);
|
|
404
474
|
}
|
|
405
475
|
};
|
|
406
476
|
return parser;
|
|
407
477
|
}
|
|
408
478
|
|
|
409
479
|
//#endregion
|
|
410
|
-
export { valibot };
|
|
480
|
+
export { valibot, valibotAsync };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@optique/valibot",
|
|
3
|
-
"version": "1.1.0-dev.
|
|
3
|
+
"version": "1.1.0-dev.2148",
|
|
4
4
|
"description": "Valibot value parsers for Optique",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"CLI",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"valibot": "^1.2.0"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@optique/core": "1.1.0-dev.
|
|
60
|
+
"@optique/core": "1.1.0-dev.2148+ab56ac96"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@types/node": "^24.0.0",
|