yedra 0.20.11 → 0.20.13
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/routing/rest.d.ts +2 -0
- package/dist/routing/rest.js +2 -0
- package/dist/routing/websocket.d.ts +1 -0
- package/dist/routing/websocket.js +1 -0
- package/dist/src/index.d.ts +9 -0
- package/dist/src/index.js +7 -0
- package/dist/src/lib.d.ts +10 -0
- package/dist/src/lib.js +16 -0
- package/dist/src/routing/app.d.ts +165 -0
- package/dist/src/routing/app.js +537 -0
- package/dist/src/routing/env.d.ts +4 -0
- package/dist/src/routing/env.js +13 -0
- package/dist/src/routing/errors.d.ts +50 -0
- package/dist/src/routing/errors.js +64 -0
- package/dist/src/routing/log.d.ts +22 -0
- package/dist/src/routing/log.js +30 -0
- package/dist/src/routing/path.d.ts +44 -0
- package/dist/src/routing/path.js +110 -0
- package/dist/src/routing/rest.d.ts +103 -0
- package/dist/src/routing/rest.js +181 -0
- package/dist/src/routing/websocket.d.ts +60 -0
- package/dist/src/routing/websocket.js +132 -0
- package/dist/src/schema-lib.d.ts +17 -0
- package/dist/src/schema-lib.js +20 -0
- package/dist/src/schema.d.ts +2 -0
- package/dist/src/schema.js +4 -0
- package/dist/src/util/counter.d.ts +7 -0
- package/dist/src/util/counter.js +24 -0
- package/dist/src/util/docs.d.ts +9 -0
- package/dist/src/util/docs.js +57 -0
- package/dist/src/util/security.d.ts +14 -0
- package/dist/src/util/security.js +6 -0
- package/dist/src/util/stream.d.ts +2 -0
- package/dist/src/util/stream.js +7 -0
- package/dist/src/validation/body.d.ts +46 -0
- package/dist/src/validation/body.js +15 -0
- package/dist/src/validation/boolean.d.ts +10 -0
- package/dist/src/validation/boolean.js +27 -0
- package/dist/src/validation/date.d.ts +11 -0
- package/dist/src/validation/date.js +29 -0
- package/dist/src/validation/doc.d.ts +10 -0
- package/dist/src/validation/doc.js +22 -0
- package/dist/src/validation/either.d.ts +15 -0
- package/dist/src/validation/either.js +38 -0
- package/dist/src/validation/enum.d.ts +19 -0
- package/dist/src/validation/enum.js +44 -0
- package/dist/src/validation/error.d.ts +21 -0
- package/dist/src/validation/error.js +32 -0
- package/dist/src/validation/integer.d.ts +23 -0
- package/dist/src/validation/integer.js +64 -0
- package/dist/src/validation/json.d.ts +12 -0
- package/dist/src/validation/json.js +33 -0
- package/dist/src/validation/lazy.d.ts +48 -0
- package/dist/src/validation/lazy.js +78 -0
- package/dist/src/validation/modifiable.d.ts +105 -0
- package/dist/src/validation/modifiable.js +223 -0
- package/dist/src/validation/none.d.ts +10 -0
- package/dist/src/validation/none.js +14 -0
- package/dist/src/validation/null.d.ts +10 -0
- package/dist/src/validation/null.js +21 -0
- package/dist/src/validation/number.d.ts +23 -0
- package/dist/src/validation/number.js +58 -0
- package/dist/src/validation/object.d.ts +38 -0
- package/dist/src/validation/object.js +87 -0
- package/dist/src/validation/raw.d.ts +13 -0
- package/dist/src/validation/raw.js +21 -0
- package/dist/src/validation/record.d.ts +16 -0
- package/dist/src/validation/record.js +51 -0
- package/dist/src/validation/schema.d.ts +35 -0
- package/dist/src/validation/schema.js +76 -0
- package/dist/src/validation/stream.d.ts +13 -0
- package/dist/src/validation/stream.js +26 -0
- package/dist/src/validation/string.d.ts +29 -0
- package/dist/src/validation/string.js +51 -0
- package/dist/src/validation/union.d.ts +16 -0
- package/dist/src/validation/union.js +36 -0
- package/dist/src/validation/unknown.d.ts +10 -0
- package/dist/src/validation/unknown.js +13 -0
- package/dist/src/validation/uuid.d.ts +11 -0
- package/dist/src/validation/uuid.js +23 -0
- package/package.json +3 -4
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Issue, ValidationError } from './error.js';
|
|
2
|
+
import { ModifiableSchema } from './modifiable.js';
|
|
3
|
+
import { Schema } from './schema.js';
|
|
4
|
+
export class ObjectSchema extends ModifiableSchema {
|
|
5
|
+
constructor(shape, lax) {
|
|
6
|
+
super();
|
|
7
|
+
this.shape = shape;
|
|
8
|
+
this.lax = lax;
|
|
9
|
+
}
|
|
10
|
+
parse(obj) {
|
|
11
|
+
if (typeof obj !== 'object') {
|
|
12
|
+
throw new ValidationError([
|
|
13
|
+
new Issue([], `Expected object but got ${typeof obj}`),
|
|
14
|
+
]);
|
|
15
|
+
}
|
|
16
|
+
if (obj == null) {
|
|
17
|
+
throw new ValidationError([
|
|
18
|
+
new Issue([], 'Expected object but got null'),
|
|
19
|
+
]);
|
|
20
|
+
}
|
|
21
|
+
const result = {};
|
|
22
|
+
const issues = [];
|
|
23
|
+
for (const prop in this.shape) {
|
|
24
|
+
const propSchema = this.shape[prop];
|
|
25
|
+
if (propSchema instanceof Schema) {
|
|
26
|
+
if (!(prop in obj || propSchema.isOptional())) {
|
|
27
|
+
issues.push(new Issue([prop], 'Required'));
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
result[prop] = propSchema.parse(obj[prop]);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
if (error instanceof ValidationError) {
|
|
35
|
+
issues.push(...error.withPrefix(prop));
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (!this.lax) {
|
|
44
|
+
for (const prop in obj) {
|
|
45
|
+
if (prop in this.shape) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
issues.push(new Issue([prop], 'Unrecognized'));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (issues.length > 0) {
|
|
52
|
+
throw new ValidationError(issues);
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
documentation() {
|
|
57
|
+
const properties = {};
|
|
58
|
+
const required = [];
|
|
59
|
+
for (const prop in this.shape) {
|
|
60
|
+
const propSchema = this.shape[prop];
|
|
61
|
+
if (propSchema instanceof Schema) {
|
|
62
|
+
if (!propSchema.isOptional()) {
|
|
63
|
+
required.push(prop);
|
|
64
|
+
}
|
|
65
|
+
properties[prop] = propSchema.documentation();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
type: 'object',
|
|
70
|
+
properties,
|
|
71
|
+
additionalProperties: this.lax,
|
|
72
|
+
...(required.length > 0 && { required }),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* A schema matching a JavaScript object of the specified shape. Fields which
|
|
78
|
+
* can be undefined are automatically marked as optional.
|
|
79
|
+
* @param shape - The object shape.
|
|
80
|
+
*
|
|
81
|
+
* ```typescript
|
|
82
|
+
* const schema = y.object({ num: y.number(), str: y.string().optional() });
|
|
83
|
+
* type SchemaType = y.Typeof<typeof schema>; // { num: number, str?: string }
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export const object = (shape) => new ObjectSchema(shape, false);
|
|
87
|
+
export const laxObject = (shape) => new ObjectSchema(shape, true);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Readable } from 'node:stream';
|
|
2
|
+
import { BodyType } from './body.js';
|
|
3
|
+
declare class RawBody extends BodyType<Buffer<ArrayBuffer>, Buffer<ArrayBufferLike>> {
|
|
4
|
+
private contentType;
|
|
5
|
+
constructor(contentType: string);
|
|
6
|
+
deserialize(stream: Readable, _contentType: string): Promise<Buffer<ArrayBuffer>>;
|
|
7
|
+
bodyDocs(): object;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Accepts a raw buffer of the specified content type.
|
|
11
|
+
*/
|
|
12
|
+
export declare const raw: (contentType?: string) => RawBody;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { readableToBuffer } from '../util/stream.js';
|
|
2
|
+
import { BodyType } from './body.js';
|
|
3
|
+
class RawBody extends BodyType {
|
|
4
|
+
constructor(contentType) {
|
|
5
|
+
super();
|
|
6
|
+
this.contentType = contentType;
|
|
7
|
+
}
|
|
8
|
+
async deserialize(stream, _contentType) {
|
|
9
|
+
const buffer = await readableToBuffer(stream);
|
|
10
|
+
return buffer;
|
|
11
|
+
}
|
|
12
|
+
bodyDocs() {
|
|
13
|
+
return {
|
|
14
|
+
[this.contentType]: {},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Accepts a raw buffer of the specified content type.
|
|
20
|
+
*/
|
|
21
|
+
export const raw = (contentType) => new RawBody(contentType ?? 'application/octet-stream');
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Typeof } from './body.js';
|
|
2
|
+
import { ModifiableSchema } from './modifiable.js';
|
|
3
|
+
import type { Schema } from './schema.js';
|
|
4
|
+
declare class RecordSchema<ValueSchema extends Schema<unknown>> extends ModifiableSchema<Record<string, Typeof<ValueSchema> | undefined>> {
|
|
5
|
+
private readonly valueSchema;
|
|
6
|
+
constructor(valueSchema: ValueSchema);
|
|
7
|
+
parse(obj: unknown): Record<string, Typeof<ValueSchema> | undefined>;
|
|
8
|
+
documentation(): object;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A schema matching a JavaScript object with arbitrary keys. Every value has
|
|
12
|
+
* to match the specified value schema.
|
|
13
|
+
* @param valueSchema - The schema for the record values.
|
|
14
|
+
*/
|
|
15
|
+
export declare const record: <ValueSchema extends Schema<unknown>>(valueSchema: ValueSchema) => RecordSchema<ValueSchema>;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Issue, ValidationError } from './error.js';
|
|
2
|
+
import { ModifiableSchema } from './modifiable.js';
|
|
3
|
+
class RecordSchema extends ModifiableSchema {
|
|
4
|
+
constructor(valueSchema) {
|
|
5
|
+
super();
|
|
6
|
+
this.valueSchema = valueSchema;
|
|
7
|
+
}
|
|
8
|
+
parse(obj) {
|
|
9
|
+
if (typeof obj !== 'object') {
|
|
10
|
+
throw new ValidationError([
|
|
11
|
+
new Issue([], `Expected object but got ${typeof obj}`),
|
|
12
|
+
]);
|
|
13
|
+
}
|
|
14
|
+
if (obj === null) {
|
|
15
|
+
throw new ValidationError([
|
|
16
|
+
new Issue([], 'Expected object but got null'),
|
|
17
|
+
]);
|
|
18
|
+
}
|
|
19
|
+
const result = {};
|
|
20
|
+
const issues = [];
|
|
21
|
+
for (const key in obj) {
|
|
22
|
+
try {
|
|
23
|
+
result[key] = this.valueSchema.parse(obj[key]);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (error instanceof ValidationError) {
|
|
27
|
+
issues.push(...error.withPrefix(key));
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (issues.length > 0) {
|
|
35
|
+
throw new ValidationError(issues);
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
documentation() {
|
|
40
|
+
return {
|
|
41
|
+
type: 'object',
|
|
42
|
+
additionalProperties: this.valueSchema.documentation(),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* A schema matching a JavaScript object with arbitrary keys. Every value has
|
|
48
|
+
* to match the specified value schema.
|
|
49
|
+
* @param valueSchema - The schema for the record values.
|
|
50
|
+
*/
|
|
51
|
+
export const record = (valueSchema) => new RecordSchema(valueSchema);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Readable } from 'node:stream';
|
|
2
|
+
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
3
|
+
import { BodyType } from './body.js';
|
|
4
|
+
/**
|
|
5
|
+
* The base class for all schemas.
|
|
6
|
+
*/
|
|
7
|
+
export declare abstract class Schema<T> extends BodyType<T, T> implements StandardSchemaV1<T, T> {
|
|
8
|
+
deserialize(stream: Readable, contentType: string): Promise<T>;
|
|
9
|
+
bodyDocs(): object;
|
|
10
|
+
/**
|
|
11
|
+
* Parse the object with this schema. This throws a
|
|
12
|
+
* `ValidationError` if the object is invalid.
|
|
13
|
+
* @param obj - The object to be parsed.
|
|
14
|
+
*/
|
|
15
|
+
abstract parse(obj: unknown): T;
|
|
16
|
+
/**
|
|
17
|
+
* Generate a JSON schema for this schema.
|
|
18
|
+
*/
|
|
19
|
+
abstract documentation(): object;
|
|
20
|
+
/**
|
|
21
|
+
* Whether the schema is allowed to be optional.
|
|
22
|
+
*/
|
|
23
|
+
isOptional(): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Standard Schema V1 compliance. This allows yedra schemas to be used
|
|
26
|
+
* directly with libraries that accept Standard Schema validators
|
|
27
|
+
* (e.g. TanStack Form, TanStack Router, tRPC).
|
|
28
|
+
*
|
|
29
|
+
* This is a non-breaking addition — it does not affect `parse()` or any
|
|
30
|
+
* existing behavior. All subclasses inherit this automatically.
|
|
31
|
+
*
|
|
32
|
+
* @see https://standardschema.dev/
|
|
33
|
+
*/
|
|
34
|
+
get '~standard'(): StandardSchemaV1.Props<T, T>;
|
|
35
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { BodyType } from './body.js';
|
|
2
|
+
import { Issue, ValidationError } from './error.js';
|
|
3
|
+
/**
|
|
4
|
+
* The base class for all schemas.
|
|
5
|
+
*/
|
|
6
|
+
export class Schema extends BodyType {
|
|
7
|
+
async deserialize(stream, contentType) {
|
|
8
|
+
// Lazy import to keep this module browser-safe for yedra/schema.
|
|
9
|
+
// deserialize() is only called server-side, so the Node-specific
|
|
10
|
+
// stream utility is never resolved when bundled for the frontend.
|
|
11
|
+
const { readableToBuffer } = await import('../util/stream.js');
|
|
12
|
+
const buffer = await readableToBuffer(stream);
|
|
13
|
+
if (buffer.length === 0) {
|
|
14
|
+
return this.parse({});
|
|
15
|
+
}
|
|
16
|
+
if (contentType !== 'application/json') {
|
|
17
|
+
throw new ValidationError([
|
|
18
|
+
new Issue([], `Expected content type \`application/json\`, but got \`${contentType}\``),
|
|
19
|
+
]);
|
|
20
|
+
}
|
|
21
|
+
const data = JSON.parse(Buffer.from(buffer).toString('utf8'));
|
|
22
|
+
return this.parse(data);
|
|
23
|
+
}
|
|
24
|
+
bodyDocs() {
|
|
25
|
+
return {
|
|
26
|
+
'application/json': {
|
|
27
|
+
schema: this.documentation(),
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Whether the schema is allowed to be optional.
|
|
33
|
+
*/
|
|
34
|
+
isOptional() {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Standard Schema V1 compliance. This allows yedra schemas to be used
|
|
39
|
+
* directly with libraries that accept Standard Schema validators
|
|
40
|
+
* (e.g. TanStack Form, TanStack Router, tRPC).
|
|
41
|
+
*
|
|
42
|
+
* This is a non-breaking addition — it does not affect `parse()` or any
|
|
43
|
+
* existing behavior. All subclasses inherit this automatically.
|
|
44
|
+
*
|
|
45
|
+
* @see https://standardschema.dev/
|
|
46
|
+
*/
|
|
47
|
+
get '~standard'() {
|
|
48
|
+
return {
|
|
49
|
+
version: 1,
|
|
50
|
+
vendor: 'yedra',
|
|
51
|
+
types: {},
|
|
52
|
+
// Wraps parse() to match Standard Schema's non-throwing convention:
|
|
53
|
+
// returns { value } on success, { issues } on failure.
|
|
54
|
+
validate: (value) => {
|
|
55
|
+
try {
|
|
56
|
+
return { value: this.parse(value) };
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (error instanceof ValidationError) {
|
|
60
|
+
return {
|
|
61
|
+
issues: error.issues.map((issue) => ({
|
|
62
|
+
message: issue.message,
|
|
63
|
+
// Convert array index strings ("0", "1") to numbers
|
|
64
|
+
path: issue.path.map((segment) => {
|
|
65
|
+
const num = Number(segment);
|
|
66
|
+
return Number.isInteger(num) && num >= 0 ? num : segment;
|
|
67
|
+
}),
|
|
68
|
+
})),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Readable } from 'node:stream';
|
|
2
|
+
import { BodyType } from './body.js';
|
|
3
|
+
declare class StreamBody extends BodyType<ReadableStream, ReadableStream> {
|
|
4
|
+
private readonly contentType;
|
|
5
|
+
constructor(contentType: string);
|
|
6
|
+
deserialize(stream: Readable, _contentType: string): Promise<ReadableStream>;
|
|
7
|
+
bodyDocs(): object;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Accepts a raw buffer of the specified content type, and presents it as a stream.
|
|
11
|
+
*/
|
|
12
|
+
export declare const stream: (contentType?: string) => StreamBody;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { BodyType } from './body.js';
|
|
2
|
+
class StreamBody extends BodyType {
|
|
3
|
+
constructor(contentType) {
|
|
4
|
+
super();
|
|
5
|
+
this.contentType = contentType;
|
|
6
|
+
}
|
|
7
|
+
deserialize(stream, _contentType) {
|
|
8
|
+
return Promise.resolve(new ReadableStream({
|
|
9
|
+
async start(controller) {
|
|
10
|
+
for await (const chunk of stream) {
|
|
11
|
+
controller.enqueue(chunk);
|
|
12
|
+
}
|
|
13
|
+
controller.close();
|
|
14
|
+
},
|
|
15
|
+
}));
|
|
16
|
+
}
|
|
17
|
+
bodyDocs() {
|
|
18
|
+
return {
|
|
19
|
+
[this.contentType]: {},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Accepts a raw buffer of the specified content type, and presents it as a stream.
|
|
25
|
+
*/
|
|
26
|
+
export const stream = (contentType) => new StreamBody(contentType ?? 'application/octet-stream');
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ModifiableSchema } from './modifiable.js';
|
|
2
|
+
declare class StringSchema extends ModifiableSchema<string> {
|
|
3
|
+
/**
|
|
4
|
+
* Set the minimum length the string is allowed to be.
|
|
5
|
+
* @param length - The minimum length.
|
|
6
|
+
*/
|
|
7
|
+
min(length: number): import("./modifiable.js").RefinedSchema<string>;
|
|
8
|
+
/**
|
|
9
|
+
* Set the maximum length the string is allowed to be.
|
|
10
|
+
* @param length - The maximum length.
|
|
11
|
+
*/
|
|
12
|
+
max(length: number): import("./modifiable.js").RefinedSchema<string>;
|
|
13
|
+
/**
|
|
14
|
+
* Require the string to be a valid email address.
|
|
15
|
+
*/
|
|
16
|
+
email(): import("./modifiable.js").RefinedSchema<string>;
|
|
17
|
+
/**
|
|
18
|
+
* Require the string to match the specified pattern.
|
|
19
|
+
* @param pattern - A regular expression.
|
|
20
|
+
*/
|
|
21
|
+
pattern(pattern: RegExp): import("./modifiable.js").RefinedSchema<string>;
|
|
22
|
+
parse(obj: unknown): string;
|
|
23
|
+
documentation(): object;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* A schema matching a string.
|
|
27
|
+
*/
|
|
28
|
+
export declare const string: () => StringSchema;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Issue, ValidationError } from './error.js';
|
|
2
|
+
import { ModifiableSchema } from './modifiable.js';
|
|
3
|
+
const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
4
|
+
class StringSchema extends ModifiableSchema {
|
|
5
|
+
/**
|
|
6
|
+
* Set the minimum length the string is allowed to be.
|
|
7
|
+
* @param length - The minimum length.
|
|
8
|
+
*/
|
|
9
|
+
min(length) {
|
|
10
|
+
return this.refine((s) => s.length >= length || `Must be at least ${length} characters`, { minLength: length });
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Set the maximum length the string is allowed to be.
|
|
14
|
+
* @param length - The maximum length.
|
|
15
|
+
*/
|
|
16
|
+
max(length) {
|
|
17
|
+
return this.refine((s) => s.length <= length || `Must be at most ${length} characters`, { maxLength: length });
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Require the string to be a valid email address.
|
|
21
|
+
*/
|
|
22
|
+
email() {
|
|
23
|
+
return this.refine((s) => EMAIL_REGEX.test(s) || 'Expected email address', {
|
|
24
|
+
format: 'email',
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Require the string to match the specified pattern.
|
|
29
|
+
* @param pattern - A regular expression.
|
|
30
|
+
*/
|
|
31
|
+
pattern(pattern) {
|
|
32
|
+
return this.refine((s) => pattern.test(s) || `Does not match pattern /${pattern.source}/`, { pattern: pattern.source });
|
|
33
|
+
}
|
|
34
|
+
parse(obj) {
|
|
35
|
+
if (typeof obj !== 'string') {
|
|
36
|
+
throw new ValidationError([
|
|
37
|
+
new Issue([], `Expected string but got ${typeof obj}`),
|
|
38
|
+
]);
|
|
39
|
+
}
|
|
40
|
+
return obj;
|
|
41
|
+
}
|
|
42
|
+
documentation() {
|
|
43
|
+
return {
|
|
44
|
+
type: 'string',
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A schema matching a string.
|
|
50
|
+
*/
|
|
51
|
+
export const string = () => new StringSchema();
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Typeof } from './body.js';
|
|
2
|
+
import { ModifiableSchema } from './modifiable.js';
|
|
3
|
+
import type { Schema } from './schema.js';
|
|
4
|
+
declare class UnionSchema<T extends [...Schema<unknown>[]]> extends ModifiableSchema<Typeof<T[number]>> {
|
|
5
|
+
private readonly options;
|
|
6
|
+
constructor(options: T);
|
|
7
|
+
parse(obj: unknown): Typeof<T[number]>;
|
|
8
|
+
documentation(): object;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A schema that matches one of multiple other schemas. Similar to `y.enum`,
|
|
12
|
+
* expect that this requires real schemas instead of just strings or numbers.
|
|
13
|
+
* @param options - The different possible schemas.
|
|
14
|
+
*/
|
|
15
|
+
export declare const union: <T extends [...Schema<unknown>[]]>(...options: T) => UnionSchema<T>;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ValidationError } from './error.js';
|
|
2
|
+
import { ModifiableSchema } from './modifiable.js';
|
|
3
|
+
class UnionSchema extends ModifiableSchema {
|
|
4
|
+
constructor(options) {
|
|
5
|
+
super();
|
|
6
|
+
this.options = options;
|
|
7
|
+
}
|
|
8
|
+
parse(obj) {
|
|
9
|
+
const issues = [];
|
|
10
|
+
for (const option of this.options) {
|
|
11
|
+
try {
|
|
12
|
+
return option.parse(obj);
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
if (error instanceof ValidationError) {
|
|
16
|
+
issues.push(...error.issues);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
throw new ValidationError(issues);
|
|
24
|
+
}
|
|
25
|
+
documentation() {
|
|
26
|
+
return {
|
|
27
|
+
anyOf: this.options.map((option) => option.documentation()),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A schema that matches one of multiple other schemas. Similar to `y.enum`,
|
|
33
|
+
* expect that this requires real schemas instead of just strings or numbers.
|
|
34
|
+
* @param options - The different possible schemas.
|
|
35
|
+
*/
|
|
36
|
+
export const union = (...options) => new UnionSchema(options);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ModifiableSchema } from './modifiable.js';
|
|
2
|
+
declare class UnknownSchema extends ModifiableSchema<unknown> {
|
|
3
|
+
parse(obj: unknown): unknown;
|
|
4
|
+
documentation(): object;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* A schema matching anything.
|
|
8
|
+
*/
|
|
9
|
+
export declare const unknown: () => UnknownSchema;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ModifiableSchema } from './modifiable.js';
|
|
2
|
+
class UnknownSchema extends ModifiableSchema {
|
|
3
|
+
parse(obj) {
|
|
4
|
+
return obj;
|
|
5
|
+
}
|
|
6
|
+
documentation() {
|
|
7
|
+
return {};
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A schema matching anything.
|
|
12
|
+
*/
|
|
13
|
+
export const unknown = () => new UnknownSchema();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ModifiableSchema } from './modifiable.js';
|
|
2
|
+
declare class UuidSchema extends ModifiableSchema<string> {
|
|
3
|
+
parse(obj: unknown): string;
|
|
4
|
+
documentation(): object;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* A schema matching a universally unique identifier UUID
|
|
8
|
+
* of version 4.
|
|
9
|
+
*/
|
|
10
|
+
export declare const uuid: () => UuidSchema;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { validate, version } from 'uuid';
|
|
2
|
+
import { Issue, ValidationError } from './error.js';
|
|
3
|
+
import { ModifiableSchema } from './modifiable.js';
|
|
4
|
+
class UuidSchema extends ModifiableSchema {
|
|
5
|
+
parse(obj) {
|
|
6
|
+
if (typeof obj !== 'string' || !validate(obj) || version(obj) !== 4) {
|
|
7
|
+
throw new ValidationError([
|
|
8
|
+
new Issue([], `Expected uuid but got ${typeof obj}`),
|
|
9
|
+
]);
|
|
10
|
+
}
|
|
11
|
+
return obj;
|
|
12
|
+
}
|
|
13
|
+
documentation() {
|
|
14
|
+
return {
|
|
15
|
+
type: 'string',
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A schema matching a universally unique identifier UUID
|
|
21
|
+
* of version 4.
|
|
22
|
+
*/
|
|
23
|
+
export const uuid = () => new UuidSchema();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yedra",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.13",
|
|
4
4
|
"repository": "github:0codekit/yedra",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -17,9 +17,8 @@
|
|
|
17
17
|
"@biomejs/biome": "^2.4.5",
|
|
18
18
|
"@types/bun": "^1.3.10",
|
|
19
19
|
"@types/node": "^25.3.3",
|
|
20
|
-
"@types/uuid": "^11.0.0",
|
|
21
20
|
"@types/ws": "^8.18.1",
|
|
22
|
-
"typescript": "^
|
|
21
|
+
"typescript": "^6.0.3"
|
|
23
22
|
},
|
|
24
23
|
"bugs": "https://github.com/0codekit/yedra/issues",
|
|
25
24
|
"contributors": [
|
|
@@ -47,7 +46,7 @@
|
|
|
47
46
|
"@opentelemetry/api": "^1.9.0",
|
|
48
47
|
"@standard-schema/spec": "^1.1.0",
|
|
49
48
|
"mime": "^4.1.0",
|
|
50
|
-
"uuid": "^
|
|
49
|
+
"uuid": "^14.0.0",
|
|
51
50
|
"ws": "^8.19.0"
|
|
52
51
|
}
|
|
53
52
|
}
|