@server/next 0.12.1 → 0.15.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/index.js DELETED
@@ -1,515 +0,0 @@
1
- var params = (query, path) => {
2
- // They are different and there's no matching in the query
3
- if (!/\:/.test(query) && query !== path) return;
4
-
5
- // If one fails, fail it all
6
- return (
7
- query.split("/").reduce((params, part, i) => {
8
- if (!params) return;
9
- const value = path.split("/")[i];
10
-
11
- // If there's no param in this segment, value has to match exactly
12
- if (!/^\:/.test(part)) return part === value ? params : false;
13
-
14
- const name = part.replace(/^\:/, "");
15
- if (!value) return;
16
- params[name] = value;
17
- return params;
18
- }, {}) || false
19
- );
20
- };
21
-
22
- // Put an undetermined number of callbacks together
23
- // Stops when one of them returns something
24
- var reduce = (...cbs) => {
25
- const handlers = cbs.flat(Infinity);
26
-
27
- return async ctx => {
28
- try {
29
- for (let cb of handlers) {
30
- const data = await cb(ctx);
31
- if (data) return data;
32
- }
33
- } catch (error) {
34
- return error;
35
- }
36
- };
37
- };
38
-
39
- // Normalize the reply to return always an object in the same format
40
- const cors = {
41
- "Access-Control-Allow-Origin": "*",
42
- "Access-Control-Allow-Headers":
43
- "Authorization, Origin, X-Requested-With, Content-Type, Accept",
44
- "Access-Control-Allow-Methods": "GET, PUT, PATCH, POST, DELETE, HEAD"
45
- };
46
-
47
- // https://nodejs.org/dist/latest-v12.x/docs/api/http.html#http_request_setheader_name_value
48
- // "Use an array of strings here to send multiple headers with the same name"
49
- const generateCookies = cookies => {
50
- return Object.entries(cookies).map(p => p.join("="));
51
- };
52
-
53
- var reply = async (handler, ctx) => {
54
- const data = await handler(ctx);
55
- const headers = {};
56
- if (ctx.options.cors === true) {
57
- for (let key in cors) {
58
- headers[key] = cors[key];
59
- }
60
- // Quick reply for the OPTIONS CORS
61
- if (ctx.method === "OPTIONS") {
62
- return { body: "", headers, status: 200 };
63
- }
64
- }
65
-
66
- // Did no throw, but did not resolve === not found
67
- if (!data) return { body: "Not found", headers, status: 404 };
68
-
69
- // The function means the hanlder knows what it's doing and wants a raw reply
70
- if (typeof data === "function") {
71
- const reply = await data(ctx);
72
- if (reply.cookies) {
73
- headers["set-cookie"] = generateCookies(reply.cookies);
74
- }
75
- return { ...reply, status: 200, headers: { ...reply.headers, ...headers } };
76
- }
77
-
78
- // A plain string response
79
- if (typeof data === "string") return { body: data, headers, status: 200 };
80
-
81
- // A status number response
82
- if (typeof data === "number") return { body: "", headers, status: data };
83
-
84
- // Most basic of error handling, anything higher level should be on user code
85
- if (data instanceof Error) {
86
- return { status: data.status || 500, headers, body: data.message };
87
- }
88
-
89
- // Treat it as a plain object
90
- return {
91
- body: JSON.stringify(data),
92
- status: data.status || 200,
93
- headers: { ...headers, "content-type": "application/json" }
94
- };
95
- };
96
-
97
- // Node native body parser
98
- const parseBody = async req => {
99
- return new Promise((done, fail) => {
100
- const type = req.headers["content-type"];
101
- const parser = /application\/json/.test(type)
102
- ? data => JSON.parse(data)
103
- : data => data;
104
- const data = [];
105
- req
106
- .on("data", chunk => {
107
- data.push(chunk);
108
- })
109
- .on("end", () => {
110
- const raw = Buffer.concat(data).toString();
111
- try {
112
- done(parser(raw));
113
- } catch (error) {
114
- fail(error);
115
- }
116
- })
117
- .on("error", fail);
118
- });
119
- };
120
-
121
- // Cloudflare body parser as https://developers.cloudflare.com/workers/templates/snippets/post_data/
122
- async function readRequestBody(request) {
123
- const { headers } = request;
124
- const contentType = headers.get("content-type") || "text/html";
125
- if (contentType.includes("application/json")) {
126
- const body = await request.json();
127
- return JSON.stringify(body);
128
- } else if (contentType.includes("application/text")) {
129
- const body = await request.text();
130
- return body;
131
- } else if (contentType.includes("text/html")) {
132
- const body = await request.text();
133
- return body;
134
- } else if (contentType.includes("form")) {
135
- const formData = await request.formData();
136
- let body = {};
137
- for (let entry of formData.entries()) {
138
- body[entry[0]] = entry[1];
139
- }
140
- return JSON.stringify(body);
141
- } else {
142
- let myBlob = await request.blob();
143
- var objectURL = URL.createObjectURL(myBlob);
144
- return objectURL;
145
- }
146
- }
147
-
148
- var bodyParser = async ctx => {
149
- // No parsing for now
150
- if (!ctx.req) return;
151
-
152
- // Parsing it out of the request's text() method
153
- if (ctx.req.text) {
154
- ctx.body = await readRequestBody(ctx.req);
155
- return;
156
- }
157
- ctx.body = await parseBody(ctx.req);
158
- };
159
-
160
- const decode = str => {
161
- try {
162
- return decodeURIComponent(str).catch(err => str);
163
- } catch (e) {
164
- return str;
165
- }
166
- };
167
-
168
- // Extracted originally from npm's "cookie"
169
- const parse = str => {
170
- if (typeof str !== "string") {
171
- throw new TypeError("argument str must be a string");
172
- }
173
-
174
- return str.split(/; */).reduce((cookies, pair) => {
175
- const eq_idx = pair.indexOf("=");
176
-
177
- // skip things that don't look like key=value
178
- if (eq_idx < 0) return cookies;
179
-
180
- const key = pair.substr(0, eq_idx).trim();
181
- const val = pair.substr(eq_idx + 1).trim();
182
-
183
- // unquote any quoted value
184
- if ('"' == val[0]) {
185
- val = val.slice(1, -1);
186
- }
187
-
188
- // only assign once; the first time
189
- if (undefined == cookies[key]) {
190
- cookies[key] = decode(val);
191
- }
192
- return cookies;
193
- }, {});
194
- };
195
-
196
- var cookieParser = ctx => {
197
- ctx.cookies = {};
198
- if (!ctx.headers.cookie) return;
199
- ctx.cookies = parse(ctx.headers.cookie);
200
- };
201
-
202
- const decode$1 = decodeURIComponent;
203
-
204
- // Parse the query from the url (without the `?`)
205
- const parseQuery = (query = "") => {
206
- return query
207
- .replace(/^\?/, "")
208
- .split("&")
209
- .filter(Boolean)
210
- .map(p => p.split("="))
211
- .reduce((all, [key, val]) => ({ ...all, [decode$1(key)]: decode$1(val) }), {});
212
- };
213
-
214
- // Available in Node globally since 10.0.0
215
- // https://nodejs.org/api/globals.html#globals_url
216
- var urlParser = ctx => {
217
- const url = new URL(ctx.url);
218
- ctx.protocol = url.protocol;
219
- ctx.host = url.host;
220
- ctx.port = url.port;
221
- ctx.hostname = url.hostname;
222
- ctx.password = url.password;
223
- ctx.username = url.username;
224
- ctx.origin = url.origin;
225
- ctx.path = url.pathname;
226
- ctx.query = parseQuery(url.search);
227
- };
228
-
229
- var middle = [urlParser, bodyParser, cookieParser];
230
-
231
- const runtime = "node";
232
-
233
- const getUrl = ({ protocol = "http", headers, url = "/" }) => {
234
- return protocol + "://" + headers["host"] + url;
235
- };
236
-
237
- // https://stackoverflow.com/a/19524949/938236
238
- const getIp = req => {
239
- return (
240
- (req.headers["x-forwarded-for"] || "").split(",").pop() ||
241
- req.connection.remoteAddress ||
242
- req.socket.remoteAddress ||
243
- req.connection.socket.remoteAddress
244
- );
245
- };
246
-
247
- // Launch the server for the Node.js environment
248
- var node = async (handler, options = {}) => {
249
- // This code runs ONE time on the first cold start, and we know that it runs
250
- // in the Node.js environment. So we can import Node.js libraries here safely
251
- const [http, zlib] = await Promise.all([import('http'), import('zlib')]);
252
-
253
- const compress = (data, headers) => {
254
- // Don't compress it if it's tiny
255
- if (data.length < 1000) {
256
- return data;
257
- }
258
- headers["Content-Encoding"] = "gzip";
259
- return new Promise((done, fail) => {
260
- const buffer = Buffer.from(data || "", "utf-8");
261
- zlib.gzip(buffer, (error, result) => {
262
- if (error) return fail(error);
263
- return done(result);
264
- });
265
- });
266
- };
267
-
268
- const server = http.createServer(async (req, res) => {
269
- // Handle each of the API calls here:
270
- const { status = 200, body = "", headers = {} } = await handler({
271
- url: getUrl(req),
272
- method: req.method,
273
- headers: req.headers,
274
- ip: getIp(req),
275
- runtime,
276
- req
277
- });
278
-
279
- res.statusCode = status;
280
- const compressed = await compress(body, headers);
281
- for (let key in headers) {
282
- // https://nodejs.org/dist/latest-v12.x/docs/api/http.html#http_request_setheader_name_value
283
- // "Use an array of strings here to send multiple headers with the same name"
284
- res.setHeader(key, headers[key]);
285
- }
286
-
287
- res.end(compressed);
288
- });
289
-
290
- return new Promise((resolve, reject) => {
291
- server.listen(options.port, error => {
292
- if (error) reject(error);
293
- resolve({ options, handler, runtime, close: () => server.close() });
294
- });
295
- });
296
- };
297
-
298
- const runtime$1 = "cloudflare";
299
-
300
- const getUrl$1 = ({ url }) => decodeURI(url);
301
-
302
- const getIp$1 = req => req.headers.get("CF-Connecting-IP");
303
-
304
- // At least one header has to be read first so that .entries() works
305
- const getHeaders = ({ headers }) => {
306
- const plain = {};
307
- for (let entry of headers.entries()) {
308
- headers[entry[0]] = entry[1];
309
- }
310
- return plain;
311
- };
312
-
313
- // Launch the server in a Cloudflare Worker
314
- var cloudflare = (handler, options = {}) => {
315
- addEventListener("fetch", e => {
316
- const response = handler({
317
- url: getUrl$1(e.request),
318
- method: e.request.method,
319
- headers: getHeaders(e.request),
320
- ip: getIp$1(e.request),
321
- runtime: runtime$1,
322
- req: e.request
323
- }).then(({ status, body, headers }) => {
324
- return new Response(body, { status, headers });
325
- });
326
- return e.respondWith(response);
327
- });
328
- return Promise.resolve({ options, handler, runtime: runtime$1, close: () => {} });
329
- };
330
-
331
- // Loosely find which one is the correct runtime through ducktyping
332
- var getEngine = () => {
333
- if (typeof addEventListener !== "undefined" && typeof fetch !== "undefined") {
334
- return cloudflare;
335
- }
336
-
337
- // It is Node.js by default
338
- return node;
339
- };
340
-
341
- var index = (path, ...cbs) => {
342
- // Accept a path first and then a list of callbacks
343
- if (typeof path !== "string") {
344
- cbs.unshift(path);
345
- path = "*";
346
- }
347
- const handler = reduce(cbs);
348
-
349
- return ctx => {
350
- if (path === "*") return handler(ctx);
351
-
352
- // Make sure the URL matches
353
- ctx.params = params(path, ctx.path);
354
- if (!ctx.params) return;
355
- return handler(ctx);
356
- };
357
- };
358
-
359
- var index$1 = (path, ...cbs) => {
360
- // Accept a path first and then a list of callbacks
361
- if (typeof path !== "string") {
362
- cbs.unshift(path);
363
- path = "*";
364
- }
365
- const handler = reduce(cbs);
366
-
367
- return ctx => {
368
- if (ctx.method !== "GET") return;
369
- if (path === "*") return handler(ctx);
370
-
371
- // Make sure the URL matches
372
- ctx.params = params(path, ctx.path);
373
- if (!ctx.params) return;
374
- return handler(ctx);
375
- };
376
- };
377
-
378
- var index$2 = (path, ...cbs) => {
379
- // Accept a path first and then a list of callbacks
380
- if (typeof path !== "string") {
381
- cbs.unshift(path);
382
- path = "*";
383
- }
384
- const handler = reduce(cbs);
385
-
386
- return ctx => {
387
- if (ctx.method !== "POST") return;
388
- if (path === "*") return handler(ctx);
389
-
390
- // Make sure the URL matches
391
- ctx.params = params(path, ctx.path);
392
- if (!ctx.params) return;
393
- return handler(ctx);
394
- };
395
- };
396
-
397
- var index$3 = (path, ...cbs) => {
398
- // Accept a path first and then a list of callbacks
399
- if (typeof path !== "string") {
400
- cbs.unshift(path);
401
- path = "*";
402
- }
403
- const handler = reduce(cbs);
404
-
405
- return ctx => {
406
- if (ctx.method !== "PUT") return;
407
- if (path === "*") return handler(ctx);
408
-
409
- // Make sure the URL matches
410
- ctx.params = params(path, ctx.path);
411
- if (!ctx.params) return;
412
- return handler(ctx);
413
- };
414
- };
415
-
416
- var index$4 = (path, ...cbs) => {
417
- // Accept a path first and then a list of callbacks
418
- if (typeof path !== "string") {
419
- cbs.unshift(path);
420
- path = "*";
421
- }
422
- const handler = reduce(cbs);
423
-
424
- return ctx => {
425
- if (ctx.method !== "PATCH") return;
426
- if (path === "*") return handler(ctx);
427
-
428
- // Make sure the URL matches
429
- ctx.params = params(path, ctx.path);
430
- if (!ctx.params) return;
431
- return handler(ctx);
432
- };
433
- };
434
-
435
- var index$5 = (path, ...cbs) => {
436
- // Accept a path first and then a list of callbacks
437
- if (typeof path !== "string") {
438
- cbs.unshift(path);
439
- path = "*";
440
- }
441
- const handler = reduce(cbs);
442
-
443
- return ctx => {
444
- if (ctx.method !== "DELETE") return;
445
- if (path === "*") return handler(ctx);
446
-
447
- // Make sure the URL matches
448
- ctx.params = params(path, ctx.path);
449
- if (!ctx.params) return;
450
- return handler(ctx);
451
- };
452
- };
453
-
454
- var index$6 = (path, ...cbs) => {
455
- // Accept a path first and then a list of callbacks
456
- if (typeof path !== "string") {
457
- cbs.unshift(path);
458
- path = "*";
459
- }
460
- const handler = reduce(cbs);
461
-
462
- return ctx => {
463
- if (ctx.method !== "HEAD") return;
464
- if (path === "*") return handler(ctx);
465
-
466
- // Make sure the URL matches
467
- ctx.params = params(path, ctx.path);
468
- if (!ctx.params) return;
469
- return handler(ctx);
470
- };
471
- };
472
-
473
- var index$7 = (path, ...cbs) => {
474
- // Accept a path first and then a list of callbacks
475
- if (typeof path !== "string") {
476
- cbs.unshift(path);
477
- path = "*";
478
- }
479
- const handler = reduce(cbs);
480
-
481
- return ctx => {
482
- if (ctx.method !== "OPTIONS") return;
483
- if (path === "*") return handler(ctx);
484
-
485
- // Make sure the URL matches
486
- ctx.params = params(path, ctx.path);
487
- if (!ctx.params) return;
488
- return handler(ctx);
489
- };
490
- };
491
-
492
- // Some other, non-HTTP methods but routers nonetheless
493
- // export { default as socket } from "./socket";
494
- // export { default as domain } from "./domain";
495
-
496
- // The main function that runs the whole thing
497
- var index$8 = async (options = {}, ...middleware) => {
498
- if (typeof options === "function") {
499
- middleware.unshift(options);
500
- options = { port: 3000 };
501
- }
502
- options.engine = options.engine || getEngine();
503
-
504
- const addOptions = ctx => {
505
- ctx.options = options;
506
- };
507
-
508
- // Generate a single callback with all the middleware
509
- const callback = reduce(addOptions, middle, middleware);
510
-
511
- return options.engine(ctx => reply(callback, ctx), options);
512
- };
513
-
514
- export default index$8;
515
- export { index as any, index$5 as del, index$1 as get, index$6 as head, index$7 as options, index$4 as patch, index$2 as post, index$3 as put };