yedra 0.19.2 → 0.19.4

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
@@ -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';
@@ -100,6 +100,7 @@ class BuiltApp {
100
100
  if (req.method !== 'GET' &&
101
101
  req.method !== 'POST' &&
102
102
  req.method !== 'PUT' &&
103
+ req.method !== 'PATCH' &&
103
104
  req.method !== 'DELETE') {
104
105
  return BuiltApp.errorResponse(405, `Method \`${req.method}\` not allowed.`);
105
106
  }
@@ -272,7 +273,11 @@ yedra_request_duration_sum{method="${method}",status="${status}"} ${data?.durati
272
273
  return;
273
274
  }
274
275
  try {
275
- await result.endpoint.handle(url, result.params, ws);
276
+ const headers = Object.fromEntries(Object.entries(req.headers).map(([key, value]) => [
277
+ key,
278
+ Array.isArray(value) ? value.join(',') : (value ?? ''),
279
+ ]));
280
+ await result.endpoint.handle(url, result.params, headers, ws);
276
281
  }
277
282
  catch (error) {
278
283
  if (error instanceof HttpError) {
@@ -46,7 +46,7 @@ type EndpointOptions<Params extends Record<string, Schema<unknown>>, Query exten
46
46
  do: (req: ReqObject<Typeof<ObjectSchema<Params>>, Typeof<ObjectSchema<Query>>, Typeof<ObjectSchema<Headers>>, Typeof<Req>>) => ResObject<TypeofAccepts<Res>>;
47
47
  };
48
48
  export declare abstract class RestEndpoint {
49
- abstract get method(): 'GET' | 'POST' | 'PUT' | 'DELETE';
49
+ abstract get method(): 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
50
50
  abstract handle(req: {
51
51
  url: string;
52
52
  body: Readable;
@@ -72,8 +72,8 @@ declare class ConcreteRestEndpoint<Params extends Record<string, Schema<unknown>
72
72
  private paramsSchema;
73
73
  private querySchema;
74
74
  private headersSchema;
75
- constructor(method: 'GET' | 'POST' | 'PUT' | 'DELETE', options: EndpointOptions<Params, Query, Headers, Req, Res>);
76
- get method(): 'GET' | 'POST' | 'PUT' | 'DELETE';
75
+ constructor(method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE', options: EndpointOptions<Params, Query, Headers, Req, Res>);
76
+ get method(): 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
77
77
  handle(req: {
78
78
  url: string;
79
79
  body: Readable;
@@ -97,6 +97,9 @@ export declare class Post<Params extends Record<string, Schema<unknown>>, Query
97
97
  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
98
  constructor(options: EndpointOptions<Params, Query, Headers, Req, Res>);
99
99
  }
100
+ 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> {
101
+ constructor(options: EndpointOptions<Params, Query, Headers, Req, Res>);
102
+ }
100
103
  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
104
  constructor(options: Omit<EndpointOptions<Params, Query, Headers, NoneBody, Res>, 'req'>);
102
105
  }
@@ -171,6 +171,11 @@ export class Put extends ConcreteRestEndpoint {
171
171
  super('PUT', options);
172
172
  }
173
173
  }
174
+ export class Patch extends ConcreteRestEndpoint {
175
+ constructor(options) {
176
+ super('PATCH', options);
177
+ }
178
+ }
174
179
  export class Delete extends ConcreteRestEndpoint {
175
180
  constructor(options) {
176
181
  super('DELETE', { req: none(), ...options });
@@ -32,26 +32,29 @@ declare class YedraWebSocket {
32
32
  close(code?: number, reason?: string): void;
33
33
  }
34
34
  export type { YedraWebSocket };
35
- type WebSocketOptions<Params extends Record<string, Schema<unknown>>, Query extends Record<string, Schema<unknown>>> = {
35
+ type WebSocketOptions<Params extends Record<string, Schema<unknown>>, Query extends Record<string, Schema<unknown>>, Headers extends Record<string, Schema<unknown>>> = {
36
36
  category: string;
37
37
  summary: string;
38
38
  description?: string;
39
39
  params: Params;
40
40
  query: Query;
41
+ headers: Headers;
41
42
  do: (ws: YedraWebSocket, req: {
42
43
  url: string;
43
44
  params: Typeof<ObjectSchema<Params>>;
44
45
  query: Typeof<ObjectSchema<Query>>;
46
+ headers: Typeof<ObjectSchema<Headers>>;
45
47
  }) => Promise<void> | void;
46
48
  };
47
49
  export declare abstract class WsEndpoint {
48
- abstract handle(url: URL, params: Record<string, string>, ws: NodeWebSocket): Promise<void>;
50
+ abstract handle(url: URL, params: Record<string, string>, headers: Record<string, string>, ws: NodeWebSocket): Promise<void>;
49
51
  }
50
- export declare class Ws<Params extends Record<string, Schema<unknown>>, Query extends Record<string, Schema<unknown>>> extends WsEndpoint {
52
+ export declare class Ws<Params extends Record<string, Schema<unknown>>, Query extends Record<string, Schema<unknown>>, Headers extends Record<string, Schema<unknown>>> extends WsEndpoint {
51
53
  private options;
52
54
  private paramsSchema;
53
55
  private querySchema;
54
- constructor(options: WebSocketOptions<Params, Query>);
55
- handle(url: URL, params: Record<string, string>, ws: NodeWebSocket): Promise<void>;
56
+ private headersSchema;
57
+ constructor(options: WebSocketOptions<Params, Query, Headers>);
58
+ handle(url: URL, params: Record<string, string>, headers: Record<string, string>, ws: NodeWebSocket): Promise<void>;
56
59
  documentation(): object;
57
60
  }
@@ -1,6 +1,6 @@
1
1
  import { paramDocs } from '../util/docs.js';
2
2
  import { ValidationError } from '../validation/error.js';
3
- import { object } from '../validation/object.js';
3
+ import { laxObject, object } from '../validation/object.js';
4
4
  import { BadRequestError } from './errors.js';
5
5
  class YedraWebSocket {
6
6
  constructor(ws) {
@@ -66,13 +66,16 @@ export class Ws extends WsEndpoint {
66
66
  this.options = options;
67
67
  this.paramsSchema = object(options.params);
68
68
  this.querySchema = object(options.query);
69
+ this.headersSchema = laxObject(options.headers);
69
70
  }
70
- async handle(url, params, ws) {
71
+ async handle(url, params, headers, ws) {
71
72
  let parsedParams;
72
73
  let parsedQuery;
74
+ let parsedHeaders;
73
75
  try {
74
76
  parsedParams = this.paramsSchema.parse(params);
75
77
  parsedQuery = this.querySchema.parse(Object.fromEntries(url.searchParams));
78
+ parsedHeaders = this.headersSchema.parse(headers);
76
79
  }
77
80
  catch (error) {
78
81
  if (error instanceof ValidationError) {
@@ -84,6 +87,7 @@ export class Ws extends WsEndpoint {
84
87
  url: url.pathname,
85
88
  params: parsedParams,
86
89
  query: parsedQuery,
90
+ headers: parsedHeaders,
87
91
  });
88
92
  return undefined;
89
93
  }
@@ -91,6 +95,7 @@ export class Ws extends WsEndpoint {
91
95
  const parameters = [
92
96
  ...paramDocs(this.options.params, 'path', []),
93
97
  ...paramDocs(this.options.query, 'query', []),
98
+ ...paramDocs(this.options.headers, 'header', []),
94
99
  ];
95
100
  return {
96
101
  tags: [this.options.category],
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "yedra",
3
- "version": "0.19.2",
3
+ "version": "0.19.4",
4
4
  "repository": "github:0codekit/yedra",
5
5
  "main": "dist/index.js",
6
6
  "devDependencies": {
7
- "@biomejs/biome": "^2.3.8",
8
- "@types/bun": "^1.3.4",
9
- "@types/node": "^25.0.1",
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.18.3"
40
+ "ws": "^8.19.0"
41
41
  }
42
42
  }