@server/next 0.26.0 → 0.27.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.
Files changed (66) hide show
  1. package/index.js +2005 -0
  2. package/package.json +17 -12
  3. package/readme.md +1 -0
  4. package/src/{helpers/jsx.js → jsx/jsx-dev-runtime.js} +32 -17
  5. package/src/{helpers/jsx.test.jsx → jsx/jsx-runtime.test.jsx} +1 -1
  6. package/src/ServerError.js +0 -27
  7. package/src/auth/NoSession.js +0 -19
  8. package/src/auth/auth-cookie.test.js +0 -42
  9. package/src/auth/auth-token.test.js +0 -110
  10. package/src/auth/auth.js +0 -62
  11. package/src/auth/index.js +0 -104
  12. package/src/auth/index.test.js +0 -133
  13. package/src/auth/logout.js +0 -20
  14. package/src/auth/providers/email.js +0 -145
  15. package/src/auth/providers/github.js +0 -84
  16. package/src/auth/providers/index.js +0 -4
  17. package/src/auth/session.js +0 -18
  18. package/src/auth/updateUser.js +0 -6
  19. package/src/auth/user.js +0 -9
  20. package/src/context/node.js +0 -68
  21. package/src/context/parseBody.js +0 -107
  22. package/src/context/parseBody.test.js +0 -60
  23. package/src/context/parseCookies.js +0 -9
  24. package/src/context/winter.js +0 -46
  25. package/src/errors/index.js +0 -36
  26. package/src/helpers/StatusError.js +0 -6
  27. package/src/helpers/bucket.js +0 -89
  28. package/src/helpers/bucket.test.js +0 -51
  29. package/src/helpers/color.js +0 -30
  30. package/src/helpers/config.js +0 -64
  31. package/src/helpers/cookies.test.js +0 -23
  32. package/src/helpers/cors.js +0 -24
  33. package/src/helpers/cors.test.js +0 -64
  34. package/src/helpers/createCookies.js +0 -16
  35. package/src/helpers/createId.js +0 -51
  36. package/src/helpers/createWebsocket.js +0 -21
  37. package/src/helpers/define.js +0 -18
  38. package/src/helpers/getMachine.js +0 -26
  39. package/src/helpers/handleRequest.js +0 -34
  40. package/src/helpers/index.js +0 -14
  41. package/src/helpers/iterate.js +0 -8
  42. package/src/helpers/iteratorAsyncToReadable.js +0 -20
  43. package/src/helpers/iteratorToReadable.js +0 -10
  44. package/src/helpers/parseHeaders.js +0 -15
  45. package/src/helpers/toWeb.js +0 -15
  46. package/src/helpers/types.js +0 -81
  47. package/src/helpers/validate.js +0 -34
  48. package/src/index.d.ts +0 -198
  49. package/src/index.js +0 -250
  50. package/src/index.test.js +0 -87
  51. package/src/index.types.ts +0 -28
  52. package/src/middle/assets.js +0 -17
  53. package/src/middle/assets.test.js +0 -10
  54. package/src/middle/index.js +0 -7
  55. package/src/middle/openapi.js +0 -147
  56. package/src/middle/timer.js +0 -14
  57. package/src/parseResponse.js +0 -127
  58. package/src/pathPattern.js +0 -47
  59. package/src/pathPattern.test.js +0 -99
  60. package/src/polyfill.js +0 -18
  61. package/src/reply.js +0 -153
  62. package/src/router.js +0 -53
  63. package/src/router.test.js +0 -57
  64. package/src/session.test.js +0 -65
  65. package/src/test/toSucceed.js +0 -64
  66. package/src/url.test.js +0 -26
@@ -1,81 +0,0 @@
1
- // From https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
2
- export default {
3
- aac: "audio/aac",
4
- abw: "application/x-abiword",
5
- arc: "application/x-freearc",
6
- avif: "image/avif",
7
- avi: "video/x-msvideo",
8
- azw: "application/vnd.amazon.ebook",
9
- bin: "application/octet-stream",
10
- bmp: "image/bmp",
11
- bz: "application/x-bzip",
12
- bz2: "application/x-bzip2",
13
- cda: "application/x-cdf",
14
- csh: "application/x-csh",
15
- css: "text/css",
16
- csv: "text/csv",
17
- doc: "application/msword",
18
- docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
19
- eot: "application/vnd.ms-fontobject",
20
- epub: "application/epub+zip",
21
- gz: "application/gzip",
22
- gif: "image/gif",
23
- htm: "text/html",
24
- html: "text/html",
25
- ico: "image/vnd.microsoft.icon",
26
- ics: "text/calendar",
27
- jar: "application/java-archive",
28
- jpeg: "image/jpeg",
29
- jpg: "image/jpeg",
30
- js: "text/javascript",
31
- json: "application/json",
32
- jsonld: "application/ld+json",
33
- md: "text/markdown",
34
- mid: "audio/midi",
35
- midi: "audio/midi",
36
- mjs: "text/javascript",
37
- mp3: "audio/mpeg",
38
- mp4: "video/mp4",
39
- mpeg: "video/mpeg",
40
- mpkg: "application/vnd.apple.installer+xml",
41
- odp: "application/vnd.oasis.opendocument.presentation",
42
- ods: "application/vnd.oasis.opendocument.spreadsheet",
43
- odt: "application/vnd.oasis.opendocument.text",
44
- oga: "audio/ogg",
45
- ogv: "video/ogg",
46
- ogx: "application/ogg",
47
- opus: "audio/opus",
48
- otf: "font/otf",
49
- png: "image/png",
50
- pdf: "application/pdf",
51
- php: "application/x-httpd-php",
52
- ppt: "application/vnd.ms-powerpoint",
53
- pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
54
- rar: "application/vnd.rar",
55
- rtf: "application/rtf",
56
- sh: "application/x-sh",
57
- svg: "image/svg+xml",
58
- tar: "application/x-tar",
59
- text: "text/plain",
60
- tif: "image/tiff",
61
- tiff: "image/tiff",
62
- ts: "video/mp2t",
63
- ttf: "font/ttf",
64
- txt: "text/plain",
65
- vsd: "application/vnd.visio",
66
- wav: "audio/wav",
67
- weba: "audio/webm",
68
- webm: "video/webm",
69
- webp: "image/webp",
70
- woff: "font/woff",
71
- woff2: "font/woff2",
72
- xhtml: "application/xhtml+xml",
73
- xls: "application/vnd.ms-excel",
74
- xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
75
- xml: "application/xml",
76
- xul: "application/vnd.mozilla.xul+xml",
77
- zip: "application/zip",
78
- "3gp": "video/3gpp",
79
- "3g2": "video/3gpp2",
80
- "7z": "application/x-7z-compressed",
81
- };
@@ -1,34 +0,0 @@
1
- import StatusError from "./StatusError.js";
2
-
3
- export default function validate(ctx, schema) {
4
- if (!schema || typeof schema !== "object") return;
5
-
6
- let base;
7
- try {
8
- if (typeof schema?.body === "function") {
9
- base = "body";
10
- schema.body(ctx.body || {});
11
- }
12
- if (typeof schema?.body?.parse === "function") {
13
- base = "body";
14
- schema.body.parse(ctx.body || {});
15
- }
16
- if (typeof schema?.query === "function") {
17
- base = "query";
18
- schema.query(ctx.url.query || {});
19
- }
20
- if (typeof schema?.query?.parse === "function") {
21
- base = "query";
22
- schema.query.parse(ctx.url.query || {});
23
- }
24
- } catch (error) {
25
- if (error.name === "ZodError" || error.constructor.name === "ZodError") {
26
- const message = error.issues
27
- .map(({ path, message }) => `[${base}.${path.join(".")}]: ${message}`)
28
- .sort()
29
- .join("\n");
30
- throw new StatusError(message, 422);
31
- }
32
- throw error;
33
- }
34
- }
package/src/index.d.ts DELETED
@@ -1,198 +0,0 @@
1
- type Method =
2
- | "socket"
3
- | "get"
4
- | "head"
5
- | "post"
6
- | "put"
7
- | "patch"
8
- | "delete"
9
- | "options";
10
-
11
- type Store = {
12
- get: (key: string) => Promise<any>;
13
- set: (
14
- key: string,
15
- value: any,
16
- { expires }?: { expires?: string | number },
17
- ) => Promise<any>;
18
- };
19
-
20
- type Bucket =
21
- | string
22
- | {
23
- read: (key: string) => ReadableStream;
24
- write: (
25
- key: string,
26
- data:
27
- | string
28
- | NodeJS.ArrayBufferView
29
- | Iterable<string | NodeJS.ArrayBufferView>
30
- | AsyncIterable<string | NodeJS.ArrayBufferView>,
31
- type: BufferEncoding,
32
- ) => Promise<Boolean>;
33
- delete: (key: string) => Promise<Boolean>;
34
- };
35
-
36
- type Auth = {
37
- type: "cookie" | "token";
38
- provider: "github" | "email";
39
- };
40
- type AuthString = `${Auth["type"]}:${Auth["provider"]}`;
41
-
42
- type Domain = `https://${string}/`;
43
- type Origin = boolean | "*" | Domain | Domain[];
44
- type Cors = {
45
- origin: Origin;
46
- methods: string;
47
- headers: string;
48
- credentials?: boolean;
49
- };
50
-
51
- type ServerOptions = {
52
- port?: number;
53
- views?: string | Bucket;
54
- public?: string | Bucket;
55
- uploads?: string | Bucket;
56
- cors?: boolean | Origin | Cors;
57
- auth?: AuthString | Auth;
58
- store?: Store;
59
- };
60
-
61
- type ExtractPathParams<Path extends string> =
62
- Path extends `${string}:${infer Param}(${infer Type})?/${infer Rest}`
63
- ? `${Param}:${Type}?` | ExtractPathParams<`/${Rest}`>
64
- : Path extends `${string}:${infer Param}(${infer Type})?`
65
- ? `${Param}:${Type}?`
66
- : Path extends `${string}:${infer Param}(${infer Type})/${infer Rest}`
67
- ? `${Param}:${Type}` | ExtractPathParams<`/${Rest}`>
68
- : Path extends `${string}:${infer Param}(${infer Type})`
69
- ? `${Param}:${Type}`
70
- : Path extends `${string}:${infer Param}?/${infer Rest}`
71
- ? `${Param}?` | ExtractPathParams<`/${Rest}`>
72
- : Path extends `${string}:${infer Param}?`
73
- ? `${Param}?`
74
- : Path extends `${string}:${infer Param}/${infer Rest}`
75
- ? Param | ExtractPathParams<`/${Rest}`>
76
- : Path extends `${string}:${infer Param}`
77
- ? Param
78
- : never;
79
-
80
- type ParamTypeMap = {
81
- string: string;
82
- number: number;
83
- date: Date;
84
- };
85
-
86
- type InferParamType<T extends string> = T extends keyof ParamTypeMap
87
- ? ParamTypeMap[T]
88
- : string;
89
-
90
- type ParamsToObject<Params extends string> = {
91
- [K in Params as K extends `${infer Key}:${infer Type}?`
92
- ? Key
93
- : K extends `${infer Key}:${infer Type}`
94
- ? Key
95
- : K extends `${infer Key}?`
96
- ? Key
97
- : K]: K extends `${infer Key}:${infer Type}?`
98
- ? InferParamType<Type> | undefined
99
- : K extends `${infer Key}:${infer Type}`
100
- ? InferParamType<Type>
101
- : K extends `${infer Key}?`
102
- ? string | undefined
103
- : string;
104
- };
105
-
106
- type PathToParams<Path extends string> = ParamsToObject<
107
- ExtractPathParams<Path>
108
- >;
109
-
110
- type Simplify<T> = T extends object ? { [K in keyof T]: T[K] } : T;
111
-
112
- type Context<Path extends string = string> = {
113
- method: Method;
114
- headers: { [key: string]: string | string[] };
115
- cookies: { [key: string]: any };
116
- body?: any;
117
- url: URL & {
118
- params: Simplify<PathToParams<Path>>; // Simplify here
119
- query: { [key: string]: string };
120
- };
121
- options: ServerOptions;
122
- };
123
-
124
- type Body = string;
125
-
126
- type ContentType = "application/json" | "text/plain" | (string & {});
127
-
128
- // (src: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers)
129
- type Headers = {
130
- "cache-control"?: string;
131
- "content-type"?: ContentType;
132
- "set-cookie"?: string;
133
- "content-length"?: string;
134
- server?: string;
135
- location?: string;
136
-
137
- [key: string]: string | undefined;
138
- };
139
-
140
- type InlineReply =
141
- | Response
142
- | { body: Body; headers?: Headers }
143
- | string
144
- | number
145
- | undefined;
146
-
147
- type Middleware<Path extends string = string> = (
148
- ctx: Context<Path>,
149
- ) => InlineReply | void;
150
-
151
- declare interface Router {
152
- get<Path extends string>(path: Path, ...middle: Middleware<Path>[]): this;
153
- head<Path extends string>(path: Path, ...middle: Middleware<Path>[]): this;
154
- post<Path extends string>(path: Path, ...middle: Middleware<Path>[]): this;
155
- put<Path extends string>(path: Path, ...middle: Middleware<Path>[]): this;
156
- patch<Path extends string>(path: Path, ...middle: Middleware<Path>[]): this;
157
- del<Path extends string>(path: Path, ...middle: Middleware<Path>[]): this;
158
- options<Path extends string>(path: Path, ...middle: Middleware<Path>[]): this;
159
- }
160
-
161
- declare interface Server {
162
- /**
163
- * Launch the server with the optional configuration:
164
- *
165
- * ```js
166
- * export default server({
167
- * port: 3000,
168
- * public: './public',
169
- * store: kv(new Map()),
170
- * })
171
- * ```
172
- *
173
- * **[→ Getting Started](https://react-test.dev/documentation#attr)**
174
- *
175
- * **[→ Options Docs](https://react-test.dev/documentation#attr)**
176
- */
177
- (options?: ServerOptions): this;
178
-
179
- socket(path: string, ...middle: Middleware[]): this;
180
-
181
- get<Path extends string>(path: Path, ...middle: Middleware<Path>[]): this;
182
- head<Path extends string>(path: Path, ...middle: Middleware<Path>[]): this;
183
- post<Path extends string>(path: Path, ...middle: Middleware<Path>[]): this;
184
- put<Path extends string>(path: Path, ...middle: Middleware<Path>[]): this;
185
- patch<Path extends string>(path: Path, ...middle: Middleware<Path>[]): this;
186
- del<Path extends string>(path: Path, ...middle: Middleware<Path>[]): this;
187
- options<Path extends string>(path: Path, ...middle: Middleware<Path>[]): this;
188
-
189
- use(...middle: Middleware[]): this;
190
- router(router: Router): this;
191
- }
192
-
193
- type headers = (obj?: Headers) => any;
194
-
195
- declare const server: Server;
196
- export const router: Router;
197
- export const headers: headers;
198
- export default server;
package/src/index.js DELETED
@@ -1,250 +0,0 @@
1
- import "./polyfill.js";
2
- import "./errors/index.js";
3
-
4
- import createNodeContext from "./context/node.js";
5
- import createWinterContext from "./context/winter.js";
6
- import {
7
- config,
8
- createWebsocket,
9
- getMachine,
10
- handleRequest,
11
- iterate,
12
- parseHeaders,
13
- } from "./helpers/index.js";
14
-
15
- import { assets, auth, timer, openapi } from "./middle/index.js";
16
-
17
- // Export the reply helpers
18
- export * from "./reply.js";
19
-
20
- export { default as ServerError } from "./ServerError.js";
21
-
22
- // Allow to create a sub-router
23
- export { default as router } from "./router.js";
24
-
25
- export default function server(options = {}) {
26
- // Make it so that the exported one is a prototype of function()
27
- if (!(this instanceof server)) {
28
- return new server(options).self();
29
- }
30
-
31
- // Keep a copy of the options in the instance
32
- this.opts = config(options);
33
- this.platform = getMachine();
34
-
35
- // Skip "forbidden methods" https://fetch.spec.whatwg.org/#concept-method
36
- this.handlers = {
37
- socket: [],
38
- get: [],
39
- head: [],
40
- post: [],
41
- put: [],
42
- patch: [],
43
- delete: [],
44
- options: [],
45
- };
46
-
47
- // Keep a reference of the currently connected sockets
48
- this.sockets = [];
49
-
50
- // Note: required by Bun
51
- this.websocket = createWebsocket(this.sockets, this.handlers);
52
-
53
- // Initialize it right away for Node.js
54
- if (this.platform.runtime === "node") {
55
- this.node();
56
- }
57
-
58
- this.use(timer);
59
- this.use(assets);
60
- if (this.opts.openapi) {
61
- const path = this.opts.openapi.path || "/docs";
62
- this.get(path, openapi);
63
- }
64
- if (this.opts.auth) {
65
- this.use(auth({ options: this.opts, app: this }));
66
- }
67
- }
68
-
69
- server.prototype.self = function () {
70
- const cb = this.callback.bind(this);
71
- const proto = Object.getPrototypeOf(this);
72
- for (const key in { ...proto, ...this }) {
73
- if (typeof this[key] === "function") {
74
- cb[key] = this[key].bind(this);
75
- } else {
76
- cb[key] = this[key];
77
- }
78
- }
79
- return cb;
80
- };
81
-
82
- // #region Runtimes
83
- // Node.js
84
- server.prototype.node = async function () {
85
- const http = await import("node:http");
86
- http
87
- .createServer(async (request, response) => {
88
- try {
89
- const ctx = await createNodeContext(request, this);
90
- const out = await handleRequest(this.handlers, ctx);
91
-
92
- response.writeHead(out.status || 200, parseHeaders(out.headers));
93
- if (out.body instanceof ReadableStream) {
94
- await iterate(out.body, (chunk) => response.write(chunk));
95
- } else {
96
- response.write(out.body || "");
97
- }
98
- response.end();
99
- } catch (error) {
100
- response.writeHead(error.status || 500);
101
- response.write(error.message || "");
102
- response.end();
103
- }
104
- })
105
- .listen(this.opts.port);
106
- };
107
-
108
- // Netlify
109
- server.prototype.callback = async function (request, context) {
110
- // Consider simply renaming to "ctx.next()"
111
- request.context = context;
112
- try {
113
- if (typeof Netlify === "undefined") {
114
- throw new Error("Netlify doesn't exist");
115
- }
116
- const ctx = await createWinterContext(request, this);
117
- return await handleRequest(this.handlers, ctx);
118
- } catch (error) {
119
- return new Response(error.message, { status: error.status || 500 });
120
- }
121
- };
122
-
123
- // WinterCG, Bun, Cloudflare Workers
124
- server.prototype.fetch = async function (request, env) {
125
- if (env?.upgrade(request)) return;
126
- Object.assign(globalThis.env, env); // Extend env with the passed vars
127
-
128
- let ctx;
129
- let res;
130
- let error;
131
- try {
132
- ctx = await createWinterContext(request, this);
133
- res = await handleRequest(this.handlers, ctx);
134
- } catch (err) {
135
- error = err;
136
- res = new Response(error.message, { status: error.status || 500 });
137
- }
138
- ctx?.unstableFire("finish", { ...ctx, error, res, end: performance.now() });
139
- return res;
140
- };
141
-
142
- // #region HTTP methods
143
- // INTERNAL
144
- server.prototype.handle = function (method, path, ...middleware) {
145
- // Do not try to optimize, we NEED the method to remain '*' here so that
146
- // it doesn't auto-finish
147
- if (method === "*") {
148
- for (const m in this.handlers) {
149
- this.handlers[m].push([method, path, ...middleware]);
150
- }
151
- } else {
152
- this.handlers[method].push([method, path, ...middleware]);
153
- }
154
-
155
- return this.self();
156
- };
157
-
158
- server.prototype.socket = function (path, ...middleware) {
159
- return this.handle("socket", path, ...middleware);
160
- };
161
-
162
- server.prototype.get = function (path, ...middleware) {
163
- return this.handle("get", path, ...middleware);
164
- };
165
-
166
- server.prototype.head = function (path, ...middleware) {
167
- return this.handle("head", path, ...middleware);
168
- };
169
-
170
- server.prototype.post = function (path, ...middleware) {
171
- return this.handle("post", path, ...middleware);
172
- };
173
-
174
- server.prototype.put = function (path, ...middleware) {
175
- return this.handle("put", path, ...middleware);
176
- };
177
-
178
- server.prototype.patch = function (path, ...middleware) {
179
- return this.handle("patch", path, ...middleware);
180
- };
181
-
182
- server.prototype.del = function (path, ...middleware) {
183
- return this.handle("delete", path, ...middleware);
184
- };
185
-
186
- server.prototype.options = function (path, ...middleware) {
187
- return this.handle("options", path, ...middleware);
188
- };
189
-
190
- server.prototype.use = function (...middleware) {
191
- if (typeof middleware[0] === "string") {
192
- return this.handle("*", ...middleware);
193
- }
194
- return this.handle("*", "*", ...middleware);
195
- };
196
-
197
- // Unwind the children routers into the main router
198
- server.prototype.router = function (basePath, router) {
199
- basePath = `/${basePath}/`.replace(/^\/+/, "/").replace(/\/+$/, "/");
200
- for (const m in router.handlers) {
201
- for (const [method, path, ...callbacks] of router.handlers[m]) {
202
- this.handle(method, basePath + path.replace(/^\//, ""), ...callbacks);
203
- }
204
- }
205
- return this.self();
206
- };
207
-
208
- // #region Testing helper
209
- server.prototype.test = function () {
210
- let cookie = "";
211
- const fetch = async (path, options = {}) => {
212
- if (!options.headers) options.headers = {};
213
- if (options.body && typeof options.body !== "string") {
214
- options.headers["content-type"] = "application/json";
215
- options.body = JSON.stringify(options.body);
216
- }
217
- if (cookie && !options.headers.cookie) {
218
- options.headers.cookie = cookie;
219
- }
220
- const res = await this.fetch(
221
- new Request(`http://localhost:3000${path}`, options),
222
- );
223
-
224
- const headers = parseHeaders(res.headers);
225
- let body;
226
- if (headers["set-cookie"]) {
227
- // TODO: this should really be a smart merge of the 2
228
- cookie = headers["set-cookie"];
229
- }
230
- if (headers["content-type"]?.includes("application/json")) {
231
- body = await res.json();
232
- } else {
233
- body = await res.text();
234
- }
235
- return { status: res.status, headers, body };
236
- };
237
- return {
238
- app: this,
239
- get: (path, options) => fetch(path, { method: "get", ...options }),
240
- head: (path, options) => fetch(path, { method: "head", ...options }),
241
- post: (path, body, options) =>
242
- fetch(path, { method: "post", body, ...options }),
243
- put: (path, body, options) =>
244
- fetch(path, { method: "put", body, ...options }),
245
- patch: (path, body, options) =>
246
- fetch(path, { method: "patch", body, ...options }),
247
- delete: (path, options) => fetch(path, { method: "delete", ...options }),
248
- options: (path, options) => fetch(path, { method: "options", ...options }),
249
- };
250
- };
package/src/index.test.js DELETED
@@ -1,87 +0,0 @@
1
- import "./test/toSucceed.js";
2
-
3
- import server, { status } from "./index.js";
4
-
5
- describe("exports", () => {
6
- it("exports as a function", () => {
7
- expect(typeof server()).toBe("function");
8
- });
9
-
10
- it("nested is also a function", () => {
11
- expect(typeof server().get("/", () => {})).toBe("function");
12
- });
13
-
14
- it("export has a fetch", () => {
15
- expect(typeof server().fetch).toBe("function");
16
- expect(typeof server().get().fetch).toBe("function");
17
- });
18
-
19
- it("export has the basic methods", () => {
20
- expect(typeof server().get).toBe("function");
21
- expect(typeof server().post).toBe("function");
22
- expect(typeof server().use).toBe("function");
23
- expect(typeof server().router).toBe("function");
24
- });
25
-
26
- it("export has the basic nested methods", () => {
27
- expect(typeof server().get().get).toBe("function");
28
- expect(typeof server().post().post).toBe("function");
29
- expect(typeof server().use().use).toBe("function");
30
- expect(typeof server().get().router).toBe("function");
31
- });
32
-
33
- it("nested is also a function", () => {
34
- expect(typeof server().get("/", () => {}).fetch).toBe("function");
35
- });
36
- });
37
-
38
- describe("return different types", () => {
39
- const api = server()
40
- .get("/", () => "Hello world")
41
- .get("/text", () => "Hello world")
42
- .get("/array", () => ["Hello world"])
43
- .get("/object", () => ({ hello: "world" }))
44
- .get("/status", () => 201)
45
- .test();
46
-
47
- it("can get the plain text", async () => {
48
- const { body } = await api.get("/text");
49
- expect(body).toBe("Hello world");
50
- });
51
-
52
- it("can get the array", async () => {
53
- const { body } = await api.get("/array");
54
- expect(body).toEqual(["Hello world"]);
55
- });
56
-
57
- it("can get the object", async () => {
58
- const req = await api.get("/object");
59
- expect(req).toSucceed({ hello: "world" });
60
- });
61
-
62
- it("can get the status", async () => {
63
- const req = await api.get("/status");
64
- expect(req).toSucceed();
65
- expect(req.status).toBe(201);
66
- });
67
- });
68
-
69
- describe("simple post works", () => {
70
- const api = server()
71
- .post("/", (ctx) => status(201).send(ctx.body))
72
- .test();
73
-
74
- it("can post new data", async () => {
75
- const { body, status, headers } = await api.post("/", "New Data");
76
- expect(status).toBe(201);
77
- expect(body).toBe("New Data");
78
- expect(headers["content-type"]).toBe("text/plain");
79
- });
80
-
81
- it("will return JSON", async () => {
82
- const { body, status, headers } = await api.post("/", { hello: "world" });
83
- expect(status).toBe(201);
84
- expect(body).toEqual({ hello: "world" });
85
- expect(headers["content-type"]).toBe("application/json");
86
- });
87
- });
@@ -1,28 +0,0 @@
1
- import server, { headers, router } from ".";
2
-
3
- const users = router
4
- .post("/users", (ctx) => {
5
- console.log(ctx.url.pathname);
6
- console.log(ctx.url.query);
7
- console.log(ctx.url.params); // No .id
8
- })
9
- .get("/users/:id?", (ctx) => {
10
- console.log(ctx.url.params.id);
11
- })
12
- .del("/users/:id", (ctx) => {
13
- console.log(ctx.url.params.id);
14
- });
15
-
16
- server()
17
- .get("/", (ctx) => {
18
- console.log(ctx.method);
19
- console.log(ctx.url);
20
- console.log(ctx.headers);
21
- console.log(ctx.cookies);
22
- console.log(ctx.body);
23
- return headers();
24
- })
25
- .router(users)
26
- .post("/", () => {
27
- return 201;
28
- });
@@ -1,17 +0,0 @@
1
- import { type } from "../reply.js";
2
-
3
- export default async function assets(ctx) {
4
- if (!ctx.options.public) return;
5
- if (ctx.method !== "get") return;
6
- // The homepage _cannot_ be a file by definition. We could consider sending
7
- // `index.html`, but that's easy with `.get('/', () => file('index.html'))
8
- if (ctx.url.pathname === "/") return;
9
- try {
10
- // TODO: streaming
11
- const asset = await ctx.options.public.read(ctx.url.pathname, null);
12
- if (!asset) return;
13
- return type(ctx.url.pathname.split(".").pop()).send(asset);
14
- } catch (error) {
15
- // NO-OP; if there's no file, keep going the normal flow
16
- }
17
- }