@mpen/valibot-extras 0.1.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/README.md +148 -0
- package/dist/index.d.ts +132 -0
- package/dist/index.js +211 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# @mpen/valibot-extras
|
|
2
|
+
|
|
3
|
+
Extras and extensions for [Valibot](https://valibot.dev/).
|
|
4
|
+
|
|
5
|
+
## Motivation
|
|
6
|
+
|
|
7
|
+
Valibot's built-in string validators have some surprising behaviors:
|
|
8
|
+
|
|
9
|
+
### `v.string()` accepts ill-formed strings
|
|
10
|
+
|
|
11
|
+
`v.string()` happily accepts strings containing lone/unpaired UTF-16 surrogates:
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
v.safeParse(v.string(), '\ud800').success // ✅ true — but this is not valid Unicode!
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
These ill-formed strings can cause issues downstream (e.g. when serializing to JSON, sending over the network, or storing in a database).
|
|
18
|
+
|
|
19
|
+
### `v.minLength` / `v.maxLength` count code units, not characters
|
|
20
|
+
|
|
21
|
+
Valibot's length validators use JavaScript's `.length` property, which counts UTF-16 code units — not visible characters. Characters outside the Basic Multilingual Plane (emoji, CJK ideographs, etc.) are represented as surrogate pairs and count as **2**:
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
// '𠮷' is a single character, but 2 UTF-16 code units
|
|
25
|
+
v.safeParse(v.pipe(v.string(), v.minLength(2)), '𠮷').success // ✅ true — '𠮷'.length === 2
|
|
26
|
+
|
|
27
|
+
// '𠮷𠮷' is 2 characters, but 4 code units
|
|
28
|
+
v.safeParse(v.pipe(v.string(), v.maxLength(3)), '𠮷𠮷').success // ❌ false — despite being only 2 chars
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
This is particularly problematic when enforcing limits that should match database column widths (e.g. MySQL's `VARCHAR(n)`, which counts characters, not bytes or code units).
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
bun add @mpen/valibot-extras
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## API
|
|
40
|
+
|
|
41
|
+
### `wellFormed(message?)`
|
|
42
|
+
|
|
43
|
+
A Valibot action that rejects strings containing lone/unpaired UTF-16 surrogates (uses [`String.prototype.isWellFormed()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/isWellFormed)):
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import * as v from 'valibot'
|
|
47
|
+
import * as vx from '@mpen/valibot-extras'
|
|
48
|
+
|
|
49
|
+
const schema = v.pipe(v.string(), vx.wellFormed())
|
|
50
|
+
|
|
51
|
+
v.safeParse(schema, 'hello 𠮷').success // ✅ true
|
|
52
|
+
v.safeParse(schema, '\ud800').success // ❌ false
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### `unicodeString(message?)`
|
|
56
|
+
|
|
57
|
+
Shorthand for `v.pipe(v.string(), wellFormed())` — a string schema that only accepts well-formed Unicode:
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import * as vx from '@mpen/valibot-extras'
|
|
61
|
+
|
|
62
|
+
const schema = vx.unicodeString()
|
|
63
|
+
|
|
64
|
+
v.safeParse(schema, 'abc').success // ✅ true
|
|
65
|
+
v.safeParse(schema, '\ud800').success // ❌ false
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### `minCharLength(requirement, message?)`
|
|
69
|
+
|
|
70
|
+
Like `v.minLength`, but counts Unicode code points (characters) instead of UTF-16 code units:
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
import * as v from 'valibot'
|
|
74
|
+
import * as vx from '@mpen/valibot-extras'
|
|
75
|
+
|
|
76
|
+
const schema = v.pipe(v.string(), vx.minCharLength(3))
|
|
77
|
+
|
|
78
|
+
v.safeParse(schema, '𠮷𠮷𠮷').success // ✅ true — 3 characters
|
|
79
|
+
v.safeParse(schema, '𠮷𠮷').success // ❌ false — only 2 characters
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### `maxCharLength(requirement, message?)`
|
|
83
|
+
|
|
84
|
+
Like `v.maxLength`, but counts Unicode code points instead of UTF-16 code units:
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
import * as v from 'valibot'
|
|
88
|
+
import * as vx from '@mpen/valibot-extras'
|
|
89
|
+
|
|
90
|
+
const schema = v.pipe(v.string(), vx.maxCharLength(3))
|
|
91
|
+
|
|
92
|
+
v.safeParse(schema, '𠮷𠮷𠮷').success // ✅ true — 3 characters
|
|
93
|
+
v.safeParse(schema, '𠮷𠮷𠮷𠮷').success // ❌ false — 4 characters
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### `charLength(requirement, message?)`
|
|
97
|
+
|
|
98
|
+
Like `v.length`, but counts Unicode code points instead of UTF-16 code units:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
import * as v from 'valibot'
|
|
102
|
+
import * as vx from '@mpen/valibot-extras'
|
|
103
|
+
|
|
104
|
+
const schema = v.pipe(v.string(), vx.charLength(3))
|
|
105
|
+
|
|
106
|
+
v.safeParse(schema, '𠮷𠮷𠮷').success // ✅ true — exactly 3 characters
|
|
107
|
+
v.safeParse(schema, '𠮷𠮷').success // ❌ false — only 2
|
|
108
|
+
v.safeParse(schema, '𠮷𠮷𠮷𠮷').success // ❌ false — 4
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### `toJsonSchema(schema, config?)`
|
|
112
|
+
|
|
113
|
+
Converts a Valibot schema to JSON Schema, with support for custom JSON Schema annotations attached via [`attachJsonSchema`](#attachjsonschematarget-jsonschema).
|
|
114
|
+
|
|
115
|
+
This wraps `@valibot/to-json-schema` and adds `overrideSchema`/`overrideAction` hooks that look for schemas attached via the `jsonSchemaSymbol`. Attached schemas are merged into the converted output, preserving properties from the base conversion.
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
import * as v from 'valibot'
|
|
119
|
+
import * as vx from '@mpen/valibot-extras'
|
|
120
|
+
|
|
121
|
+
const schema = v.pipe(v.string(), vx.minCharLength(5), vx.maxCharLength(10))
|
|
122
|
+
const jsonSchema = vx.toJsonSchema(schema)
|
|
123
|
+
// { type: 'string', minLength: 5, maxLength: 10, $schema: '...' }
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### `attachJsonSchema(target, jsonSchema)`
|
|
127
|
+
|
|
128
|
+
Attaches a custom JSON Schema fragment to any Valibot schema or action via a non-enumerable Symbol property. This is used internally by `wellFormed`, `minCharLength`, etc. to make them compatible with `toJsonSchema`, but you can use it to annotate your own custom actions:
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
import * as v from 'valibot'
|
|
132
|
+
import * as vx from '@mpen/valibot-extras'
|
|
133
|
+
|
|
134
|
+
const myAction = v.check((input: string) => input.startsWith('https://'), 'Must be HTTPS')
|
|
135
|
+
const annotated = vx.attachJsonSchema(myAction, { format: 'uri' })
|
|
136
|
+
|
|
137
|
+
const schema = v.pipe(v.string(), annotated)
|
|
138
|
+
const jsonSchema = vx.toJsonSchema(schema)
|
|
139
|
+
// { type: 'string', format: 'uri', $schema: '...' }
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### `jsonSchemaSymbol`
|
|
143
|
+
|
|
144
|
+
The Symbol used by [`attachJsonSchema`](#attachjsonschematarget-jsonschema) to store the JSON Schema on a Valibot schema or action. Exposed for advanced use cases (e.g. reading back attached schemas).
|
|
145
|
+
|
|
146
|
+
### JSON Schema Compatibility
|
|
147
|
+
|
|
148
|
+
All string validators in this package are compatible with `@valibot/to-json-schema` (and the included `toJsonSchema` wrapper). The `minCharLength` / `maxCharLength` / `charLength` actions produce the standard `minLength` / `maxLength` JSON Schema keywords.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import * as v from "valibot";
|
|
2
|
+
import { ConversionConfig, JsonSchema } from "@valibot/to-json-schema";
|
|
3
|
+
|
|
4
|
+
//#region src/strings.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Creates a Valibot action to validate that a string is well-formed Unicode.
|
|
7
|
+
*
|
|
8
|
+
* This checks that the string contains no lone/unpaired UTF-16 surrogate characters.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import * as v from 'valibot';
|
|
13
|
+
* import { wellFormed } from '@mpen/valibot-extras';
|
|
14
|
+
*
|
|
15
|
+
* const schema = v.pipe(v.string(), wellFormed());
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @param message - The error message.
|
|
19
|
+
* @returns The Valibot action.
|
|
20
|
+
*/
|
|
21
|
+
declare function wellFormed(message?: string): v.CheckAction<string, string>;
|
|
22
|
+
/**
|
|
23
|
+
* Creates a Valibot schema to validate a well-formed Unicode string.
|
|
24
|
+
*
|
|
25
|
+
* This combines `v.string()` with the [`wellFormed`]{@link wellFormed} validation action.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { unicodeString } from '@mpen/valibot-extras';
|
|
30
|
+
*
|
|
31
|
+
* const schema = unicodeString('Invalid string');
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @param message - The error message.
|
|
35
|
+
* @returns The Valibot schema.
|
|
36
|
+
*/
|
|
37
|
+
declare function unicodeString(message?: string): v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, string>]>;
|
|
38
|
+
/**
|
|
39
|
+
* Creates a Valibot action to validate the minimum character length of a string (counting Unicode code points).
|
|
40
|
+
*
|
|
41
|
+
* This validator counts UTF-16 surrogate pairs as a single character (matching MySQL's `VARCHAR` length behavior).
|
|
42
|
+
* See also [`maxCharLength`]{@link maxCharLength} and [`charLength`]{@link charLength}.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* import * as v from 'valibot';
|
|
47
|
+
* import { minCharLength } from '@mpen/valibot-extras';
|
|
48
|
+
*
|
|
49
|
+
* const schema = v.pipe(v.string(), minCharLength(5));
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @param requirement - The minimum character length requirement.
|
|
53
|
+
* @param message - The error message.
|
|
54
|
+
* @returns The Valibot action.
|
|
55
|
+
*/
|
|
56
|
+
declare function minCharLength<const TRequirement extends number>(requirement: TRequirement, message?: string): never;
|
|
57
|
+
/**
|
|
58
|
+
* Creates a Valibot action to validate the maximum character length of a string (counting Unicode code points).
|
|
59
|
+
*
|
|
60
|
+
* This validator counts UTF-16 surrogate pairs as a single character (matching MySQL's `VARCHAR` length behavior).
|
|
61
|
+
* See also [`minCharLength`]{@link minCharLength} and [`charLength`]{@link charLength}.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* import * as v from 'valibot';
|
|
66
|
+
* import { maxCharLength } from '@mpen/valibot-extras';
|
|
67
|
+
*
|
|
68
|
+
* const schema = v.pipe(v.string(), maxCharLength(10));
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* @param requirement - The maximum character length requirement.
|
|
72
|
+
* @param message - The error message.
|
|
73
|
+
* @returns The Valibot action.
|
|
74
|
+
*/
|
|
75
|
+
declare function maxCharLength<const TRequirement extends number>(requirement: TRequirement, message?: string): never;
|
|
76
|
+
/**
|
|
77
|
+
* Creates a Valibot action to validate the exact character length of a string (counting Unicode code points).
|
|
78
|
+
*
|
|
79
|
+
* This validator counts UTF-16 surrogate pairs as a single character.
|
|
80
|
+
* See also [`minCharLength`]{@link minCharLength} and [`maxCharLength`]{@link maxCharLength}.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* import * as v from 'valibot';
|
|
85
|
+
* import { charLength } from '@mpen/valibot-extras';
|
|
86
|
+
*
|
|
87
|
+
* const schema = v.pipe(v.string(), charLength(5));
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* @param requirement - The exact character length requirement.
|
|
91
|
+
* @param message - The error message.
|
|
92
|
+
* @returns The Valibot action.
|
|
93
|
+
*/
|
|
94
|
+
declare function charLength<const TRequirement extends number>(requirement: TRequirement, message?: string): never;
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/json-schema.d.ts
|
|
97
|
+
/**
|
|
98
|
+
* The symbol used to attach a custom JSON Schema to a Valibot schema or action.
|
|
99
|
+
*/
|
|
100
|
+
declare const jsonSchemaSymbol: unique symbol;
|
|
101
|
+
/**
|
|
102
|
+
* Attaches a custom JSON Schema to a Valibot schema or action using a Symbol.
|
|
103
|
+
*
|
|
104
|
+
* @param target - The target Valibot schema or action.
|
|
105
|
+
* @param jsonSchema - The JSON Schema to attach.
|
|
106
|
+
* @returns The target object with the attached JSON Schema.
|
|
107
|
+
*/
|
|
108
|
+
declare function attachJsonSchema<T extends object>(target: T, jsonSchema: JsonSchema): T;
|
|
109
|
+
/**
|
|
110
|
+
* Converts a Valibot schema to JSON Schema, with support for custom attached JSON Schemas.
|
|
111
|
+
*
|
|
112
|
+
* This wraps `@valibot/to-json-schema`'s `toJsonSchema` and implements `overrideSchema`
|
|
113
|
+
* and `overrideAction` to look for schemas attached via [`attachJsonSchema`]{@link attachJsonSchema}.
|
|
114
|
+
* Attached schemas are merged into the converted JSON Schema, preserving properties from
|
|
115
|
+
* the base conversion.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* import * as v from 'valibot';
|
|
120
|
+
* import { toJsonSchema, unicodeString } from '@mpen/valibot-extras';
|
|
121
|
+
*
|
|
122
|
+
* const schema = unicodeString();
|
|
123
|
+
* const jsonSchema = toJsonSchema(schema);
|
|
124
|
+
* ```
|
|
125
|
+
*
|
|
126
|
+
* @param schema - The Valibot schema to convert.
|
|
127
|
+
* @param config - Optional conversion configuration.
|
|
128
|
+
* @returns The generated JSON Schema.
|
|
129
|
+
*/
|
|
130
|
+
declare function toJsonSchema(schema: v.GenericSchema, config?: ConversionConfig): JsonSchema;
|
|
131
|
+
//#endregion
|
|
132
|
+
export { attachJsonSchema, charLength, jsonSchemaSymbol, maxCharLength, minCharLength, toJsonSchema, unicodeString, wellFormed };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import * as v from "valibot";
|
|
2
|
+
import { toJsonSchema as toJsonSchema$1 } from "@valibot/to-json-schema";
|
|
3
|
+
//#region src/json-schema.ts
|
|
4
|
+
/**
|
|
5
|
+
* The symbol used to attach a custom JSON Schema to a Valibot schema or action.
|
|
6
|
+
*/
|
|
7
|
+
const jsonSchemaSymbol = Symbol("jsonSchema");
|
|
8
|
+
/**
|
|
9
|
+
* Attaches a custom JSON Schema to a Valibot schema or action using a Symbol.
|
|
10
|
+
*
|
|
11
|
+
* @param target - The target Valibot schema or action.
|
|
12
|
+
* @param jsonSchema - The JSON Schema to attach.
|
|
13
|
+
* @returns The target object with the attached JSON Schema.
|
|
14
|
+
*/
|
|
15
|
+
function attachJsonSchema(target, jsonSchema) {
|
|
16
|
+
Object.defineProperty(target, jsonSchemaSymbol, {
|
|
17
|
+
value: jsonSchema,
|
|
18
|
+
configurable: true,
|
|
19
|
+
enumerable: false,
|
|
20
|
+
writable: true
|
|
21
|
+
});
|
|
22
|
+
return target;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Converts a Valibot schema to JSON Schema, with support for custom attached JSON Schemas.
|
|
26
|
+
*
|
|
27
|
+
* This wraps `@valibot/to-json-schema`'s `toJsonSchema` and implements `overrideSchema`
|
|
28
|
+
* and `overrideAction` to look for schemas attached via [`attachJsonSchema`]{@link attachJsonSchema}.
|
|
29
|
+
* Attached schemas are merged into the converted JSON Schema, preserving properties from
|
|
30
|
+
* the base conversion.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* import * as v from 'valibot';
|
|
35
|
+
* import { toJsonSchema, unicodeString } from '@mpen/valibot-extras';
|
|
36
|
+
*
|
|
37
|
+
* const schema = unicodeString();
|
|
38
|
+
* const jsonSchema = toJsonSchema(schema);
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* @param schema - The Valibot schema to convert.
|
|
42
|
+
* @param config - Optional conversion configuration.
|
|
43
|
+
* @returns The generated JSON Schema.
|
|
44
|
+
*/
|
|
45
|
+
function toJsonSchema(schema, config) {
|
|
46
|
+
return toJsonSchema$1(schema, {
|
|
47
|
+
...config,
|
|
48
|
+
overrideSchema(context) {
|
|
49
|
+
const schemaOverride = context.valibotSchema[jsonSchemaSymbol];
|
|
50
|
+
if (schemaOverride !== void 0) return {
|
|
51
|
+
...context.jsonSchema,
|
|
52
|
+
...schemaOverride
|
|
53
|
+
};
|
|
54
|
+
return config?.overrideSchema?.(context);
|
|
55
|
+
},
|
|
56
|
+
overrideAction(context) {
|
|
57
|
+
const actionOverride = context.valibotAction[jsonSchemaSymbol];
|
|
58
|
+
if (actionOverride !== void 0) return {
|
|
59
|
+
...context.jsonSchema,
|
|
60
|
+
...actionOverride
|
|
61
|
+
};
|
|
62
|
+
return config?.overrideAction?.(context);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/strings.ts
|
|
68
|
+
/**
|
|
69
|
+
* Creates a Valibot action to validate that a string is well-formed Unicode.
|
|
70
|
+
*
|
|
71
|
+
* This checks that the string contains no lone/unpaired UTF-16 surrogate characters.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* import * as v from 'valibot';
|
|
76
|
+
* import { wellFormed } from '@mpen/valibot-extras';
|
|
77
|
+
*
|
|
78
|
+
* const schema = v.pipe(v.string(), wellFormed());
|
|
79
|
+
* ```
|
|
80
|
+
*
|
|
81
|
+
* @param message - The error message.
|
|
82
|
+
* @returns The Valibot action.
|
|
83
|
+
*/
|
|
84
|
+
function wellFormed(message = "String is not well-formed Unicode") {
|
|
85
|
+
return attachJsonSchema(v.check((input) => input.isWellFormed(), message), {});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Creates a Valibot schema to validate a well-formed Unicode string.
|
|
89
|
+
*
|
|
90
|
+
* This combines `v.string()` with the [`wellFormed`]{@link wellFormed} validation action.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* import { unicodeString } from '@mpen/valibot-extras';
|
|
95
|
+
*
|
|
96
|
+
* const schema = unicodeString('Invalid string');
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* @param message - The error message.
|
|
100
|
+
* @returns The Valibot schema.
|
|
101
|
+
*/
|
|
102
|
+
function unicodeString(message) {
|
|
103
|
+
return attachJsonSchema(v.pipe(v.string(), wellFormed(message)), { type: "string" });
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Creates a Valibot action to validate the minimum character length of a string (counting Unicode code points).
|
|
107
|
+
*
|
|
108
|
+
* This validator counts UTF-16 surrogate pairs as a single character (matching MySQL's `VARCHAR` length behavior).
|
|
109
|
+
* See also [`maxCharLength`]{@link maxCharLength} and [`charLength`]{@link charLength}.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```ts
|
|
113
|
+
* import * as v from 'valibot';
|
|
114
|
+
* import { minCharLength } from '@mpen/valibot-extras';
|
|
115
|
+
*
|
|
116
|
+
* const schema = v.pipe(v.string(), minCharLength(5));
|
|
117
|
+
* ```
|
|
118
|
+
*
|
|
119
|
+
* @param requirement - The minimum character length requirement.
|
|
120
|
+
* @param message - The error message.
|
|
121
|
+
* @returns The Valibot action.
|
|
122
|
+
*/
|
|
123
|
+
function minCharLength(requirement, message) {
|
|
124
|
+
const action = v.rawCheck(({ dataset, addIssue }) => {
|
|
125
|
+
if (!dataset.typed || typeof dataset.value !== "string") return;
|
|
126
|
+
const length = [...dataset.value].length;
|
|
127
|
+
if (length < requirement) addIssue({
|
|
128
|
+
message,
|
|
129
|
+
expected: `>=${requirement}`,
|
|
130
|
+
received: `${length}`
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
return Object.assign(action, {
|
|
134
|
+
type: "min_length",
|
|
135
|
+
expects: `>=${requirement}`,
|
|
136
|
+
requirement,
|
|
137
|
+
message
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Creates a Valibot action to validate the maximum character length of a string (counting Unicode code points).
|
|
142
|
+
*
|
|
143
|
+
* This validator counts UTF-16 surrogate pairs as a single character (matching MySQL's `VARCHAR` length behavior).
|
|
144
|
+
* See also [`minCharLength`]{@link minCharLength} and [`charLength`]{@link charLength}.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* import * as v from 'valibot';
|
|
149
|
+
* import { maxCharLength } from '@mpen/valibot-extras';
|
|
150
|
+
*
|
|
151
|
+
* const schema = v.pipe(v.string(), maxCharLength(10));
|
|
152
|
+
* ```
|
|
153
|
+
*
|
|
154
|
+
* @param requirement - The maximum character length requirement.
|
|
155
|
+
* @param message - The error message.
|
|
156
|
+
* @returns The Valibot action.
|
|
157
|
+
*/
|
|
158
|
+
function maxCharLength(requirement, message) {
|
|
159
|
+
const action = v.rawCheck(({ dataset, addIssue }) => {
|
|
160
|
+
if (!dataset.typed || typeof dataset.value !== "string") return;
|
|
161
|
+
const length = [...dataset.value].length;
|
|
162
|
+
if (length > requirement) addIssue({
|
|
163
|
+
message,
|
|
164
|
+
expected: `<=${requirement}`,
|
|
165
|
+
received: `${length}`
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
return Object.assign(action, {
|
|
169
|
+
type: "max_length",
|
|
170
|
+
expects: `<=${requirement}`,
|
|
171
|
+
requirement,
|
|
172
|
+
message
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Creates a Valibot action to validate the exact character length of a string (counting Unicode code points).
|
|
177
|
+
*
|
|
178
|
+
* This validator counts UTF-16 surrogate pairs as a single character.
|
|
179
|
+
* See also [`minCharLength`]{@link minCharLength} and [`maxCharLength`]{@link maxCharLength}.
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* ```ts
|
|
183
|
+
* import * as v from 'valibot';
|
|
184
|
+
* import { charLength } from '@mpen/valibot-extras';
|
|
185
|
+
*
|
|
186
|
+
* const schema = v.pipe(v.string(), charLength(5));
|
|
187
|
+
* ```
|
|
188
|
+
*
|
|
189
|
+
* @param requirement - The exact character length requirement.
|
|
190
|
+
* @param message - The error message.
|
|
191
|
+
* @returns The Valibot action.
|
|
192
|
+
*/
|
|
193
|
+
function charLength(requirement, message) {
|
|
194
|
+
const action = v.rawCheck(({ dataset, addIssue }) => {
|
|
195
|
+
if (!dataset.typed || typeof dataset.value !== "string") return;
|
|
196
|
+
const length = [...dataset.value].length;
|
|
197
|
+
if (length !== requirement) addIssue({
|
|
198
|
+
message,
|
|
199
|
+
expected: `${requirement}`,
|
|
200
|
+
received: `${length}`
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
return Object.assign(action, {
|
|
204
|
+
type: "length",
|
|
205
|
+
expects: `${requirement}`,
|
|
206
|
+
requirement,
|
|
207
|
+
message
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
//#endregion
|
|
211
|
+
export { attachJsonSchema, charLength, jsonSchemaSymbol, maxCharLength, minCharLength, toJsonSchema, unicodeString, wellFormed };
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mpen/valibot-extras",
|
|
3
|
+
"description": "Extras/extensions for Valibot.",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist",
|
|
8
|
+
"README.md"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "bun run --bun tsdown",
|
|
12
|
+
"dev": "bun run --bun tsdown --watch",
|
|
13
|
+
"test": "bun test src"
|
|
14
|
+
},
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"valibot": "^1.4.1",
|
|
17
|
+
"@valibot/to-json-schema": "^1.7.0"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@types/node": "^18.11.18",
|
|
21
|
+
"bun-types": "^1.3.13",
|
|
22
|
+
"tsdown": "^0.21",
|
|
23
|
+
"typescript": "^6",
|
|
24
|
+
"valibot": "^1.4.1",
|
|
25
|
+
"@valibot/to-json-schema": "^1.7.0"
|
|
26
|
+
},
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/mnpenner/npm-packages.git",
|
|
30
|
+
"directory": "packages/valibot-extras"
|
|
31
|
+
},
|
|
32
|
+
"exports": {
|
|
33
|
+
".": "./dist/index.js",
|
|
34
|
+
"./package.json": "./package.json"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"types": "./dist/index.d.ts"
|
|
40
|
+
}
|