yedra 0.20.6 → 0.20.7
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/app.js +18 -11
- package/dist/schema-lib.d.ts +1 -0
- package/dist/schema-lib.js +1 -0
- package/dist/validation/doc.d.ts +1 -1
- package/dist/validation/doc.js +1 -1
- package/dist/validation/integer.d.ts +1 -1
- package/dist/validation/integer.js +7 -7
- package/dist/validation/lazy.d.ts +48 -0
- package/dist/validation/lazy.js +78 -0
- package/dist/validation/modifiable.d.ts +3 -3
- package/dist/validation/modifiable.js +7 -7
- package/dist/validation/number.d.ts +1 -1
- package/dist/validation/number.js +5 -5
- package/dist/validation/object.d.ts +3 -3
- package/dist/validation/object.js +8 -8
- package/dist/validation/schema.d.ts +4 -4
- package/dist/validation/schema.js +8 -8
- package/dist/validation/string.d.ts +1 -1
- package/dist/validation/string.js +6 -6
- package/package.json +51 -51
package/dist/routing/app.js
CHANGED
|
@@ -8,6 +8,7 @@ import { context, propagation, SpanKind, trace } from '@opentelemetry/api';
|
|
|
8
8
|
import mime from 'mime';
|
|
9
9
|
import { WebSocketServer } from 'ws';
|
|
10
10
|
import { Counter } from '../util/counter.js';
|
|
11
|
+
import { collectLazySchemas } from '../validation/lazy.js';
|
|
11
12
|
import { HttpError } from './errors.js';
|
|
12
13
|
import { Path } from './path.js';
|
|
13
14
|
import { RestEndpoint } from './rest.js';
|
|
@@ -380,18 +381,23 @@ export class Yedra {
|
|
|
380
381
|
generateDocs(options) {
|
|
381
382
|
// this set will be filled with the security schemes from all endpoints
|
|
382
383
|
const securitySchemes = new Set();
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
384
|
+
// Wrap path generation in collectLazySchemas so that any LazySchema
|
|
385
|
+
// whose documentation() is called will register its full definition.
|
|
386
|
+
const { result: paths, schemas } = collectLazySchemas(() => {
|
|
387
|
+
const paths = {};
|
|
388
|
+
for (const route of this.restRoutes) {
|
|
389
|
+
if (route.endpoint.isHidden()) {
|
|
390
|
+
// do not include hidden endpoints in the documentation
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
const path = route.path.toString();
|
|
394
|
+
const methods = paths[path] ?? {};
|
|
395
|
+
methods[route.endpoint.method.toLowerCase()] =
|
|
396
|
+
route.endpoint.documentation(path, securitySchemes);
|
|
397
|
+
paths[path] = methods;
|
|
388
398
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
methods[route.endpoint.method.toLowerCase()] =
|
|
392
|
-
route.endpoint.documentation(path, securitySchemes);
|
|
393
|
-
paths[path] = methods;
|
|
394
|
-
}
|
|
399
|
+
return paths;
|
|
400
|
+
});
|
|
395
401
|
return {
|
|
396
402
|
openapi: '3.0.2',
|
|
397
403
|
info: {
|
|
@@ -404,6 +410,7 @@ export class Yedra {
|
|
|
404
410
|
securitySchemes: Object.fromEntries(securitySchemes
|
|
405
411
|
.values()
|
|
406
412
|
.map((scheme) => [scheme.name, scheme.scheme])),
|
|
413
|
+
schemas: Object.fromEntries(schemas),
|
|
407
414
|
},
|
|
408
415
|
servers: options?.servers ?? [],
|
|
409
416
|
paths,
|
package/dist/schema-lib.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export { date } from './validation/date.js';
|
|
|
4
4
|
export { _enum as enum } from './validation/enum.js';
|
|
5
5
|
export { ValidationError } from './validation/error.js';
|
|
6
6
|
export { integer } from './validation/integer.js';
|
|
7
|
+
export { lazy } from './validation/lazy.js';
|
|
7
8
|
export { array } from './validation/modifiable.js';
|
|
8
9
|
export { _null as null } from './validation/null.js';
|
|
9
10
|
export { number } from './validation/number.js';
|
package/dist/schema-lib.js
CHANGED
|
@@ -7,6 +7,7 @@ export { date } from './validation/date.js';
|
|
|
7
7
|
export { _enum as enum } from './validation/enum.js';
|
|
8
8
|
export { ValidationError } from './validation/error.js';
|
|
9
9
|
export { integer } from './validation/integer.js';
|
|
10
|
+
export { lazy } from './validation/lazy.js';
|
|
10
11
|
export { array } from './validation/modifiable.js';
|
|
11
12
|
export { _null as null } from './validation/null.js';
|
|
12
13
|
export { number } from './validation/number.js';
|
package/dist/validation/doc.d.ts
CHANGED
package/dist/validation/doc.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Issue, ValidationError } from
|
|
2
|
-
import { ModifiableSchema } from
|
|
1
|
+
import { Issue, ValidationError } from './error.js';
|
|
2
|
+
import { ModifiableSchema } from './modifiable.js';
|
|
3
3
|
class IntegerSchema extends ModifiableSchema {
|
|
4
4
|
constructor(min, max) {
|
|
5
5
|
super();
|
|
@@ -12,7 +12,7 @@ class IntegerSchema extends ModifiableSchema {
|
|
|
12
12
|
*/
|
|
13
13
|
min(value) {
|
|
14
14
|
if (!Number.isInteger(value)) {
|
|
15
|
-
throw new Error(
|
|
15
|
+
throw new Error('minimum value has to be an integer');
|
|
16
16
|
}
|
|
17
17
|
return new IntegerSchema(value, this.maxValue);
|
|
18
18
|
}
|
|
@@ -22,17 +22,17 @@ class IntegerSchema extends ModifiableSchema {
|
|
|
22
22
|
*/
|
|
23
23
|
max(value) {
|
|
24
24
|
if (!Number.isInteger(value)) {
|
|
25
|
-
throw new Error(
|
|
25
|
+
throw new Error('maximum value has to be an integer');
|
|
26
26
|
}
|
|
27
27
|
return new IntegerSchema(this.minValue, value);
|
|
28
28
|
}
|
|
29
29
|
parse(obj) {
|
|
30
|
-
if (typeof obj !==
|
|
30
|
+
if (typeof obj !== 'number' && typeof obj !== 'string') {
|
|
31
31
|
throw new ValidationError([
|
|
32
32
|
new Issue([], `Expected number but got ${typeof obj}`),
|
|
33
33
|
]);
|
|
34
34
|
}
|
|
35
|
-
const num = typeof obj ===
|
|
35
|
+
const num = typeof obj === 'number' ? obj : Number.parseFloat(obj);
|
|
36
36
|
if (Number.isNaN(num) || !Number.isInteger(num)) {
|
|
37
37
|
throw new ValidationError([
|
|
38
38
|
new Issue([], `Expected integer but got ${typeof obj}`),
|
|
@@ -52,7 +52,7 @@ class IntegerSchema extends ModifiableSchema {
|
|
|
52
52
|
}
|
|
53
53
|
documentation() {
|
|
54
54
|
return {
|
|
55
|
-
type:
|
|
55
|
+
type: 'integer',
|
|
56
56
|
...(this.minValue !== undefined && { minimum: this.minValue }),
|
|
57
57
|
...(this.maxValue !== undefined && { maximum: this.maxValue }),
|
|
58
58
|
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ModifiableSchema } from './modifiable.js';
|
|
2
|
+
import type { Schema } from './schema.js';
|
|
3
|
+
/**
|
|
4
|
+
* Run a function while collecting lazy schema definitions.
|
|
5
|
+
* Any `LazySchema` whose `documentation()` is called during `fn`
|
|
6
|
+
* will register its full definition in the returned map.
|
|
7
|
+
*/
|
|
8
|
+
export declare function collectLazySchemas<T>(fn: () => T): {
|
|
9
|
+
result: T;
|
|
10
|
+
schemas: Map<string, object>;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* A schema that defers evaluation to support recursive definitions.
|
|
14
|
+
* The getter function is called lazily on each parse/documentation
|
|
15
|
+
* invocation, breaking the circular reference at definition time.
|
|
16
|
+
*
|
|
17
|
+
* Usage:
|
|
18
|
+
* ```typescript
|
|
19
|
+
* interface Category {
|
|
20
|
+
* name: string;
|
|
21
|
+
* subcategories: Category[];
|
|
22
|
+
* }
|
|
23
|
+
*
|
|
24
|
+
* const category: LazySchema<Category> = y.lazy("Category", () =>
|
|
25
|
+
* y.object({
|
|
26
|
+
* name: y.string(),
|
|
27
|
+
* subcategories: category.array(),
|
|
28
|
+
* }),
|
|
29
|
+
* );
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare class LazySchema<T> extends ModifiableSchema<T> {
|
|
33
|
+
readonly schemaName: string;
|
|
34
|
+
private readonly getter;
|
|
35
|
+
constructor(name: string, getter: () => Schema<T>);
|
|
36
|
+
parse(obj: unknown): T;
|
|
37
|
+
documentation(): object;
|
|
38
|
+
private registerSchema;
|
|
39
|
+
isOptional(): boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create a lazily-evaluated schema for recursive type definitions.
|
|
43
|
+
* @param name - The schema name, used for `$ref` in OpenAPI documentation.
|
|
44
|
+
* @param getter - A function that returns the schema. Called at
|
|
45
|
+
* parse time, not at definition time, so circular references
|
|
46
|
+
* are safe.
|
|
47
|
+
*/
|
|
48
|
+
export declare const lazy: <T>(name: string, getter: () => Schema<T>) => LazySchema<T>;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { ModifiableSchema } from './modifiable.js';
|
|
2
|
+
/**
|
|
3
|
+
* Temporary context used during OpenAPI doc generation to accumulate
|
|
4
|
+
* lazy schema definitions. Set by `collectLazySchemas()`, read by
|
|
5
|
+
* `LazySchema.documentation()`. Not a persistent global registry —
|
|
6
|
+
* only lives for the duration of a single doc generation call.
|
|
7
|
+
*/
|
|
8
|
+
let schemaCollector = null;
|
|
9
|
+
/**
|
|
10
|
+
* Run a function while collecting lazy schema definitions.
|
|
11
|
+
* Any `LazySchema` whose `documentation()` is called during `fn`
|
|
12
|
+
* will register its full definition in the returned map.
|
|
13
|
+
*/
|
|
14
|
+
export function collectLazySchemas(fn) {
|
|
15
|
+
const schemas = new Map();
|
|
16
|
+
schemaCollector = schemas;
|
|
17
|
+
try {
|
|
18
|
+
const result = fn();
|
|
19
|
+
return { result, schemas };
|
|
20
|
+
}
|
|
21
|
+
finally {
|
|
22
|
+
schemaCollector = null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* A schema that defers evaluation to support recursive definitions.
|
|
27
|
+
* The getter function is called lazily on each parse/documentation
|
|
28
|
+
* invocation, breaking the circular reference at definition time.
|
|
29
|
+
*
|
|
30
|
+
* Usage:
|
|
31
|
+
* ```typescript
|
|
32
|
+
* interface Category {
|
|
33
|
+
* name: string;
|
|
34
|
+
* subcategories: Category[];
|
|
35
|
+
* }
|
|
36
|
+
*
|
|
37
|
+
* const category: LazySchema<Category> = y.lazy("Category", () =>
|
|
38
|
+
* y.object({
|
|
39
|
+
* name: y.string(),
|
|
40
|
+
* subcategories: category.array(),
|
|
41
|
+
* }),
|
|
42
|
+
* );
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export class LazySchema extends ModifiableSchema {
|
|
46
|
+
constructor(name, getter) {
|
|
47
|
+
super();
|
|
48
|
+
this.schemaName = name;
|
|
49
|
+
this.getter = getter;
|
|
50
|
+
}
|
|
51
|
+
parse(obj) {
|
|
52
|
+
return this.getter().parse(obj);
|
|
53
|
+
}
|
|
54
|
+
documentation() {
|
|
55
|
+
if (schemaCollector && !schemaCollector.has(this.schemaName)) {
|
|
56
|
+
this.registerSchema(schemaCollector);
|
|
57
|
+
}
|
|
58
|
+
return { $ref: `#/components/schemas/${this.schemaName}` };
|
|
59
|
+
}
|
|
60
|
+
registerSchema(collector) {
|
|
61
|
+
// Set a placeholder first to break infinite recursion —
|
|
62
|
+
// if the getter references this schema, documentation()
|
|
63
|
+
// will see the key already exists and skip re-registration.
|
|
64
|
+
collector.set(this.schemaName, {});
|
|
65
|
+
collector.set(this.schemaName, this.getter().documentation());
|
|
66
|
+
}
|
|
67
|
+
isOptional() {
|
|
68
|
+
return this.getter().isOptional();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Create a lazily-evaluated schema for recursive type definitions.
|
|
73
|
+
* @param name - The schema name, used for `$ref` in OpenAPI documentation.
|
|
74
|
+
* @param getter - A function that returns the schema. Called at
|
|
75
|
+
* parse time, not at definition time, so circular references
|
|
76
|
+
* are safe.
|
|
77
|
+
*/
|
|
78
|
+
export const lazy = (name, getter) => new LazySchema(name, getter);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Typeof } from
|
|
2
|
-
import { DocSchema } from
|
|
3
|
-
import { Schema } from
|
|
1
|
+
import type { Typeof } from './body.js';
|
|
2
|
+
import { DocSchema } from './doc.js';
|
|
3
|
+
import { Schema } from './schema.js';
|
|
4
4
|
export declare abstract class ModifiableSchema<T> extends Schema<T> {
|
|
5
5
|
/**
|
|
6
6
|
* Mark this schema as optional.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { DocSchema } from
|
|
2
|
-
import { Issue, ValidationError } from
|
|
3
|
-
import { Schema } from
|
|
1
|
+
import { DocSchema } from './doc.js';
|
|
2
|
+
import { Issue, ValidationError } from './error.js';
|
|
3
|
+
import { Schema } from './schema.js';
|
|
4
4
|
export class ModifiableSchema extends Schema {
|
|
5
5
|
/**
|
|
6
6
|
* Mark this schema as optional.
|
|
@@ -105,7 +105,7 @@ export class RefinedSchema extends ModifiableSchema {
|
|
|
105
105
|
*/
|
|
106
106
|
min(value) {
|
|
107
107
|
const docs = this.documentation();
|
|
108
|
-
const isArray = docs.type ===
|
|
108
|
+
const isArray = docs.type === 'array';
|
|
109
109
|
return this.refine(((v) => {
|
|
110
110
|
const len = v.length;
|
|
111
111
|
return (len >= value ||
|
|
@@ -120,7 +120,7 @@ export class RefinedSchema extends ModifiableSchema {
|
|
|
120
120
|
*/
|
|
121
121
|
max(value) {
|
|
122
122
|
const docs = this.documentation();
|
|
123
|
-
const isArray = docs.type ===
|
|
123
|
+
const isArray = docs.type === 'array';
|
|
124
124
|
return this.refine(((v) => {
|
|
125
125
|
const len = v.length;
|
|
126
126
|
return (len <= value ||
|
|
@@ -142,7 +142,7 @@ export class RefinedSchema extends ModifiableSchema {
|
|
|
142
142
|
if (result === true) {
|
|
143
143
|
return parsed;
|
|
144
144
|
}
|
|
145
|
-
const message = typeof result ===
|
|
145
|
+
const message = typeof result === 'string' ? result : 'Validation failed';
|
|
146
146
|
throw new ValidationError([new Issue([], message)]);
|
|
147
147
|
}
|
|
148
148
|
documentation() {
|
|
@@ -210,7 +210,7 @@ export class ArraySchema extends ModifiableSchema {
|
|
|
210
210
|
}
|
|
211
211
|
documentation() {
|
|
212
212
|
return {
|
|
213
|
-
type:
|
|
213
|
+
type: 'array',
|
|
214
214
|
items: this.itemSchema.documentation(),
|
|
215
215
|
};
|
|
216
216
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Issue, ValidationError } from
|
|
2
|
-
import { ModifiableSchema } from
|
|
1
|
+
import { Issue, ValidationError } from './error.js';
|
|
2
|
+
import { ModifiableSchema } from './modifiable.js';
|
|
3
3
|
class NumberSchema extends ModifiableSchema {
|
|
4
4
|
constructor(min, max) {
|
|
5
5
|
super();
|
|
@@ -21,12 +21,12 @@ class NumberSchema extends ModifiableSchema {
|
|
|
21
21
|
return new NumberSchema(this.minValue, value);
|
|
22
22
|
}
|
|
23
23
|
parse(obj) {
|
|
24
|
-
if (typeof obj !==
|
|
24
|
+
if (typeof obj !== 'number' && typeof obj !== 'string') {
|
|
25
25
|
throw new ValidationError([
|
|
26
26
|
new Issue([], `Expected number but got ${typeof obj}`),
|
|
27
27
|
]);
|
|
28
28
|
}
|
|
29
|
-
const num = typeof obj ===
|
|
29
|
+
const num = typeof obj === 'number' ? obj : Number.parseFloat(obj);
|
|
30
30
|
if (Number.isNaN(num)) {
|
|
31
31
|
throw new ValidationError([
|
|
32
32
|
new Issue([], `Expected number but got ${typeof obj}`),
|
|
@@ -46,7 +46,7 @@ class NumberSchema extends ModifiableSchema {
|
|
|
46
46
|
}
|
|
47
47
|
documentation() {
|
|
48
48
|
return {
|
|
49
|
-
type:
|
|
49
|
+
type: 'number',
|
|
50
50
|
...(this.minValue !== undefined && { minimum: this.minValue }),
|
|
51
51
|
...(this.maxValue !== undefined && { maximum: this.maxValue }),
|
|
52
52
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Typeof } from
|
|
2
|
-
import { ModifiableSchema } from
|
|
3
|
-
import { Schema } from
|
|
1
|
+
import type { Typeof } from './body.js';
|
|
2
|
+
import { ModifiableSchema } from './modifiable.js';
|
|
3
|
+
import { Schema } from './schema.js';
|
|
4
4
|
/**
|
|
5
5
|
* Make a union of all keys that are not extended by undefined
|
|
6
6
|
* (i.e. have undefined as a variant) of the specified type.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Issue, ValidationError } from
|
|
2
|
-
import { ModifiableSchema } from
|
|
3
|
-
import { Schema } from
|
|
1
|
+
import { Issue, ValidationError } from './error.js';
|
|
2
|
+
import { ModifiableSchema } from './modifiable.js';
|
|
3
|
+
import { Schema } from './schema.js';
|
|
4
4
|
export class ObjectSchema extends ModifiableSchema {
|
|
5
5
|
constructor(shape, lax) {
|
|
6
6
|
super();
|
|
@@ -8,14 +8,14 @@ export class ObjectSchema extends ModifiableSchema {
|
|
|
8
8
|
this.lax = lax;
|
|
9
9
|
}
|
|
10
10
|
parse(obj) {
|
|
11
|
-
if (typeof obj !==
|
|
11
|
+
if (typeof obj !== 'object') {
|
|
12
12
|
throw new ValidationError([
|
|
13
13
|
new Issue([], `Expected object but got ${typeof obj}`),
|
|
14
14
|
]);
|
|
15
15
|
}
|
|
16
16
|
if (obj == null) {
|
|
17
17
|
throw new ValidationError([
|
|
18
|
-
new Issue([],
|
|
18
|
+
new Issue([], 'Expected object but got null'),
|
|
19
19
|
]);
|
|
20
20
|
}
|
|
21
21
|
const result = {};
|
|
@@ -24,7 +24,7 @@ export class ObjectSchema extends ModifiableSchema {
|
|
|
24
24
|
const propSchema = this.shape[prop];
|
|
25
25
|
if (propSchema instanceof Schema) {
|
|
26
26
|
if (!(prop in obj || propSchema.isOptional())) {
|
|
27
|
-
issues.push(new Issue([prop],
|
|
27
|
+
issues.push(new Issue([prop], 'Required'));
|
|
28
28
|
continue;
|
|
29
29
|
}
|
|
30
30
|
try {
|
|
@@ -45,7 +45,7 @@ export class ObjectSchema extends ModifiableSchema {
|
|
|
45
45
|
if (prop in this.shape) {
|
|
46
46
|
continue;
|
|
47
47
|
}
|
|
48
|
-
issues.push(new Issue([prop],
|
|
48
|
+
issues.push(new Issue([prop], 'Unrecognized'));
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
if (issues.length > 0) {
|
|
@@ -66,7 +66,7 @@ export class ObjectSchema extends ModifiableSchema {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
return {
|
|
69
|
-
type:
|
|
69
|
+
type: 'object',
|
|
70
70
|
properties,
|
|
71
71
|
additionalProperties: this.lax,
|
|
72
72
|
...(required.length > 0 && { required }),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Readable } from
|
|
2
|
-
import type { StandardSchemaV1 } from
|
|
3
|
-
import { BodyType } from
|
|
1
|
+
import type { Readable } from 'node:stream';
|
|
2
|
+
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
3
|
+
import { BodyType } from './body.js';
|
|
4
4
|
/**
|
|
5
5
|
* The base class for all schemas.
|
|
6
6
|
*/
|
|
@@ -31,5 +31,5 @@ export declare abstract class Schema<T> extends BodyType<T, T> implements Standa
|
|
|
31
31
|
*
|
|
32
32
|
* @see https://standardschema.dev/
|
|
33
33
|
*/
|
|
34
|
-
get
|
|
34
|
+
get '~standard'(): StandardSchemaV1.Props<T, T>;
|
|
35
35
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { BodyType } from
|
|
2
|
-
import { Issue, ValidationError } from
|
|
1
|
+
import { BodyType } from './body.js';
|
|
2
|
+
import { Issue, ValidationError } from './error.js';
|
|
3
3
|
/**
|
|
4
4
|
* The base class for all schemas.
|
|
5
5
|
*/
|
|
@@ -8,22 +8,22 @@ export class Schema extends BodyType {
|
|
|
8
8
|
// Lazy import to keep this module browser-safe for yedra/schema.
|
|
9
9
|
// deserialize() is only called server-side, so the Node-specific
|
|
10
10
|
// stream utility is never resolved when bundled for the frontend.
|
|
11
|
-
const { readableToBuffer } = await import(
|
|
11
|
+
const { readableToBuffer } = await import('../util/stream.js');
|
|
12
12
|
const buffer = await readableToBuffer(stream);
|
|
13
13
|
if (buffer.length === 0) {
|
|
14
14
|
return this.parse({});
|
|
15
15
|
}
|
|
16
|
-
if (contentType !==
|
|
16
|
+
if (contentType !== 'application/json') {
|
|
17
17
|
throw new ValidationError([
|
|
18
18
|
new Issue([], `Expected content type \`application/json\`, but got \`${contentType}\``),
|
|
19
19
|
]);
|
|
20
20
|
}
|
|
21
|
-
const data = JSON.parse(Buffer.from(buffer).toString(
|
|
21
|
+
const data = JSON.parse(Buffer.from(buffer).toString('utf8'));
|
|
22
22
|
return this.parse(data);
|
|
23
23
|
}
|
|
24
24
|
bodyDocs() {
|
|
25
25
|
return {
|
|
26
|
-
|
|
26
|
+
'application/json': {
|
|
27
27
|
schema: this.documentation(),
|
|
28
28
|
},
|
|
29
29
|
};
|
|
@@ -44,10 +44,10 @@ export class Schema extends BodyType {
|
|
|
44
44
|
*
|
|
45
45
|
* @see https://standardschema.dev/
|
|
46
46
|
*/
|
|
47
|
-
get
|
|
47
|
+
get '~standard'() {
|
|
48
48
|
return {
|
|
49
49
|
version: 1,
|
|
50
|
-
vendor:
|
|
50
|
+
vendor: 'yedra',
|
|
51
51
|
types: {},
|
|
52
52
|
// Wraps parse() to match Standard Schema's non-throwing convention:
|
|
53
53
|
// returns { value } on success, { issues } on failure.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Issue, ValidationError } from
|
|
2
|
-
import { ModifiableSchema } from
|
|
1
|
+
import { Issue, ValidationError } from './error.js';
|
|
2
|
+
import { ModifiableSchema } from './modifiable.js';
|
|
3
3
|
const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
4
4
|
class StringSchema extends ModifiableSchema {
|
|
5
5
|
/**
|
|
@@ -20,8 +20,8 @@ class StringSchema extends ModifiableSchema {
|
|
|
20
20
|
* Require the string to be a valid email address.
|
|
21
21
|
*/
|
|
22
22
|
email() {
|
|
23
|
-
return this.refine((s) => EMAIL_REGEX.test(s) ||
|
|
24
|
-
format:
|
|
23
|
+
return this.refine((s) => EMAIL_REGEX.test(s) || 'Expected email address', {
|
|
24
|
+
format: 'email',
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
@@ -32,7 +32,7 @@ class StringSchema extends ModifiableSchema {
|
|
|
32
32
|
return this.refine((s) => pattern.test(s) || `Does not match pattern /${pattern.source}/`, { pattern: pattern.source });
|
|
33
33
|
}
|
|
34
34
|
parse(obj) {
|
|
35
|
-
if (typeof obj !==
|
|
35
|
+
if (typeof obj !== 'string') {
|
|
36
36
|
throw new ValidationError([
|
|
37
37
|
new Issue([], `Expected string but got ${typeof obj}`),
|
|
38
38
|
]);
|
|
@@ -41,7 +41,7 @@ class StringSchema extends ModifiableSchema {
|
|
|
41
41
|
}
|
|
42
42
|
documentation() {
|
|
43
43
|
return {
|
|
44
|
-
type:
|
|
44
|
+
type: 'string',
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
}
|
package/package.json
CHANGED
|
@@ -1,53 +1,53 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
2
|
+
"name": "yedra",
|
|
3
|
+
"version": "0.20.7",
|
|
4
|
+
"repository": "github:0codekit/yedra",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"default": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"./schema": {
|
|
12
|
+
"types": "./dist/schema.d.ts",
|
|
13
|
+
"default": "./dist/schema.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@biomejs/biome": "^2.4.5",
|
|
18
|
+
"@types/bun": "^1.3.10",
|
|
19
|
+
"@types/node": "^25.3.3",
|
|
20
|
+
"@types/uuid": "^11.0.0",
|
|
21
|
+
"@types/ws": "^8.18.1",
|
|
22
|
+
"typescript": "^5.9.3"
|
|
23
|
+
},
|
|
24
|
+
"bugs": "https://github.com/0codekit/yedra/issues",
|
|
25
|
+
"contributors": [
|
|
26
|
+
"Justus Zorn <jzorn@wemakefuture.com>"
|
|
27
|
+
],
|
|
28
|
+
"description": "A TypeScript web framework with OpenAPI generation.",
|
|
29
|
+
"keywords": [
|
|
30
|
+
"typescript",
|
|
31
|
+
"web",
|
|
32
|
+
"http",
|
|
33
|
+
"schema",
|
|
34
|
+
"validation",
|
|
35
|
+
"openapi"
|
|
36
|
+
],
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"files": [
|
|
39
|
+
"./dist/**"
|
|
40
|
+
],
|
|
41
|
+
"scripts": {
|
|
42
|
+
"check": "biome check src/*"
|
|
43
|
+
},
|
|
44
|
+
"types": "dist/index.d.ts",
|
|
45
|
+
"type": "module",
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@opentelemetry/api": "^1.9.0",
|
|
48
|
+
"@standard-schema/spec": "^1.1.0",
|
|
49
|
+
"mime": "^4.1.0",
|
|
50
|
+
"uuid": "^13.0.0",
|
|
51
|
+
"ws": "^8.19.0"
|
|
52
|
+
}
|
|
53
53
|
}
|