yedra 0.18.0 → 0.18.2

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 CHANGED
@@ -4,5 +4,6 @@ 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
6
  export { Delete, Get, Post, Put } from './routing/rest.js';
7
+ export type { YedraWebSocket } from './routing/websocket.js';
7
8
  export { Ws } from './routing/websocket.js';
8
9
  export { SecurityScheme } from './util/security.js';
@@ -10,6 +10,11 @@ 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>;
13
18
  };
14
19
  type ResObject<Body> = Promise<{
15
20
  status?: number;
@@ -26,12 +26,15 @@ class ConcreteRestEndpoint extends RestEndpoint {
26
26
  }
27
27
  async handle(req) {
28
28
  let parsedBody;
29
+ let rawBody;
29
30
  let parsedParams;
30
31
  let parsedQuery;
31
32
  let parsedHeaders;
32
33
  const issues = [];
33
34
  try {
34
- parsedBody = await this.options.req.deserialize(req.body, req.headers['content-type'] ?? 'application/octet-stream');
35
+ const result = await this.options.req.deserialize(req.body, req.headers['content-type'] ?? 'application/octet-stream');
36
+ parsedBody = result.parsed;
37
+ rawBody = result.raw;
35
38
  }
36
39
  catch (error) {
37
40
  if (error instanceof SyntaxError) {
@@ -91,6 +94,8 @@ class ConcreteRestEndpoint extends RestEndpoint {
91
94
  headers: parsedHeaders,
92
95
  // biome-ignore lint/style/noNonNullAssertion: this is required to convince TypeScript that this is initialized
93
96
  body: parsedBody,
97
+ // biome-ignore lint/style/noNonNullAssertion: this is required to convince TypeScript that this is initialized
98
+ raw: rawBody,
94
99
  });
95
100
  }
96
101
  isHidden() {
@@ -31,6 +31,7 @@ declare class YedraWebSocket {
31
31
  */
32
32
  close(code?: number, reason?: string): void;
33
33
  }
34
+ export type { YedraWebSocket };
34
35
  type WebSocketOptions<Params extends Record<string, Schema<unknown>>, Query extends Record<string, Schema<unknown>>> = {
35
36
  category: string;
36
37
  summary: string;
@@ -54,4 +55,3 @@ export declare class Ws<Params extends Record<string, Schema<unknown>>, Query ex
54
55
  handle(url: URL, params: Record<string, string>, ws: NodeWebSocket): Promise<void>;
55
56
  documentation(): object;
56
57
  }
57
- export {};
@@ -17,7 +17,10 @@ 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<Provides>;
20
+ abstract deserialize(stream: Readable, contentType: string): Promise<{
21
+ parsed: Provides;
22
+ raw: Buffer<ArrayBuffer>;
23
+ }>;
21
24
  /**
22
25
  * Generate OpenAPI docs for this body.
23
26
  */
@@ -3,7 +3,10 @@ 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<Typeof<T[number]>>;
6
+ deserialize(stream: Readable, contentType: string): Promise<{
7
+ parsed: Typeof<T[number]>;
8
+ raw: Buffer<ArrayBuffer>;
9
+ }>;
7
10
  bodyDocs(): object;
8
11
  }
9
12
  /**
@@ -1,7 +1,10 @@
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<undefined>;
4
+ deserialize(_stream: Readable, _contentType: string): Promise<{
5
+ parsed: undefined;
6
+ raw: Buffer<ArrayBuffer>;
7
+ }>;
5
8
  bodyDocs(): object;
6
9
  }
7
10
  /**
@@ -1,7 +1,7 @@
1
1
  import { BodyType } from './body.js';
2
2
  export class NoneBody extends BodyType {
3
3
  deserialize(_stream, _contentType) {
4
- return Promise.resolve(undefined);
4
+ return Promise.resolve({ parsed: undefined, raw: Buffer.from('') });
5
5
  }
6
6
  bodyDocs() {
7
7
  // TODO
@@ -3,7 +3,10 @@ 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<Buffer<ArrayBuffer>>;
6
+ deserialize(stream: Readable, _contentType: string): Promise<{
7
+ parsed: Buffer<ArrayBuffer>;
8
+ raw: Buffer<ArrayBuffer>;
9
+ }>;
7
10
  bodyDocs(): object;
8
11
  }
9
12
  /**
@@ -6,7 +6,11 @@ class RawBody extends BodyType {
6
6
  this.contentType = contentType;
7
7
  }
8
8
  async deserialize(stream, _contentType) {
9
- return await readableToBuffer(stream);
9
+ const buffer = await readableToBuffer(stream);
10
+ return {
11
+ parsed: buffer,
12
+ raw: buffer,
13
+ };
10
14
  }
11
15
  bodyDocs() {
12
16
  return {
@@ -4,7 +4,10 @@ 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<T>;
7
+ deserialize(stream: Readable, contentType: string): Promise<{
8
+ parsed: T;
9
+ raw: Buffer<ArrayBuffer>;
10
+ }>;
8
11
  bodyDocs(): object;
9
12
  /**
10
13
  * 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 this.parse({});
11
+ return { parsed: this.parse({}), raw: buffer };
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 this.parse(data);
19
+ return { parsed: this.parse(data), raw: buffer };
20
20
  }
21
21
  bodyDocs() {
22
22
  return {
@@ -3,7 +3,10 @@ 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<ReadableStream>;
6
+ deserialize(stream: Readable, _contentType: string): Promise<{
7
+ parsed: ReadableStream;
8
+ raw: Buffer<ArrayBuffer>;
9
+ }>;
7
10
  bodyDocs(): object;
8
11
  }
9
12
  /**
@@ -5,14 +5,17 @@ class StreamBody extends BodyType {
5
5
  this.contentType = contentType;
6
6
  }
7
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
- }));
8
+ return Promise.resolve({
9
+ parsed: new ReadableStream({
10
+ async start(controller) {
11
+ for await (const chunk of stream) {
12
+ controller.enqueue(chunk);
13
+ }
14
+ controller.close();
15
+ },
16
+ }),
17
+ raw: Buffer.from(''),
18
+ });
16
19
  }
17
20
  bodyDocs() {
18
21
  return {
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "yedra",
3
- "version": "0.18.0",
3
+ "version": "0.18.2",
4
4
  "repository": "github:0codekit/yedra",
5
5
  "main": "dist/index.js",
6
6
  "devDependencies": {
7
- "@biomejs/biome": "^2.2.5",
8
- "@types/bun": "^1.2.23",
9
- "@types/node": "^24.7.0",
7
+ "@biomejs/biome": "^2.3.3",
8
+ "@types/bun": "^1.3.1",
9
+ "@types/node": "^24.10.0",
10
10
  "@types/uuid": "^11.0.0",
11
11
  "@types/ws": "^8.18.1",
12
12
  "typescript": "^5.9.3"