@optique/valibot 1.0.0-dev.1344 → 1.0.0-dev.1359
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/dist/index.cjs +145 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +145 -0
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -27,6 +27,148 @@ const valibot = __toESM(require("valibot"));
|
|
|
27
27
|
|
|
28
28
|
//#region src/index.ts
|
|
29
29
|
/**
|
|
30
|
+
* Valibot transformation action types that are known to be non-rejecting and
|
|
31
|
+
* type-preserving (they transform a string into a string without ever adding
|
|
32
|
+
* issues). All other transformation types (transform, raw_transform,
|
|
33
|
+
* parse_json, to_number, to_boolean, etc.) may reject input or change the
|
|
34
|
+
* value type.
|
|
35
|
+
*/
|
|
36
|
+
const SAFE_TRANSFORMATION_TYPES = new Set([
|
|
37
|
+
"trim",
|
|
38
|
+
"to_lower_case",
|
|
39
|
+
"to_upper_case",
|
|
40
|
+
"normalize",
|
|
41
|
+
"to_min_value",
|
|
42
|
+
"to_max_value",
|
|
43
|
+
"trim_start",
|
|
44
|
+
"trim_end",
|
|
45
|
+
"readonly",
|
|
46
|
+
"brand",
|
|
47
|
+
"flavor"
|
|
48
|
+
]);
|
|
49
|
+
/**
|
|
50
|
+
* Checks whether a schema synchronously accepts every possible input value.
|
|
51
|
+
* This includes:
|
|
52
|
+
* - `v.unknown()`, `v.any()` (accept everything regardless of input type)
|
|
53
|
+
* - Bare `v.string()` without a pipe (accepts every string)
|
|
54
|
+
* - Any wrapper with a `wrapped` field pointing to a catch-all schema
|
|
55
|
+
* (e.g., `v.optional()`, `v.nullable()`, `v.nonOptional()`, etc.)
|
|
56
|
+
*
|
|
57
|
+
* Piped schemas are considered catch-all only when the base type is
|
|
58
|
+
* `string`/`unknown`/`any` and every pipe action is a non-rejecting
|
|
59
|
+
* transformation (not a validation or nested schema).
|
|
60
|
+
*
|
|
61
|
+
* @param afterTransform When true, only type-agnostic catch-alls
|
|
62
|
+
* (`v.unknown()`, `v.any()`) are recognized. String-based catch-alls
|
|
63
|
+
* are not trusted since the input type may no longer be a string.
|
|
64
|
+
*/
|
|
65
|
+
function isCatchAllSchema(schema, afterTransform = false) {
|
|
66
|
+
const s = schema;
|
|
67
|
+
if (s.async) return false;
|
|
68
|
+
if ("fallback" in s) return true;
|
|
69
|
+
if (s.type === "unknown" || s.type === "any") {
|
|
70
|
+
if (!s.pipe) return true;
|
|
71
|
+
return s.pipe.slice(1).every((action) => {
|
|
72
|
+
const a = action;
|
|
73
|
+
if (a.kind === "validation") return false;
|
|
74
|
+
if (a.kind === "schema") return isCatchAllSchema(action, afterTransform);
|
|
75
|
+
return SAFE_TRANSFORMATION_TYPES.has(a.type ?? "");
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
if (!afterTransform && s.type === "string") {
|
|
79
|
+
if (!s.pipe) return true;
|
|
80
|
+
return s.pipe.slice(1).every((action) => {
|
|
81
|
+
const a = action;
|
|
82
|
+
if (a.kind === "validation") return false;
|
|
83
|
+
if (a.kind === "schema") return isCatchAllSchema(action, afterTransform);
|
|
84
|
+
return SAFE_TRANSFORMATION_TYPES.has(a.type ?? "");
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
if (s.wrapped && !s.pipe) return isCatchAllSchema(s.wrapped, afterTransform);
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Recursively checks whether a Valibot schema contains any async parts
|
|
92
|
+
* (e.g., `pipeAsync`, `checkAsync`). Wrapper schemas such as `optional()`,
|
|
93
|
+
* `nullable()`, `nullish()`, and `union()` keep `async === false` on the
|
|
94
|
+
* outer layer even when they wrap async inner schemas, so a shallow check
|
|
95
|
+
* on the top-level `async` property is not sufficient.
|
|
96
|
+
*
|
|
97
|
+
* Known limitations:
|
|
98
|
+
* - `v.variant()` arms are treated like union arms, but the catch-all
|
|
99
|
+
* detection does not recognize object-shaped variant arms. Variant
|
|
100
|
+
* schemas with async arms after a broad discriminator will be
|
|
101
|
+
* conservatively rejected.
|
|
102
|
+
* - `v.lazy()` schemas are not inspected because the getter depends on
|
|
103
|
+
* actual parse input, making static analysis unreliable.
|
|
104
|
+
*
|
|
105
|
+
* @param afterTransform When true, a preceding `v.transform()` may have
|
|
106
|
+
* changed the value type. Container members become reachable and
|
|
107
|
+
* string-based union catch-all arms are no longer trusted.
|
|
108
|
+
*/
|
|
109
|
+
function containsAsyncSchema(schema, visited = /* @__PURE__ */ new WeakMap(), afterTransform = false) {
|
|
110
|
+
const prev = visited.get(schema);
|
|
111
|
+
if (prev !== void 0 && (prev || !afterTransform)) return false;
|
|
112
|
+
visited.set(schema, (prev ?? false) || afterTransform);
|
|
113
|
+
const s = schema;
|
|
114
|
+
if (s.async) return true;
|
|
115
|
+
if (s.wrapped && !s.pipe) return containsAsyncSchema(s.wrapped, visited, afterTransform);
|
|
116
|
+
if (s.options && Array.isArray(s.options)) {
|
|
117
|
+
if (s.type === "union") for (const option of s.options) {
|
|
118
|
+
if (typeof option !== "object" || option == null) continue;
|
|
119
|
+
if (isCatchAllSchema(option, afterTransform)) break;
|
|
120
|
+
if (containsAsyncSchema(option, visited, afterTransform)) return true;
|
|
121
|
+
}
|
|
122
|
+
else if (s.type === "variant") {
|
|
123
|
+
if (afterTransform) {
|
|
124
|
+
for (const option of s.options) if (typeof option === "object" && option != null) {
|
|
125
|
+
if (containsAsyncSchema(option, visited, true)) return true;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
} else for (const option of s.options) if (typeof option === "object" && option != null) {
|
|
129
|
+
if (containsAsyncSchema(option, visited, afterTransform)) return true;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (s.pipe && Array.isArray(s.pipe)) {
|
|
133
|
+
let seenTransform = afterTransform;
|
|
134
|
+
for (const action of s.pipe) {
|
|
135
|
+
if (action.async) return true;
|
|
136
|
+
const a = action;
|
|
137
|
+
if (a.kind === "transformation" && !SAFE_TRANSFORMATION_TYPES.has(a.type ?? "")) seenTransform = true;
|
|
138
|
+
if (a.kind === "schema") {
|
|
139
|
+
if (containsAsyncSchema(action, visited, seenTransform)) return true;
|
|
140
|
+
if (!seenTransform) {
|
|
141
|
+
const innerPipe = action.pipe;
|
|
142
|
+
if (innerPipe && Array.isArray(innerPipe)) for (const innerAction of innerPipe) {
|
|
143
|
+
const ia = innerAction;
|
|
144
|
+
if (ia.kind === "transformation" && !SAFE_TRANSFORMATION_TYPES.has(ia.type ?? "")) {
|
|
145
|
+
seenTransform = true;
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (afterTransform) {
|
|
154
|
+
if (s.entries) {
|
|
155
|
+
for (const entry of Object.values(s.entries)) if (containsAsyncSchema(entry, visited, true)) return true;
|
|
156
|
+
}
|
|
157
|
+
if (s.item && containsAsyncSchema(s.item, visited, true)) return true;
|
|
158
|
+
if (s.items && Array.isArray(s.items)) {
|
|
159
|
+
for (const item of s.items) if (containsAsyncSchema(item, visited, true)) return true;
|
|
160
|
+
}
|
|
161
|
+
if (s.key && typeof s.key === "object" && containsAsyncSchema(s.key, visited, true)) return true;
|
|
162
|
+
if (s.value && containsAsyncSchema(s.value, visited, true)) return true;
|
|
163
|
+
if (s.rest && containsAsyncSchema(s.rest, visited, true)) return true;
|
|
164
|
+
if (s.type === "promise") {
|
|
165
|
+
const promiseInner = schema.message;
|
|
166
|
+
if (typeof promiseInner === "object" && promiseInner != null && "kind" in promiseInner && containsAsyncSchema(promiseInner, visited, true)) return true;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
30
172
|
* Infers an appropriate metavar string from a Valibot schema.
|
|
31
173
|
*
|
|
32
174
|
* This function analyzes the Valibot schema's internal structure to determine
|
|
@@ -221,9 +363,12 @@ function inferChoices(schema) {
|
|
|
221
363
|
* ```
|
|
222
364
|
*
|
|
223
365
|
* @throws {TypeError} If the resolved `metavar` is an empty string.
|
|
366
|
+
* @throws {TypeError} If the schema contains async validations that cannot be
|
|
367
|
+
* executed synchronously.
|
|
224
368
|
* @since 0.7.0
|
|
225
369
|
*/
|
|
226
370
|
function valibot$1(schema, options = {}) {
|
|
371
|
+
if (containsAsyncSchema(schema)) throw new TypeError("Async Valibot schemas (e.g., async validations) are not supported by valibot(). Use synchronous schemas instead.");
|
|
227
372
|
const choices = inferChoices(schema);
|
|
228
373
|
const metavar = options.metavar ?? inferMetavar(schema);
|
|
229
374
|
(0, __optique_core_nonempty.ensureNonEmptyString)(metavar);
|
package/dist/index.d.cts
CHANGED
|
@@ -107,6 +107,8 @@ interface ValibotParserOptions {
|
|
|
107
107
|
* ```
|
|
108
108
|
*
|
|
109
109
|
* @throws {TypeError} If the resolved `metavar` is an empty string.
|
|
110
|
+
* @throws {TypeError} If the schema contains async validations that cannot be
|
|
111
|
+
* executed synchronously.
|
|
110
112
|
* @since 0.7.0
|
|
111
113
|
*/
|
|
112
114
|
declare function valibot<T>(schema: v.BaseSchema<unknown, T, v.BaseIssue<unknown>>, options?: ValibotParserOptions): ValueParser<"sync", T>;
|
package/dist/index.d.ts
CHANGED
|
@@ -107,6 +107,8 @@ interface ValibotParserOptions {
|
|
|
107
107
|
* ```
|
|
108
108
|
*
|
|
109
109
|
* @throws {TypeError} If the resolved `metavar` is an empty string.
|
|
110
|
+
* @throws {TypeError} If the schema contains async validations that cannot be
|
|
111
|
+
* executed synchronously.
|
|
110
112
|
* @since 0.7.0
|
|
111
113
|
*/
|
|
112
114
|
declare function valibot<T>(schema: v.BaseSchema<unknown, T, v.BaseIssue<unknown>>, options?: ValibotParserOptions): ValueParser<"sync", T>;
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,148 @@ import { safeParse } from "valibot";
|
|
|
4
4
|
|
|
5
5
|
//#region src/index.ts
|
|
6
6
|
/**
|
|
7
|
+
* Valibot transformation action types that are known to be non-rejecting and
|
|
8
|
+
* type-preserving (they transform a string into a string without ever adding
|
|
9
|
+
* issues). All other transformation types (transform, raw_transform,
|
|
10
|
+
* parse_json, to_number, to_boolean, etc.) may reject input or change the
|
|
11
|
+
* value type.
|
|
12
|
+
*/
|
|
13
|
+
const SAFE_TRANSFORMATION_TYPES = new Set([
|
|
14
|
+
"trim",
|
|
15
|
+
"to_lower_case",
|
|
16
|
+
"to_upper_case",
|
|
17
|
+
"normalize",
|
|
18
|
+
"to_min_value",
|
|
19
|
+
"to_max_value",
|
|
20
|
+
"trim_start",
|
|
21
|
+
"trim_end",
|
|
22
|
+
"readonly",
|
|
23
|
+
"brand",
|
|
24
|
+
"flavor"
|
|
25
|
+
]);
|
|
26
|
+
/**
|
|
27
|
+
* Checks whether a schema synchronously accepts every possible input value.
|
|
28
|
+
* This includes:
|
|
29
|
+
* - `v.unknown()`, `v.any()` (accept everything regardless of input type)
|
|
30
|
+
* - Bare `v.string()` without a pipe (accepts every string)
|
|
31
|
+
* - Any wrapper with a `wrapped` field pointing to a catch-all schema
|
|
32
|
+
* (e.g., `v.optional()`, `v.nullable()`, `v.nonOptional()`, etc.)
|
|
33
|
+
*
|
|
34
|
+
* Piped schemas are considered catch-all only when the base type is
|
|
35
|
+
* `string`/`unknown`/`any` and every pipe action is a non-rejecting
|
|
36
|
+
* transformation (not a validation or nested schema).
|
|
37
|
+
*
|
|
38
|
+
* @param afterTransform When true, only type-agnostic catch-alls
|
|
39
|
+
* (`v.unknown()`, `v.any()`) are recognized. String-based catch-alls
|
|
40
|
+
* are not trusted since the input type may no longer be a string.
|
|
41
|
+
*/
|
|
42
|
+
function isCatchAllSchema(schema, afterTransform = false) {
|
|
43
|
+
const s = schema;
|
|
44
|
+
if (s.async) return false;
|
|
45
|
+
if ("fallback" in s) return true;
|
|
46
|
+
if (s.type === "unknown" || s.type === "any") {
|
|
47
|
+
if (!s.pipe) return true;
|
|
48
|
+
return s.pipe.slice(1).every((action) => {
|
|
49
|
+
const a = action;
|
|
50
|
+
if (a.kind === "validation") return false;
|
|
51
|
+
if (a.kind === "schema") return isCatchAllSchema(action, afterTransform);
|
|
52
|
+
return SAFE_TRANSFORMATION_TYPES.has(a.type ?? "");
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (!afterTransform && s.type === "string") {
|
|
56
|
+
if (!s.pipe) return true;
|
|
57
|
+
return s.pipe.slice(1).every((action) => {
|
|
58
|
+
const a = action;
|
|
59
|
+
if (a.kind === "validation") return false;
|
|
60
|
+
if (a.kind === "schema") return isCatchAllSchema(action, afterTransform);
|
|
61
|
+
return SAFE_TRANSFORMATION_TYPES.has(a.type ?? "");
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
if (s.wrapped && !s.pipe) return isCatchAllSchema(s.wrapped, afterTransform);
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Recursively checks whether a Valibot schema contains any async parts
|
|
69
|
+
* (e.g., `pipeAsync`, `checkAsync`). Wrapper schemas such as `optional()`,
|
|
70
|
+
* `nullable()`, `nullish()`, and `union()` keep `async === false` on the
|
|
71
|
+
* outer layer even when they wrap async inner schemas, so a shallow check
|
|
72
|
+
* on the top-level `async` property is not sufficient.
|
|
73
|
+
*
|
|
74
|
+
* Known limitations:
|
|
75
|
+
* - `v.variant()` arms are treated like union arms, but the catch-all
|
|
76
|
+
* detection does not recognize object-shaped variant arms. Variant
|
|
77
|
+
* schemas with async arms after a broad discriminator will be
|
|
78
|
+
* conservatively rejected.
|
|
79
|
+
* - `v.lazy()` schemas are not inspected because the getter depends on
|
|
80
|
+
* actual parse input, making static analysis unreliable.
|
|
81
|
+
*
|
|
82
|
+
* @param afterTransform When true, a preceding `v.transform()` may have
|
|
83
|
+
* changed the value type. Container members become reachable and
|
|
84
|
+
* string-based union catch-all arms are no longer trusted.
|
|
85
|
+
*/
|
|
86
|
+
function containsAsyncSchema(schema, visited = /* @__PURE__ */ new WeakMap(), afterTransform = false) {
|
|
87
|
+
const prev = visited.get(schema);
|
|
88
|
+
if (prev !== void 0 && (prev || !afterTransform)) return false;
|
|
89
|
+
visited.set(schema, (prev ?? false) || afterTransform);
|
|
90
|
+
const s = schema;
|
|
91
|
+
if (s.async) return true;
|
|
92
|
+
if (s.wrapped && !s.pipe) return containsAsyncSchema(s.wrapped, visited, afterTransform);
|
|
93
|
+
if (s.options && Array.isArray(s.options)) {
|
|
94
|
+
if (s.type === "union") for (const option of s.options) {
|
|
95
|
+
if (typeof option !== "object" || option == null) continue;
|
|
96
|
+
if (isCatchAllSchema(option, afterTransform)) break;
|
|
97
|
+
if (containsAsyncSchema(option, visited, afterTransform)) return true;
|
|
98
|
+
}
|
|
99
|
+
else if (s.type === "variant") {
|
|
100
|
+
if (afterTransform) {
|
|
101
|
+
for (const option of s.options) if (typeof option === "object" && option != null) {
|
|
102
|
+
if (containsAsyncSchema(option, visited, true)) return true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
} else for (const option of s.options) if (typeof option === "object" && option != null) {
|
|
106
|
+
if (containsAsyncSchema(option, visited, afterTransform)) return true;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (s.pipe && Array.isArray(s.pipe)) {
|
|
110
|
+
let seenTransform = afterTransform;
|
|
111
|
+
for (const action of s.pipe) {
|
|
112
|
+
if (action.async) return true;
|
|
113
|
+
const a = action;
|
|
114
|
+
if (a.kind === "transformation" && !SAFE_TRANSFORMATION_TYPES.has(a.type ?? "")) seenTransform = true;
|
|
115
|
+
if (a.kind === "schema") {
|
|
116
|
+
if (containsAsyncSchema(action, visited, seenTransform)) return true;
|
|
117
|
+
if (!seenTransform) {
|
|
118
|
+
const innerPipe = action.pipe;
|
|
119
|
+
if (innerPipe && Array.isArray(innerPipe)) for (const innerAction of innerPipe) {
|
|
120
|
+
const ia = innerAction;
|
|
121
|
+
if (ia.kind === "transformation" && !SAFE_TRANSFORMATION_TYPES.has(ia.type ?? "")) {
|
|
122
|
+
seenTransform = true;
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (afterTransform) {
|
|
131
|
+
if (s.entries) {
|
|
132
|
+
for (const entry of Object.values(s.entries)) if (containsAsyncSchema(entry, visited, true)) return true;
|
|
133
|
+
}
|
|
134
|
+
if (s.item && containsAsyncSchema(s.item, visited, true)) return true;
|
|
135
|
+
if (s.items && Array.isArray(s.items)) {
|
|
136
|
+
for (const item of s.items) if (containsAsyncSchema(item, visited, true)) return true;
|
|
137
|
+
}
|
|
138
|
+
if (s.key && typeof s.key === "object" && containsAsyncSchema(s.key, visited, true)) return true;
|
|
139
|
+
if (s.value && containsAsyncSchema(s.value, visited, true)) return true;
|
|
140
|
+
if (s.rest && containsAsyncSchema(s.rest, visited, true)) return true;
|
|
141
|
+
if (s.type === "promise") {
|
|
142
|
+
const promiseInner = schema.message;
|
|
143
|
+
if (typeof promiseInner === "object" && promiseInner != null && "kind" in promiseInner && containsAsyncSchema(promiseInner, visited, true)) return true;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
7
149
|
* Infers an appropriate metavar string from a Valibot schema.
|
|
8
150
|
*
|
|
9
151
|
* This function analyzes the Valibot schema's internal structure to determine
|
|
@@ -198,9 +340,12 @@ function inferChoices(schema) {
|
|
|
198
340
|
* ```
|
|
199
341
|
*
|
|
200
342
|
* @throws {TypeError} If the resolved `metavar` is an empty string.
|
|
343
|
+
* @throws {TypeError} If the schema contains async validations that cannot be
|
|
344
|
+
* executed synchronously.
|
|
201
345
|
* @since 0.7.0
|
|
202
346
|
*/
|
|
203
347
|
function valibot(schema, options = {}) {
|
|
348
|
+
if (containsAsyncSchema(schema)) throw new TypeError("Async Valibot schemas (e.g., async validations) are not supported by valibot(). Use synchronous schemas instead.");
|
|
204
349
|
const choices = inferChoices(schema);
|
|
205
350
|
const metavar = options.metavar ?? inferMetavar(schema);
|
|
206
351
|
ensureNonEmptyString(metavar);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@optique/valibot",
|
|
3
|
-
"version": "1.0.0-dev.
|
|
3
|
+
"version": "1.0.0-dev.1359+1fa707c2",
|
|
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.0.0-dev.
|
|
60
|
+
"@optique/core": "1.0.0-dev.1359+1fa707c2"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@types/node": "^20.19.9",
|