bun-crumb 0.6.0 → 0.8.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 +42 -9
- package/dist/index.js +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/types/route.d.ts +40 -7
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -48,7 +48,8 @@ type Validate = (data: unknown, schema: SchemaData) => boolean;
|
|
|
48
48
|
* const method: HttpMethod = 'GET';
|
|
49
49
|
* ```
|
|
50
50
|
*/
|
|
51
|
-
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS';
|
|
51
|
+
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
|
|
52
|
+
type RedirectStatusCode = 300 | 301 | 302 | 303 | 304 | 307 | 308;
|
|
52
53
|
/**
|
|
53
54
|
* HTTP Header struct.
|
|
54
55
|
*/
|
|
@@ -57,16 +58,47 @@ type Header = {
|
|
|
57
58
|
value: string;
|
|
58
59
|
};
|
|
59
60
|
type Headers = ResponseInit['headers'];
|
|
61
|
+
type RouteRequestParams<T extends string | undefined = undefined> = [
|
|
62
|
+
T
|
|
63
|
+
] extends [string] ? {
|
|
64
|
+
[K in T]: string;
|
|
65
|
+
} : {
|
|
66
|
+
[key: string]: string | undefined;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
*
|
|
70
|
+
*
|
|
71
|
+
* Type of RouteRequest generic
|
|
72
|
+
*
|
|
73
|
+
*
|
|
74
|
+
*
|
|
75
|
+
*
|
|
76
|
+
*
|
|
77
|
+
*/
|
|
78
|
+
interface RouteRequestGeneric {
|
|
79
|
+
body?: unknown;
|
|
80
|
+
params?: string;
|
|
81
|
+
}
|
|
60
82
|
/**
|
|
61
83
|
* Type of route handler `request`
|
|
62
84
|
*/
|
|
63
|
-
interface RouteRequest<T extends {
|
|
64
|
-
|
|
65
|
-
} = {
|
|
66
|
-
body: unknown;
|
|
67
|
-
}> extends Omit<BunRequest, 'body'> {
|
|
85
|
+
interface RouteRequest<T extends RouteRequestGeneric = RouteRequestGeneric> extends Omit<BunRequest, 'params'> {
|
|
86
|
+
params: RouteRequestParams<T['params']>;
|
|
68
87
|
/**
|
|
69
|
-
*
|
|
88
|
+
* #### Parses and validates body of request.
|
|
89
|
+
*
|
|
90
|
+
* - Parses body to JSON or text
|
|
91
|
+
* - Validates body with `schemaValidator` if it is provided.
|
|
92
|
+
*
|
|
93
|
+
* @returns Promise with handled body
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
*
|
|
97
|
+
* ```typescript
|
|
98
|
+
* request.handleBody().then((bodyData) => {
|
|
99
|
+
* console.log(bodyData);
|
|
100
|
+
* })
|
|
101
|
+
* ```
|
|
70
102
|
*/
|
|
71
103
|
handleBody: () => Promise<T extends {
|
|
72
104
|
body: unknown;
|
|
@@ -87,6 +119,7 @@ interface RouteResponse<T extends {
|
|
|
87
119
|
}> {
|
|
88
120
|
setHeader: (name: Header['name'], value: Header['value']) => void;
|
|
89
121
|
send: (data: T['body'], options?: ResponseOptions) => void;
|
|
122
|
+
redirect: (url: string, status: RedirectStatusCode | (number & {})) => void;
|
|
90
123
|
}
|
|
91
124
|
type Route = Partial<Record<HttpMethod, RouteOptions>>;
|
|
92
125
|
type RouteHandler = (request: RouteRequest, response: RouteResponse) => Promise<void> | void;
|
|
@@ -143,7 +176,7 @@ interface ListenOptions {
|
|
|
143
176
|
* listen(PORT, 'localhost');
|
|
144
177
|
* ```
|
|
145
178
|
*/
|
|
146
|
-
declare const listen: (options
|
|
179
|
+
declare const listen: (options?: ListenOptions) => void;
|
|
147
180
|
|
|
148
181
|
/**
|
|
149
182
|
* Creates a route with `url`, `method` and `handler`.
|
|
@@ -201,4 +234,4 @@ declare const listen: (options: ListenOptions) => void;
|
|
|
201
234
|
declare const createRoute: (routeOptions: RouteOptions) => void;
|
|
202
235
|
|
|
203
236
|
export { createRoute, listen };
|
|
204
|
-
export type { Header, Headers, HttpMethod, ListenOptions, ResponseOptions, Route, RouteHandler, RouteOptions, RouteRequest, RouteResponse, Schema, SchemaData, Validate };
|
|
237
|
+
export type { Header, Headers, HttpMethod, ListenOptions, RedirectStatusCode, ResponseOptions, Route, RouteHandler, RouteOptions, RouteRequest, RouteRequestGeneric, RouteRequestParams, RouteResponse, Schema, SchemaData, Validate };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{serve as t}from"bun";class e extends Error{status;constructor(t,e){super(e),this.status=t,this.name="HttpError"}}const s=new Map,n=(t,s)=>n=>{const o=n.headers.get("Content-Type")??"text/plain",r=n;return r.handleBody=()=>((t,s,n,o)=>{const r={"application/json":t=>t.json().catch(()=>{throw new e(400,"Bad Request")}).then(t=>{if(n&&o&&!o(t,n))throw new e(400,"Request does not match schema");return t}),"text/plain":t=>t.text().catch(t=>{throw new e(400,t)}).then(t=>{if(n&&o&&!o(t,n))throw new e(400,"Request does not match schema");return t})};return s in r?r[s](t):Promise.reject(new e(415,"Unsupported media type"))})(n,o,t.schema,s),Promise.resolve(((t,e)=>{let s=200,n="",o="";const r={},a={setHeader:(t,e)=>{r[t]=e},send:(t,e)=>{"object"==typeof t?(r["Content-Type"]="application/json",o=JSON.stringify(t)):"string"==typeof t&&(r["Content-Type"]="text/plain",o=t),e&&(s=e.status,n=e.statusText)}};return Promise.resolve(e.handler(t,a)).then(()=>new Response(o,{headers:r,status:s,statusText:n}))})(r,t)).then(t=>t).catch(t=>t instanceof e?new Response(t.message,{status:t.status}):new Response("Internal server error",{status:500}))},o=(t,e)=>{const s={};for(const o in t)Object.hasOwn(t,o)&&(s[o]=n(t[o],e));return s},r=(t,e)=>{const s={};for(const n of t)s[n[0]]=o(n[1],e);return t.clear(),s},a=e=>{t({port:e
|
|
1
|
+
import{serve as t}from"bun";class e extends Error{status;constructor(t,e){super(e),this.status=t,this.name="HttpError"}}const s=new Map,n=(t,s)=>n=>{const o=n.headers.get("Content-Type")??"text/plain",r=n;return r.handleBody=()=>((t,s,n,o)=>{const r={"application/json":t=>t.json().catch(()=>{throw new e(400,"Bad Request")}).then(t=>{if(n&&o&&!o(t,n))throw new e(400,"Request does not match schema");return t}),"text/plain":t=>t.text().catch(t=>{throw new e(400,t)}).then(t=>{if(n&&o&&!o(t,n))throw new e(400,"Request does not match schema");return t})};return s in r?r[s](t):Promise.reject(new e(415,"Unsupported media type"))})(n,o,t.schema,s),Promise.resolve(((t,e)=>{let s=200,n="",o="";const r={},a={setHeader:(t,e)=>{r[t]=e},send:(t,e)=>{"object"==typeof t?(r["Content-Type"]="application/json",o=JSON.stringify(t)):"string"==typeof t&&(r["Content-Type"]="text/plain",o=t),e&&(s=e.status,n=e.statusText)},redirect:(t,e)=>{o="",s=e,r.Location=t}};return Promise.resolve(e.handler(t,a)).then(()=>new Response(o,{headers:r,status:s,statusText:n}))})(r,t)).then(t=>t).catch(t=>t instanceof e?new Response(t.message,{status:t.status}):new Response("Internal server error",{status:500}))},o=(t,e)=>{const s={};for(const o in t)Object.hasOwn(t,o)&&(s[o]=n(t[o],e));return s},r=(t,e)=>{const s={};for(const n of t)s[n[0]]=o(n[1],e);return t.clear(),s},a=e=>{t({port:e?.port,hostname:e?.hostname,development:e?.development??!1,routes:r(s,e?.schemaValidator)})},c=t=>{const e=s.get(t.url);e?e[t.method]=t:s.set(t.url,{[t.method]:t})};export{c as createRoute,a as listen};
|
package/dist/server.d.ts
CHANGED
|
@@ -104,5 +104,5 @@ export declare const prepareRoutes: (routes: Routes, schemaValidator?: Validate)
|
|
|
104
104
|
* listen(PORT, 'localhost');
|
|
105
105
|
* ```
|
|
106
106
|
*/
|
|
107
|
-
export declare const listen: (options
|
|
107
|
+
export declare const listen: (options?: ListenOptions) => void;
|
|
108
108
|
export {};
|
package/dist/types/route.d.ts
CHANGED
|
@@ -8,7 +8,8 @@ import type { SchemaData } from './schema';
|
|
|
8
8
|
* const method: HttpMethod = 'GET';
|
|
9
9
|
* ```
|
|
10
10
|
*/
|
|
11
|
-
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS';
|
|
11
|
+
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
|
|
12
|
+
export type RedirectStatusCode = 300 | 301 | 302 | 303 | 304 | 307 | 308;
|
|
12
13
|
/**
|
|
13
14
|
* HTTP Header struct.
|
|
14
15
|
*/
|
|
@@ -17,16 +18,47 @@ export type Header = {
|
|
|
17
18
|
value: string;
|
|
18
19
|
};
|
|
19
20
|
export type Headers = ResponseInit['headers'];
|
|
21
|
+
export type RouteRequestParams<T extends string | undefined = undefined> = [
|
|
22
|
+
T
|
|
23
|
+
] extends [string] ? {
|
|
24
|
+
[K in T]: string;
|
|
25
|
+
} : {
|
|
26
|
+
[key: string]: string | undefined;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
*
|
|
30
|
+
*
|
|
31
|
+
* Type of RouteRequest generic
|
|
32
|
+
*
|
|
33
|
+
*
|
|
34
|
+
*
|
|
35
|
+
*
|
|
36
|
+
*
|
|
37
|
+
*/
|
|
38
|
+
export interface RouteRequestGeneric {
|
|
39
|
+
body?: unknown;
|
|
40
|
+
params?: string;
|
|
41
|
+
}
|
|
20
42
|
/**
|
|
21
43
|
* Type of route handler `request`
|
|
22
44
|
*/
|
|
23
|
-
export interface RouteRequest<T extends {
|
|
24
|
-
|
|
25
|
-
} = {
|
|
26
|
-
body: unknown;
|
|
27
|
-
}> extends Omit<BunRequest, 'body'> {
|
|
45
|
+
export interface RouteRequest<T extends RouteRequestGeneric = RouteRequestGeneric> extends Omit<BunRequest, 'params'> {
|
|
46
|
+
params: RouteRequestParams<T['params']>;
|
|
28
47
|
/**
|
|
29
|
-
*
|
|
48
|
+
* #### Parses and validates body of request.
|
|
49
|
+
*
|
|
50
|
+
* - Parses body to JSON or text
|
|
51
|
+
* - Validates body with `schemaValidator` if it is provided.
|
|
52
|
+
*
|
|
53
|
+
* @returns Promise with handled body
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
*
|
|
57
|
+
* ```typescript
|
|
58
|
+
* request.handleBody().then((bodyData) => {
|
|
59
|
+
* console.log(bodyData);
|
|
60
|
+
* })
|
|
61
|
+
* ```
|
|
30
62
|
*/
|
|
31
63
|
handleBody: () => Promise<T extends {
|
|
32
64
|
body: unknown;
|
|
@@ -47,6 +79,7 @@ export interface RouteResponse<T extends {
|
|
|
47
79
|
}> {
|
|
48
80
|
setHeader: (name: Header['name'], value: Header['value']) => void;
|
|
49
81
|
send: (data: T['body'], options?: ResponseOptions) => void;
|
|
82
|
+
redirect: (url: string, status: RedirectStatusCode | (number & {})) => void;
|
|
50
83
|
}
|
|
51
84
|
export type Route = Partial<Record<HttpMethod, RouteOptions>>;
|
|
52
85
|
export type RouteHandler = (request: RouteRequest, response: RouteResponse) => Promise<void> | void;
|