yedra 0.19.3 → 0.20.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/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lib.d.ts +1 -0
- package/dist/lib.js +1 -0
- package/dist/routing/app.js +1 -0
- package/dist/routing/rest.d.ts +6 -8
- package/dist/routing/rest.js +6 -5
- package/dist/validation/body.d.ts +1 -4
- package/dist/validation/either.d.ts +1 -4
- package/dist/validation/json.d.ts +12 -0
- package/dist/validation/json.js +33 -0
- package/dist/validation/none.d.ts +1 -4
- package/dist/validation/none.js +1 -1
- package/dist/validation/raw.d.ts +1 -4
- package/dist/validation/raw.js +1 -4
- package/dist/validation/schema.d.ts +1 -4
- package/dist/validation/schema.js +2 -2
- package/dist/validation/stream.d.ts +1 -4
- package/dist/validation/stream.js +8 -11
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export { y };
|
|
|
3
3
|
export type { ConnectMiddleware } from './routing/app.js';
|
|
4
4
|
export { Yedra } from './routing/app.js';
|
|
5
5
|
export { BadRequestError, ConflictError, ForbiddenError, HttpError, NotFoundError, PaymentRequiredError, UnauthorizedError, } from './routing/errors.js';
|
|
6
|
-
export { Delete, Get, Post, Put } from './routing/rest.js';
|
|
6
|
+
export { Delete, Get, Patch, Post, Put } from './routing/rest.js';
|
|
7
7
|
export type { YedraWebSocket } from './routing/websocket.js';
|
|
8
8
|
export { Ws } from './routing/websocket.js';
|
|
9
9
|
export { SecurityScheme } from './util/security.js';
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,6 @@ import * as y from './lib.js';
|
|
|
2
2
|
export { y };
|
|
3
3
|
export { Yedra } from './routing/app.js';
|
|
4
4
|
export { BadRequestError, ConflictError, ForbiddenError, HttpError, NotFoundError, PaymentRequiredError, UnauthorizedError, } from './routing/errors.js';
|
|
5
|
-
export { Delete, Get, Post, Put } from './routing/rest.js';
|
|
5
|
+
export { Delete, Get, Patch, Post, Put } from './routing/rest.js';
|
|
6
6
|
export { Ws } from './routing/websocket.js';
|
|
7
7
|
export { SecurityScheme } from './util/security.js';
|
package/dist/lib.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export { either } from './validation/either.js';
|
|
|
10
10
|
export { _enum as enum } from './validation/enum.js';
|
|
11
11
|
export { ValidationError } from './validation/error.js';
|
|
12
12
|
export { integer } from './validation/integer.js';
|
|
13
|
+
export { json } from './validation/json.js';
|
|
13
14
|
export { array } from './validation/modifiable.js';
|
|
14
15
|
export { _null as null } from './validation/null.js';
|
|
15
16
|
export { number } from './validation/number.js';
|
package/dist/lib.js
CHANGED
|
@@ -14,6 +14,7 @@ export { either } from './validation/either.js';
|
|
|
14
14
|
export { _enum as enum } from './validation/enum.js';
|
|
15
15
|
export { ValidationError } from './validation/error.js';
|
|
16
16
|
export { integer } from './validation/integer.js';
|
|
17
|
+
export { json } from './validation/json.js';
|
|
17
18
|
// validation
|
|
18
19
|
export { array } from './validation/modifiable.js';
|
|
19
20
|
export { _null as null } from './validation/null.js';
|
package/dist/routing/app.js
CHANGED
package/dist/routing/rest.d.ts
CHANGED
|
@@ -10,11 +10,6 @@ type ReqObject<Params, Query, Headers, Body> = {
|
|
|
10
10
|
query: Query;
|
|
11
11
|
headers: Headers;
|
|
12
12
|
body: Body;
|
|
13
|
-
/**
|
|
14
|
-
* The raw request data. If the request body is
|
|
15
|
-
* streamed, this will be an empty buffer.
|
|
16
|
-
*/
|
|
17
|
-
raw: Buffer<ArrayBuffer>;
|
|
18
13
|
};
|
|
19
14
|
type ResObject<Body> = Promise<{
|
|
20
15
|
status?: number;
|
|
@@ -46,7 +41,7 @@ type EndpointOptions<Params extends Record<string, Schema<unknown>>, Query exten
|
|
|
46
41
|
do: (req: ReqObject<Typeof<ObjectSchema<Params>>, Typeof<ObjectSchema<Query>>, Typeof<ObjectSchema<Headers>>, Typeof<Req>>) => ResObject<TypeofAccepts<Res>>;
|
|
47
42
|
};
|
|
48
43
|
export declare abstract class RestEndpoint {
|
|
49
|
-
abstract get method(): 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
44
|
+
abstract get method(): 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
50
45
|
abstract handle(req: {
|
|
51
46
|
url: string;
|
|
52
47
|
body: Readable;
|
|
@@ -72,8 +67,8 @@ declare class ConcreteRestEndpoint<Params extends Record<string, Schema<unknown>
|
|
|
72
67
|
private paramsSchema;
|
|
73
68
|
private querySchema;
|
|
74
69
|
private headersSchema;
|
|
75
|
-
constructor(method: 'GET' | 'POST' | 'PUT' | 'DELETE', options: EndpointOptions<Params, Query, Headers, Req, Res>);
|
|
76
|
-
get method(): 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
70
|
+
constructor(method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE', options: EndpointOptions<Params, Query, Headers, Req, Res>);
|
|
71
|
+
get method(): 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
77
72
|
handle(req: {
|
|
78
73
|
url: string;
|
|
79
74
|
body: Readable;
|
|
@@ -97,6 +92,9 @@ export declare class Post<Params extends Record<string, Schema<unknown>>, Query
|
|
|
97
92
|
export declare class Put<Params extends Record<string, Schema<unknown>>, Query extends Record<string, Schema<unknown>>, Headers extends Record<string, Schema<unknown>>, Req extends BodyType<unknown, unknown>, Res extends BodyType<unknown, unknown>> extends ConcreteRestEndpoint<Params, Query, Headers, Req, Res> {
|
|
98
93
|
constructor(options: EndpointOptions<Params, Query, Headers, Req, Res>);
|
|
99
94
|
}
|
|
95
|
+
export declare class Patch<Params extends Record<string, Schema<unknown>>, Query extends Record<string, Schema<unknown>>, Headers extends Record<string, Schema<unknown>>, Req extends BodyType<unknown, unknown>, Res extends BodyType<unknown, unknown>> extends ConcreteRestEndpoint<Params, Query, Headers, Req, Res> {
|
|
96
|
+
constructor(options: EndpointOptions<Params, Query, Headers, Req, Res>);
|
|
97
|
+
}
|
|
100
98
|
export declare class Delete<Params extends Record<string, Schema<unknown>>, Query extends Record<string, Schema<unknown>>, Headers extends Record<string, Schema<unknown>>, Res extends BodyType<unknown, unknown>> extends ConcreteRestEndpoint<Params, Query, Headers, NoneBody, Res> {
|
|
101
99
|
constructor(options: Omit<EndpointOptions<Params, Query, Headers, NoneBody, Res>, 'req'>);
|
|
102
100
|
}
|
package/dist/routing/rest.js
CHANGED
|
@@ -26,15 +26,13 @@ class ConcreteRestEndpoint extends RestEndpoint {
|
|
|
26
26
|
}
|
|
27
27
|
async handle(req) {
|
|
28
28
|
let parsedBody;
|
|
29
|
-
let rawBody;
|
|
30
29
|
let parsedParams;
|
|
31
30
|
let parsedQuery;
|
|
32
31
|
let parsedHeaders;
|
|
33
32
|
const issues = [];
|
|
34
33
|
try {
|
|
35
34
|
const result = await this.options.req.deserialize(req.body, req.headers['content-type'] ?? 'application/octet-stream');
|
|
36
|
-
parsedBody = result
|
|
37
|
-
rawBody = result.raw;
|
|
35
|
+
parsedBody = result;
|
|
38
36
|
}
|
|
39
37
|
catch (error) {
|
|
40
38
|
if (error instanceof SyntaxError) {
|
|
@@ -94,8 +92,6 @@ class ConcreteRestEndpoint extends RestEndpoint {
|
|
|
94
92
|
headers: parsedHeaders,
|
|
95
93
|
// biome-ignore lint/style/noNonNullAssertion: this is required to convince TypeScript that this is initialized
|
|
96
94
|
body: parsedBody,
|
|
97
|
-
// biome-ignore lint/style/noNonNullAssertion: this is required to convince TypeScript that this is initialized
|
|
98
|
-
raw: rawBody,
|
|
99
95
|
});
|
|
100
96
|
}
|
|
101
97
|
isHidden() {
|
|
@@ -171,6 +167,11 @@ export class Put extends ConcreteRestEndpoint {
|
|
|
171
167
|
super('PUT', options);
|
|
172
168
|
}
|
|
173
169
|
}
|
|
170
|
+
export class Patch extends ConcreteRestEndpoint {
|
|
171
|
+
constructor(options) {
|
|
172
|
+
super('PATCH', options);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
174
175
|
export class Delete extends ConcreteRestEndpoint {
|
|
175
176
|
constructor(options) {
|
|
176
177
|
super('DELETE', { req: none(), ...options });
|
|
@@ -17,10 +17,7 @@ export declare abstract class BodyType<Provides, Accepts> {
|
|
|
17
17
|
* @param stream - The raw stream.
|
|
18
18
|
* @param contentType - The content type.
|
|
19
19
|
*/
|
|
20
|
-
abstract deserialize(stream: Readable, contentType: string): Promise<
|
|
21
|
-
parsed: Provides;
|
|
22
|
-
raw: Buffer<ArrayBuffer>;
|
|
23
|
-
}>;
|
|
20
|
+
abstract deserialize(stream: Readable, contentType: string): Promise<Provides>;
|
|
24
21
|
/**
|
|
25
22
|
* Generate OpenAPI docs for this body.
|
|
26
23
|
*/
|
|
@@ -3,10 +3,7 @@ import { BodyType, type Typeof, type TypeofAccepts, type TypeofProvides } from '
|
|
|
3
3
|
declare class EitherBody<T extends [...BodyType<unknown, unknown>[]]> extends BodyType<TypeofProvides<T[number]>, TypeofAccepts<T[number]>> {
|
|
4
4
|
private options;
|
|
5
5
|
constructor(options: T);
|
|
6
|
-
deserialize(stream: Readable, contentType: string): Promise<
|
|
7
|
-
parsed: Typeof<T[number]>;
|
|
8
|
-
raw: Buffer<ArrayBuffer>;
|
|
9
|
-
}>;
|
|
6
|
+
deserialize(stream: Readable, contentType: string): Promise<Typeof<T[number]>>;
|
|
10
7
|
bodyDocs(): object;
|
|
11
8
|
}
|
|
12
9
|
/**
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Readable } from 'node:stream';
|
|
2
|
+
import { BodyType } from './body.js';
|
|
3
|
+
import type { Schema } from './schema.js';
|
|
4
|
+
declare class JsonBody<T> extends BodyType<T, T> {
|
|
5
|
+
private contentType;
|
|
6
|
+
private schema;
|
|
7
|
+
constructor(contentType: string, schema: Schema<T>);
|
|
8
|
+
deserialize(stream: Readable, contentType: string): Promise<T>;
|
|
9
|
+
bodyDocs(): object;
|
|
10
|
+
}
|
|
11
|
+
export declare const json: <T>(schema: Schema<T>, contentType: string) => JsonBody<T>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { readableToBuffer } from '../util/stream.js';
|
|
2
|
+
import { BodyType } from './body.js';
|
|
3
|
+
import { Issue, ValidationError } from './error.js';
|
|
4
|
+
class JsonBody extends BodyType {
|
|
5
|
+
constructor(contentType, schema) {
|
|
6
|
+
super();
|
|
7
|
+
this.contentType = contentType;
|
|
8
|
+
this.schema = schema;
|
|
9
|
+
}
|
|
10
|
+
async deserialize(stream, contentType) {
|
|
11
|
+
const buffer = await readableToBuffer(stream);
|
|
12
|
+
if (buffer.length === 0) {
|
|
13
|
+
return this.schema.parse({});
|
|
14
|
+
}
|
|
15
|
+
if (contentType !== this.contentType) {
|
|
16
|
+
throw new ValidationError([
|
|
17
|
+
new Issue([], `Expected content type \`${this.contentType}\`, but got \`${contentType}\``),
|
|
18
|
+
]);
|
|
19
|
+
}
|
|
20
|
+
const obj = JSON.parse(buffer.toString('utf-8'));
|
|
21
|
+
return this.schema.parse(obj);
|
|
22
|
+
}
|
|
23
|
+
bodyDocs() {
|
|
24
|
+
return {
|
|
25
|
+
[this.contentType]: {
|
|
26
|
+
schema: this.schema.documentation(),
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export const json = (schema, contentType) => {
|
|
32
|
+
return new JsonBody(contentType, schema);
|
|
33
|
+
};
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import type { Readable } from 'node:stream';
|
|
2
2
|
import { BodyType } from './body.js';
|
|
3
3
|
export declare class NoneBody extends BodyType<undefined, undefined> {
|
|
4
|
-
deserialize(_stream: Readable, _contentType: string): Promise<
|
|
5
|
-
parsed: undefined;
|
|
6
|
-
raw: Buffer<ArrayBuffer>;
|
|
7
|
-
}>;
|
|
4
|
+
deserialize(_stream: Readable, _contentType: string): Promise<undefined>;
|
|
8
5
|
bodyDocs(): object;
|
|
9
6
|
}
|
|
10
7
|
/**
|
package/dist/validation/none.js
CHANGED
package/dist/validation/raw.d.ts
CHANGED
|
@@ -3,10 +3,7 @@ import { BodyType } from './body.js';
|
|
|
3
3
|
declare class RawBody extends BodyType<Buffer<ArrayBuffer>, Buffer<ArrayBufferLike>> {
|
|
4
4
|
private contentType;
|
|
5
5
|
constructor(contentType: string);
|
|
6
|
-
deserialize(stream: Readable, _contentType: string): Promise<
|
|
7
|
-
parsed: Buffer<ArrayBuffer>;
|
|
8
|
-
raw: Buffer<ArrayBuffer>;
|
|
9
|
-
}>;
|
|
6
|
+
deserialize(stream: Readable, _contentType: string): Promise<Buffer<ArrayBuffer>>;
|
|
10
7
|
bodyDocs(): object;
|
|
11
8
|
}
|
|
12
9
|
/**
|
package/dist/validation/raw.js
CHANGED
|
@@ -4,10 +4,7 @@ import { BodyType } from './body.js';
|
|
|
4
4
|
* The base class for all schemas.
|
|
5
5
|
*/
|
|
6
6
|
export declare abstract class Schema<T> extends BodyType<T, T> {
|
|
7
|
-
deserialize(stream: Readable, contentType: string): Promise<
|
|
8
|
-
parsed: T;
|
|
9
|
-
raw: Buffer<ArrayBuffer>;
|
|
10
|
-
}>;
|
|
7
|
+
deserialize(stream: Readable, contentType: string): Promise<T>;
|
|
11
8
|
bodyDocs(): object;
|
|
12
9
|
/**
|
|
13
10
|
* Parse the object with this schema. This throws a
|
|
@@ -8,7 +8,7 @@ export class Schema extends BodyType {
|
|
|
8
8
|
async deserialize(stream, contentType) {
|
|
9
9
|
const buffer = await readableToBuffer(stream);
|
|
10
10
|
if (buffer.length === 0) {
|
|
11
|
-
return
|
|
11
|
+
return this.parse({});
|
|
12
12
|
}
|
|
13
13
|
if (contentType !== 'application/json') {
|
|
14
14
|
throw new ValidationError([
|
|
@@ -16,7 +16,7 @@ export class Schema extends BodyType {
|
|
|
16
16
|
]);
|
|
17
17
|
}
|
|
18
18
|
const data = JSON.parse(Buffer.from(buffer).toString('utf8'));
|
|
19
|
-
return
|
|
19
|
+
return this.parse(data);
|
|
20
20
|
}
|
|
21
21
|
bodyDocs() {
|
|
22
22
|
return {
|
|
@@ -3,10 +3,7 @@ import { BodyType } from './body.js';
|
|
|
3
3
|
declare class StreamBody extends BodyType<ReadableStream, ReadableStream> {
|
|
4
4
|
private readonly contentType;
|
|
5
5
|
constructor(contentType: string);
|
|
6
|
-
deserialize(stream: Readable, _contentType: string): Promise<
|
|
7
|
-
parsed: ReadableStream;
|
|
8
|
-
raw: Buffer<ArrayBuffer>;
|
|
9
|
-
}>;
|
|
6
|
+
deserialize(stream: Readable, _contentType: string): Promise<ReadableStream>;
|
|
10
7
|
bodyDocs(): object;
|
|
11
8
|
}
|
|
12
9
|
/**
|
|
@@ -5,17 +5,14 @@ class StreamBody extends BodyType {
|
|
|
5
5
|
this.contentType = contentType;
|
|
6
6
|
}
|
|
7
7
|
deserialize(stream, _contentType) {
|
|
8
|
-
return Promise.resolve({
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}),
|
|
17
|
-
raw: Buffer.from(''),
|
|
18
|
-
});
|
|
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
|
+
}));
|
|
19
16
|
}
|
|
20
17
|
bodyDocs() {
|
|
21
18
|
return {
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yedra",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"repository": "github:0codekit/yedra",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"devDependencies": {
|
|
7
|
-
"@biomejs/biome": "^2.3.
|
|
8
|
-
"@types/bun": "^1.3.
|
|
9
|
-
"@types/node": "^25.0.
|
|
7
|
+
"@biomejs/biome": "^2.3.12",
|
|
8
|
+
"@types/bun": "^1.3.6",
|
|
9
|
+
"@types/node": "^25.0.10",
|
|
10
10
|
"@types/uuid": "^11.0.0",
|
|
11
11
|
"@types/ws": "^8.18.1",
|
|
12
12
|
"typescript": "^5.9.3"
|
|
@@ -37,6 +37,6 @@
|
|
|
37
37
|
"@opentelemetry/api": "^1.9.0",
|
|
38
38
|
"mime": "^4.1.0",
|
|
39
39
|
"uuid": "^13.0.0",
|
|
40
|
-
"ws": "^8.
|
|
40
|
+
"ws": "^8.19.0"
|
|
41
41
|
}
|
|
42
42
|
}
|