@agentuity/schema 0.0.69
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/AGENTS.md +86 -0
- package/README.md +323 -0
- package/dist/base.d.ts +111 -0
- package/dist/base.d.ts.map +1 -0
- package/dist/base.js +93 -0
- package/dist/base.js.map +1 -0
- package/dist/coerce/boolean.d.ts +37 -0
- package/dist/coerce/boolean.d.ts.map +1 -0
- package/dist/coerce/boolean.js +49 -0
- package/dist/coerce/boolean.js.map +1 -0
- package/dist/coerce/date.d.ts +36 -0
- package/dist/coerce/date.d.ts.map +1 -0
- package/dist/coerce/date.js +60 -0
- package/dist/coerce/date.js.map +1 -0
- package/dist/coerce/number.d.ts +36 -0
- package/dist/coerce/number.d.ts.map +1 -0
- package/dist/coerce/number.js +59 -0
- package/dist/coerce/number.js.map +1 -0
- package/dist/coerce/string.d.ts +35 -0
- package/dist/coerce/string.d.ts.map +1 -0
- package/dist/coerce/string.js +47 -0
- package/dist/coerce/string.js.map +1 -0
- package/dist/complex/array.d.ts +56 -0
- package/dist/complex/array.d.ts.map +1 -0
- package/dist/complex/array.js +96 -0
- package/dist/complex/array.js.map +1 -0
- package/dist/complex/object.d.ts +76 -0
- package/dist/complex/object.d.ts.map +1 -0
- package/dist/complex/object.js +104 -0
- package/dist/complex/object.js.map +1 -0
- package/dist/complex/record.d.ts +53 -0
- package/dist/complex/record.d.ts.map +1 -0
- package/dist/complex/record.js +109 -0
- package/dist/complex/record.js.map +1 -0
- package/dist/index.d.ts +151 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +128 -0
- package/dist/index.js.map +1 -0
- package/dist/json-schema.d.ts +60 -0
- package/dist/json-schema.d.ts.map +1 -0
- package/dist/json-schema.js +280 -0
- package/dist/json-schema.js.map +1 -0
- package/dist/primitives/any.d.ts +44 -0
- package/dist/primitives/any.d.ts.map +1 -0
- package/dist/primitives/any.js +57 -0
- package/dist/primitives/any.js.map +1 -0
- package/dist/primitives/boolean.d.ts +39 -0
- package/dist/primitives/boolean.d.ts.map +1 -0
- package/dist/primitives/boolean.js +53 -0
- package/dist/primitives/boolean.js.map +1 -0
- package/dist/primitives/null.d.ts +26 -0
- package/dist/primitives/null.d.ts.map +1 -0
- package/dist/primitives/null.js +40 -0
- package/dist/primitives/null.js.map +1 -0
- package/dist/primitives/number.d.ts +87 -0
- package/dist/primitives/number.d.ts.map +1 -0
- package/dist/primitives/number.js +129 -0
- package/dist/primitives/number.js.map +1 -0
- package/dist/primitives/string.d.ts +64 -0
- package/dist/primitives/string.d.ts.map +1 -0
- package/dist/primitives/string.js +102 -0
- package/dist/primitives/string.js.map +1 -0
- package/dist/primitives/undefined.d.ts +26 -0
- package/dist/primitives/undefined.d.ts.map +1 -0
- package/dist/primitives/undefined.js +40 -0
- package/dist/primitives/undefined.js.map +1 -0
- package/dist/primitives/unknown.d.ts +47 -0
- package/dist/primitives/unknown.d.ts.map +1 -0
- package/dist/primitives/unknown.js +56 -0
- package/dist/primitives/unknown.js.map +1 -0
- package/dist/utils/literal.d.ts +47 -0
- package/dist/utils/literal.d.ts.map +1 -0
- package/dist/utils/literal.js +64 -0
- package/dist/utils/literal.js.map +1 -0
- package/dist/utils/nullable.d.ts +50 -0
- package/dist/utils/nullable.d.ts.map +1 -0
- package/dist/utils/nullable.js +69 -0
- package/dist/utils/nullable.js.map +1 -0
- package/dist/utils/optional.d.ts +50 -0
- package/dist/utils/optional.d.ts.map +1 -0
- package/dist/utils/optional.js +69 -0
- package/dist/utils/optional.js.map +1 -0
- package/dist/utils/union.d.ts +60 -0
- package/dist/utils/union.d.ts.map +1 -0
- package/dist/utils/union.js +87 -0
- package/dist/utils/union.js.map +1 -0
- package/package.json +39 -0
- package/src/__tests__/coerce.test.ts +88 -0
- package/src/__tests__/complex.test.ts +124 -0
- package/src/__tests__/errors.test.ts +129 -0
- package/src/__tests__/json-schema.test.ts +138 -0
- package/src/__tests__/primitives.test.ts +184 -0
- package/src/__tests__/type-inference.test.ts +68 -0
- package/src/__tests__/utils.test.ts +100 -0
- package/src/base.ts +185 -0
- package/src/coerce/boolean.ts +56 -0
- package/src/coerce/date.ts +68 -0
- package/src/coerce/number.ts +67 -0
- package/src/coerce/string.ts +54 -0
- package/src/complex/array.ts +108 -0
- package/src/complex/object.ts +141 -0
- package/src/complex/record.ts +129 -0
- package/src/index.ts +177 -0
- package/src/json-schema.ts +331 -0
- package/src/primitives/any.ts +64 -0
- package/src/primitives/boolean.ts +60 -0
- package/src/primitives/null.ts +47 -0
- package/src/primitives/number.ts +141 -0
- package/src/primitives/string.ts +113 -0
- package/src/primitives/undefined.ts +47 -0
- package/src/primitives/unknown.ts +63 -0
- package/src/utils/literal.ts +71 -0
- package/src/utils/nullable.ts +80 -0
- package/src/utils/optional.ts +80 -0
- package/src/utils/union.ts +103 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { Schema } from '../base';
|
|
2
|
+
import { createIssue, failure, success, createParseMethods } from '../base';
|
|
3
|
+
import { optional } from '../utils/optional';
|
|
4
|
+
import { nullable } from '../utils/nullable';
|
|
5
|
+
|
|
6
|
+
const parseMethods = createParseMethods<boolean>();
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Schema for validating boolean values.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const schema = s.boolean();
|
|
14
|
+
* const active = schema.parse(true); // true
|
|
15
|
+
* schema.parse('true'); // throws ValidationError
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export class BooleanSchema implements Schema<boolean, boolean> {
|
|
19
|
+
description?: string;
|
|
20
|
+
|
|
21
|
+
readonly '~standard' = {
|
|
22
|
+
version: 1 as const,
|
|
23
|
+
vendor: 'agentuity',
|
|
24
|
+
validate: (value: unknown) => {
|
|
25
|
+
if (typeof value !== 'boolean') {
|
|
26
|
+
return failure([createIssue(`Expected boolean, got ${typeof value}`)]);
|
|
27
|
+
}
|
|
28
|
+
return success(value);
|
|
29
|
+
},
|
|
30
|
+
types: undefined as unknown as { input: boolean; output: boolean },
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
describe(description: string): this {
|
|
34
|
+
this.description = description;
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
optional() {
|
|
39
|
+
return optional(this);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
nullable() {
|
|
43
|
+
return nullable(this);
|
|
44
|
+
}
|
|
45
|
+
parse = parseMethods.parse;
|
|
46
|
+
safeParse = parseMethods.safeParse;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Create a boolean schema.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* const activeSchema = s.boolean().describe('Account status');
|
|
55
|
+
* const active = activeSchema.parse(true);
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export function boolean(): BooleanSchema {
|
|
59
|
+
return new BooleanSchema();
|
|
60
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Schema } from '../base';
|
|
2
|
+
import { createIssue, failure, success, createParseMethods } from '../base';
|
|
3
|
+
import { optional } from '../utils/optional';
|
|
4
|
+
import { nullable } from '../utils/nullable';
|
|
5
|
+
|
|
6
|
+
const parseMethods = createParseMethods<null>();
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Schema for validating null values.
|
|
10
|
+
*/
|
|
11
|
+
export class NullSchema implements Schema<null, null> {
|
|
12
|
+
description?: string;
|
|
13
|
+
|
|
14
|
+
readonly '~standard' = {
|
|
15
|
+
version: 1 as const,
|
|
16
|
+
vendor: 'agentuity',
|
|
17
|
+
validate: (value: unknown) => {
|
|
18
|
+
if (value !== null) {
|
|
19
|
+
return failure([createIssue(`Expected null, got ${typeof value}`)]);
|
|
20
|
+
}
|
|
21
|
+
return success(value);
|
|
22
|
+
},
|
|
23
|
+
types: undefined as unknown as { input: null; output: null },
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
describe(description: string): this {
|
|
27
|
+
this.description = description;
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
optional() {
|
|
32
|
+
return optional(this);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
nullable() {
|
|
36
|
+
return nullable(this);
|
|
37
|
+
}
|
|
38
|
+
parse = parseMethods.parse;
|
|
39
|
+
safeParse = parseMethods.safeParse;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Create a null schema.
|
|
44
|
+
*/
|
|
45
|
+
export function null_(): NullSchema {
|
|
46
|
+
return new NullSchema();
|
|
47
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import type { Schema } from '../base';
|
|
2
|
+
import { createIssue, failure, success, createParseMethods } from '../base';
|
|
3
|
+
import { optional } from '../utils/optional';
|
|
4
|
+
import { nullable } from '../utils/nullable';
|
|
5
|
+
|
|
6
|
+
const parseMethods = createParseMethods<number>();
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Schema for validating number values.
|
|
10
|
+
* Rejects NaN values.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const schema = s.number();
|
|
15
|
+
* const age = schema.parse(30); // 30
|
|
16
|
+
* schema.parse('30'); // throws ValidationError
|
|
17
|
+
* schema.parse(NaN); // throws ValidationError
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export class NumberSchema implements Schema<number, number> {
|
|
21
|
+
description?: string;
|
|
22
|
+
private _finite = false;
|
|
23
|
+
private _min?: number;
|
|
24
|
+
private _max?: number;
|
|
25
|
+
|
|
26
|
+
readonly '~standard' = {
|
|
27
|
+
version: 1 as const,
|
|
28
|
+
vendor: 'agentuity',
|
|
29
|
+
validate: (value: unknown) => {
|
|
30
|
+
if (typeof value !== 'number' || Number.isNaN(value)) {
|
|
31
|
+
return failure([createIssue(`Expected number, got ${typeof value}`)]);
|
|
32
|
+
}
|
|
33
|
+
if (this._finite && !Number.isFinite(value)) {
|
|
34
|
+
return failure([createIssue('Expected finite number (not Infinity or -Infinity)')]);
|
|
35
|
+
}
|
|
36
|
+
if (this._min !== undefined && value < this._min) {
|
|
37
|
+
return failure([createIssue(`Expected number >= ${this._min}, got ${value}`)]);
|
|
38
|
+
}
|
|
39
|
+
if (this._max !== undefined && value > this._max) {
|
|
40
|
+
return failure([createIssue(`Expected number <= ${this._max}, got ${value}`)]);
|
|
41
|
+
}
|
|
42
|
+
return success(value);
|
|
43
|
+
},
|
|
44
|
+
types: undefined as unknown as { input: number; output: number },
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
describe(description: string): this {
|
|
48
|
+
this.description = description;
|
|
49
|
+
return this;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Require the number to be finite (not Infinity, -Infinity, or NaN).
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const schema = s.number().finite();
|
|
58
|
+
* schema.parse(123); // 123
|
|
59
|
+
* schema.parse(Infinity); // throws ValidationError
|
|
60
|
+
* schema.parse(-Infinity); // throws ValidationError
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
finite(): NumberSchema {
|
|
64
|
+
const clone = this._clone();
|
|
65
|
+
clone._finite = true;
|
|
66
|
+
return clone;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Set minimum value (inclusive).
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* const schema = s.number().min(0);
|
|
75
|
+
* schema.parse(5); // 5
|
|
76
|
+
* schema.parse(-1); // throws ValidationError
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
min(value: number): NumberSchema {
|
|
80
|
+
const clone = this._clone();
|
|
81
|
+
clone._min = value;
|
|
82
|
+
return clone;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Set maximum value (inclusive).
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* const schema = s.number().max(100);
|
|
91
|
+
* schema.parse(50); // 50
|
|
92
|
+
* schema.parse(101); // throws ValidationError
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
max(value: number): NumberSchema {
|
|
96
|
+
const clone = this._clone();
|
|
97
|
+
clone._max = value;
|
|
98
|
+
return clone;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
optional() {
|
|
102
|
+
return optional(this);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
nullable() {
|
|
106
|
+
return nullable(this);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private _clone(): NumberSchema {
|
|
110
|
+
const clone = new NumberSchema();
|
|
111
|
+
clone.description = this.description;
|
|
112
|
+
clone._finite = this._finite;
|
|
113
|
+
clone._min = this._min;
|
|
114
|
+
clone._max = this._max;
|
|
115
|
+
return clone;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
parse = parseMethods.parse;
|
|
119
|
+
safeParse = parseMethods.safeParse;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Create a number schema.
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```typescript
|
|
127
|
+
* const ageSchema = s.number().describe('User age');
|
|
128
|
+
* const age = ageSchema.parse(30);
|
|
129
|
+
*
|
|
130
|
+
* const finiteSchema = s.number().finite();
|
|
131
|
+
* finiteSchema.parse(123); // OK
|
|
132
|
+
* finiteSchema.parse(Infinity); // throws
|
|
133
|
+
*
|
|
134
|
+
* const rangeSchema = s.number().min(0).max(100);
|
|
135
|
+
* rangeSchema.parse(50); // OK
|
|
136
|
+
* rangeSchema.parse(101); // throws
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
export function number(): NumberSchema {
|
|
140
|
+
return new NumberSchema();
|
|
141
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { Schema } from '../base';
|
|
2
|
+
import { createIssue, failure, success, createParseMethods } from '../base';
|
|
3
|
+
import { optional } from '../utils/optional';
|
|
4
|
+
import { nullable } from '../utils/nullable';
|
|
5
|
+
|
|
6
|
+
const parseMethods = createParseMethods<string>();
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Schema for validating string values.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const schema = s.string();
|
|
14
|
+
* const name = schema.parse('John'); // "John"
|
|
15
|
+
* schema.parse(123); // throws ValidationError
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export class StringSchema implements Schema<string, string> {
|
|
19
|
+
description?: string;
|
|
20
|
+
private _min?: number;
|
|
21
|
+
private _max?: number;
|
|
22
|
+
|
|
23
|
+
readonly '~standard' = {
|
|
24
|
+
version: 1 as const,
|
|
25
|
+
vendor: 'agentuity',
|
|
26
|
+
validate: (value: unknown) => {
|
|
27
|
+
if (typeof value !== 'string') {
|
|
28
|
+
return failure([createIssue(`Expected string, got ${typeof value}`)]);
|
|
29
|
+
}
|
|
30
|
+
if (this._min !== undefined && value.length < this._min) {
|
|
31
|
+
return failure([
|
|
32
|
+
createIssue(`String must be at least ${this._min} characters, got ${value.length}`),
|
|
33
|
+
]);
|
|
34
|
+
}
|
|
35
|
+
if (this._max !== undefined && value.length > this._max) {
|
|
36
|
+
return failure([
|
|
37
|
+
createIssue(`String must be at most ${this._max} characters, got ${value.length}`),
|
|
38
|
+
]);
|
|
39
|
+
}
|
|
40
|
+
return success(value);
|
|
41
|
+
},
|
|
42
|
+
types: undefined as unknown as { input: string; output: string },
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
describe(description: string): this {
|
|
46
|
+
this.description = description;
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Set minimum length.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const schema = s.string().min(3);
|
|
56
|
+
* schema.parse('hello'); // "hello"
|
|
57
|
+
* schema.parse('hi'); // throws ValidationError
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
min(length: number): StringSchema {
|
|
61
|
+
const clone = this._clone();
|
|
62
|
+
clone._min = length;
|
|
63
|
+
return clone;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Set maximum length.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* const schema = s.string().max(10);
|
|
72
|
+
* schema.parse('hello'); // "hello"
|
|
73
|
+
* schema.parse('hello world'); // throws ValidationError
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
max(length: number): StringSchema {
|
|
77
|
+
const clone = this._clone();
|
|
78
|
+
clone._max = length;
|
|
79
|
+
return clone;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
optional() {
|
|
83
|
+
return optional(this);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
nullable() {
|
|
87
|
+
return nullable(this);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private _clone(): StringSchema {
|
|
91
|
+
const clone = new StringSchema();
|
|
92
|
+
clone.description = this.description;
|
|
93
|
+
clone._min = this._min;
|
|
94
|
+
clone._max = this._max;
|
|
95
|
+
return clone;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
parse = parseMethods.parse;
|
|
99
|
+
safeParse = parseMethods.safeParse;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Create a string schema.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```typescript
|
|
107
|
+
* const nameSchema = s.string().describe('User name');
|
|
108
|
+
* const name = nameSchema.parse('John');
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export function string(): StringSchema {
|
|
112
|
+
return new StringSchema();
|
|
113
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Schema } from '../base';
|
|
2
|
+
import { createIssue, failure, success, createParseMethods } from '../base';
|
|
3
|
+
import { optional } from '../utils/optional';
|
|
4
|
+
import { nullable } from '../utils/nullable';
|
|
5
|
+
|
|
6
|
+
const parseMethods = createParseMethods<undefined>();
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Schema for validating undefined values.
|
|
10
|
+
*/
|
|
11
|
+
export class UndefinedSchema implements Schema<undefined, undefined> {
|
|
12
|
+
description?: string;
|
|
13
|
+
|
|
14
|
+
readonly '~standard' = {
|
|
15
|
+
version: 1 as const,
|
|
16
|
+
vendor: 'agentuity',
|
|
17
|
+
validate: (value: unknown) => {
|
|
18
|
+
if (value !== undefined) {
|
|
19
|
+
return failure([createIssue(`Expected undefined, got ${typeof value}`)]);
|
|
20
|
+
}
|
|
21
|
+
return success(value);
|
|
22
|
+
},
|
|
23
|
+
types: undefined as unknown as { input: undefined; output: undefined },
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
describe(description: string): this {
|
|
27
|
+
this.description = description;
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
optional() {
|
|
32
|
+
return optional(this);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
nullable() {
|
|
36
|
+
return nullable(this);
|
|
37
|
+
}
|
|
38
|
+
parse = parseMethods.parse;
|
|
39
|
+
safeParse = parseMethods.safeParse;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Create an undefined schema.
|
|
44
|
+
*/
|
|
45
|
+
export function undefined_(): UndefinedSchema {
|
|
46
|
+
return new UndefinedSchema();
|
|
47
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Schema } from '../base';
|
|
2
|
+
import { success, createParseMethods } from '../base';
|
|
3
|
+
import { optional } from '../utils/optional';
|
|
4
|
+
import { nullable } from '../utils/nullable';
|
|
5
|
+
|
|
6
|
+
const parseMethods = createParseMethods<unknown>();
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Schema that accepts any value with type-safe unknown.
|
|
10
|
+
* Returns the value as-is without validation.
|
|
11
|
+
* Use this when you want to accept any value but force type checking at usage site.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const schema = s.unknown();
|
|
16
|
+
* const value = schema.parse(123); // unknown
|
|
17
|
+
* const value2 = schema.parse('hello'); // unknown
|
|
18
|
+
* const value3 = schema.parse(null); // unknown
|
|
19
|
+
*
|
|
20
|
+
* // Forces type narrowing
|
|
21
|
+
* if (typeof value === 'string') {
|
|
22
|
+
* console.log(value.toUpperCase());
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export class UnknownSchema implements Schema<unknown, unknown> {
|
|
27
|
+
description?: string;
|
|
28
|
+
|
|
29
|
+
readonly '~standard' = {
|
|
30
|
+
version: 1 as const,
|
|
31
|
+
vendor: 'agentuity',
|
|
32
|
+
validate: (value: unknown) => success(value),
|
|
33
|
+
types: undefined as unknown as { input: unknown; output: unknown },
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
describe(description: string): this {
|
|
37
|
+
this.description = description;
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
optional() {
|
|
42
|
+
return optional(this);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
nullable() {
|
|
46
|
+
return nullable(this);
|
|
47
|
+
}
|
|
48
|
+
parse = parseMethods.parse;
|
|
49
|
+
safeParse = parseMethods.safeParse;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Create an unknown schema that accepts any value.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const schema = s.unknown();
|
|
58
|
+
* const value = schema.parse(anything); // Type is unknown
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export function unknown(): UnknownSchema {
|
|
62
|
+
return new UnknownSchema();
|
|
63
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Schema } from '../base';
|
|
2
|
+
import { createIssue, failure, success, createParseMethods } from '../base';
|
|
3
|
+
import { optional } from '../utils/optional';
|
|
4
|
+
import { nullable } from '../utils/nullable';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Schema for validating exact literal values.
|
|
8
|
+
*
|
|
9
|
+
* @template T - The exact value type
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const adminSchema = s.literal('admin');
|
|
14
|
+
* adminSchema.parse('admin'); // 'admin'
|
|
15
|
+
* adminSchema.parse('user'); // throws ValidationError
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export class LiteralSchema<T extends string | number | boolean> implements Schema<T, T> {
|
|
19
|
+
description?: string;
|
|
20
|
+
private parseMethods = createParseMethods<T>();
|
|
21
|
+
|
|
22
|
+
constructor(private value: T) {}
|
|
23
|
+
|
|
24
|
+
readonly '~standard' = {
|
|
25
|
+
version: 1 as const,
|
|
26
|
+
vendor: 'agentuity',
|
|
27
|
+
validate: (input: unknown) => {
|
|
28
|
+
if (input !== this.value) {
|
|
29
|
+
return failure([
|
|
30
|
+
createIssue(
|
|
31
|
+
`Expected literal value ${JSON.stringify(this.value)}, got ${JSON.stringify(input)}`
|
|
32
|
+
),
|
|
33
|
+
]);
|
|
34
|
+
}
|
|
35
|
+
return success(this.value);
|
|
36
|
+
},
|
|
37
|
+
types: undefined as unknown as { input: T; output: T },
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
describe(description: string): this {
|
|
41
|
+
this.description = description;
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
optional() {
|
|
46
|
+
return optional(this);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
nullable() {
|
|
50
|
+
return nullable(this);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
parse = this.parseMethods.parse;
|
|
54
|
+
safeParse = this.parseMethods.safeParse;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Create a schema for an exact literal value.
|
|
59
|
+
*
|
|
60
|
+
* @param value - The exact value to match
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* const adminRole = s.literal('admin');
|
|
65
|
+
* const maxValue = s.literal(100);
|
|
66
|
+
* const enabled = s.literal(true);
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export function literal<T extends string | number | boolean>(value: T): LiteralSchema<T> {
|
|
70
|
+
return new LiteralSchema(value);
|
|
71
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { Schema, Infer } from '../base';
|
|
2
|
+
import { success, createParseMethods } from '../base';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Schema for nullable values (T | null).
|
|
6
|
+
* Accepts null or the wrapped schema's type.
|
|
7
|
+
*
|
|
8
|
+
* @template T - The wrapped schema type
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const schema = s.nullable(s.string());
|
|
13
|
+
* schema.parse('hello'); // 'hello'
|
|
14
|
+
* schema.parse(null); // null
|
|
15
|
+
* schema.parse(123); // throws ValidationError
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
+
export class NullableSchema<T extends Schema<any, any>>
|
|
20
|
+
implements Schema<Infer<T> | null, Infer<T> | null>
|
|
21
|
+
{
|
|
22
|
+
readonly schema: T;
|
|
23
|
+
description?: string;
|
|
24
|
+
|
|
25
|
+
readonly '~standard' = {
|
|
26
|
+
version: 1 as const,
|
|
27
|
+
vendor: 'agentuity',
|
|
28
|
+
validate: (value: unknown) => {
|
|
29
|
+
if (value === null) {
|
|
30
|
+
return success(null as Infer<T> | null);
|
|
31
|
+
}
|
|
32
|
+
return this.schema['~standard'].validate(value);
|
|
33
|
+
},
|
|
34
|
+
types: undefined as unknown as { input: Infer<T> | null; output: Infer<T> | null },
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Type-safe parse methods for this instance
|
|
38
|
+
private parseMethods = createParseMethods<Infer<T> | null>();
|
|
39
|
+
|
|
40
|
+
constructor(schema: T) {
|
|
41
|
+
this.schema = schema;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
describe(description: string): this {
|
|
45
|
+
this.description = description;
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
optional(): Schema<Infer<T> | null | undefined, Infer<T> | null | undefined> {
|
|
50
|
+
// Import here to avoid circular dependency
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
52
|
+
const { optional } = require('./optional.js');
|
|
53
|
+
return optional(this);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
nullable() {
|
|
57
|
+
return this; // Already nullable
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
parse = this.parseMethods.parse;
|
|
61
|
+
safeParse = this.parseMethods.safeParse;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Make a schema nullable (T | null).
|
|
66
|
+
*
|
|
67
|
+
* @param schema - The schema to make nullable
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* const userSchema = s.object({
|
|
72
|
+
* name: s.string(),
|
|
73
|
+
* bio: s.nullable(s.string())
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
78
|
+
export function nullable<T extends Schema<any, any>>(schema: T): NullableSchema<T> {
|
|
79
|
+
return new NullableSchema(schema);
|
|
80
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { Schema, Infer } from '../base';
|
|
2
|
+
import { success, createParseMethods } from '../base';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Schema for optional values (T | undefined).
|
|
6
|
+
* Accepts undefined or the wrapped schema's type.
|
|
7
|
+
*
|
|
8
|
+
* @template T - The wrapped schema type
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const schema = s.optional(s.string());
|
|
13
|
+
* schema.parse('hello'); // 'hello'
|
|
14
|
+
* schema.parse(undefined); // undefined
|
|
15
|
+
* schema.parse(123); // throws ValidationError
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
+
export class OptionalSchema<T extends Schema<any, any>>
|
|
20
|
+
implements Schema<Infer<T> | undefined, Infer<T> | undefined>
|
|
21
|
+
{
|
|
22
|
+
readonly schema: T;
|
|
23
|
+
description?: string;
|
|
24
|
+
|
|
25
|
+
readonly '~standard' = {
|
|
26
|
+
version: 1 as const,
|
|
27
|
+
vendor: 'agentuity',
|
|
28
|
+
validate: (value: unknown) => {
|
|
29
|
+
if (value === undefined) {
|
|
30
|
+
return success(undefined as Infer<T> | undefined);
|
|
31
|
+
}
|
|
32
|
+
return this.schema['~standard'].validate(value);
|
|
33
|
+
},
|
|
34
|
+
types: undefined as unknown as { input: Infer<T> | undefined; output: Infer<T> | undefined },
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Type-safe parse methods for this instance
|
|
38
|
+
private parseMethods = createParseMethods<Infer<T> | undefined>();
|
|
39
|
+
|
|
40
|
+
constructor(schema: T) {
|
|
41
|
+
this.schema = schema;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
describe(description: string): this {
|
|
45
|
+
this.description = description;
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
optional() {
|
|
50
|
+
return this; // Already optional
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
nullable(): Schema<Infer<T> | undefined | null, Infer<T> | undefined | null> {
|
|
54
|
+
// Import here to avoid circular dependency
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
56
|
+
const { nullable } = require('./nullable.js');
|
|
57
|
+
return nullable(this);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
parse = this.parseMethods.parse;
|
|
61
|
+
safeParse = this.parseMethods.safeParse;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Make a schema optional (T | undefined).
|
|
66
|
+
*
|
|
67
|
+
* @param schema - The schema to make optional
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* const userSchema = s.object({
|
|
72
|
+
* name: s.string(),
|
|
73
|
+
* nickname: s.optional(s.string())
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
78
|
+
export function optional<T extends Schema<any, any>>(schema: T): OptionalSchema<T> {
|
|
79
|
+
return new OptionalSchema(schema);
|
|
80
|
+
}
|