@kaito-http/core 2.3.9 → 2.5.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.
@@ -2,35 +2,78 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var http = require('http');
6
- var fmw = require('find-my-way');
7
- var tls = require('tls');
5
+ var node_tls = require('node:tls');
8
6
  var contentType = require('content-type');
9
7
  var getRawBody = require('raw-body');
8
+ var cookie = require('cookie');
9
+ var fmw = require('find-my-way');
10
+ var http = require('node:http');
10
11
 
11
12
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
12
13
 
13
14
  function _interopNamespace(e) {
14
- if (e && e.__esModule) return e;
15
- var n = Object.create(null);
16
- if (e) {
17
- Object.keys(e).forEach(function (k) {
18
- if (k !== 'default') {
19
- var d = Object.getOwnPropertyDescriptor(e, k);
20
- Object.defineProperty(n, k, d.get ? d : {
21
- enumerable: true,
22
- get: function () { return e[k]; }
23
- });
24
- }
25
- });
26
- }
27
- n["default"] = e;
28
- return Object.freeze(n);
15
+ if (e && e.__esModule) return e;
16
+ var n = Object.create(null);
17
+ if (e) {
18
+ Object.keys(e).forEach(function (k) {
19
+ if (k !== 'default') {
20
+ var d = Object.getOwnPropertyDescriptor(e, k);
21
+ Object.defineProperty(n, k, d.get ? d : {
22
+ enumerable: true,
23
+ get: function () { return e[k]; }
24
+ });
25
+ }
26
+ });
27
+ }
28
+ n["default"] = e;
29
+ return Object.freeze(n);
29
30
  }
30
31
 
31
- var http__namespace = /*#__PURE__*/_interopNamespace(http);
32
- var fmw__default = /*#__PURE__*/_interopDefault(fmw);
33
32
  var getRawBody__default = /*#__PURE__*/_interopDefault(getRawBody);
33
+ var fmw__default = /*#__PURE__*/_interopDefault(fmw);
34
+ var http__namespace = /*#__PURE__*/_interopNamespace(http);
35
+
36
+ class WrappedError extends Error {
37
+ static maybe(maybeError) {
38
+ if (maybeError instanceof Error) {
39
+ return maybeError;
40
+ }
41
+
42
+ return WrappedError.from(maybeError);
43
+ }
44
+
45
+ static from(data) {
46
+ return new WrappedError(data);
47
+ }
48
+
49
+ constructor(data) {
50
+ super('Something was thrown, but it was not an instance of Error, so a WrappedError was created.');
51
+ this.data = data;
52
+ }
53
+
54
+ }
55
+ class KaitoError extends Error {
56
+ constructor(status, message) {
57
+ super(message);
58
+ this.status = status;
59
+ }
60
+
61
+ }
62
+
63
+ function _defineProperty(obj, key, value) {
64
+ if (key in obj) {
65
+ Object.defineProperty(obj, key, {
66
+ value: value,
67
+ enumerable: true,
68
+ configurable: true,
69
+ writable: true
70
+ });
71
+ } else {
72
+ obj[key] = value;
73
+ }
74
+
75
+ return obj;
76
+ }
34
77
 
35
78
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
36
79
  try {
@@ -68,118 +111,6 @@ function _asyncToGenerator(fn) {
68
111
  };
69
112
  }
70
113
 
71
- function createFMWServer(config) {
72
- var fmw = config.router.toFindMyWay(config);
73
- var server = http__namespace.createServer( /*#__PURE__*/function () {
74
- var _ref = _asyncToGenerator(function* (req, res) {
75
- for (var fn of (_config$before = config.before) !== null && _config$before !== void 0 ? _config$before : []) {
76
- var _config$before;
77
-
78
- // Disabled because we need these to run in order!
79
- // eslint-disable-next-line no-await-in-loop
80
- yield fn(req, res);
81
- }
82
-
83
- if (req.method === 'OPTIONS') {
84
- return;
85
- }
86
-
87
- fmw.lookup(req, res);
88
- });
89
-
90
- return function (_x, _x2) {
91
- return _ref.apply(this, arguments);
92
- };
93
- }());
94
- return {
95
- server,
96
- fmw
97
- };
98
- }
99
- function createServer(config) {
100
- return createFMWServer(config).server;
101
- }
102
-
103
- function _defineProperty(obj, key, value) {
104
- if (key in obj) {
105
- Object.defineProperty(obj, key, {
106
- value: value,
107
- enumerable: true,
108
- configurable: true,
109
- writable: true
110
- });
111
- } else {
112
- obj[key] = value;
113
- }
114
-
115
- return obj;
116
- }
117
-
118
- function ownKeys(object, enumerableOnly) {
119
- var keys = Object.keys(object);
120
-
121
- if (Object.getOwnPropertySymbols) {
122
- var symbols = Object.getOwnPropertySymbols(object);
123
-
124
- if (enumerableOnly) {
125
- symbols = symbols.filter(function (sym) {
126
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
127
- });
128
- }
129
-
130
- keys.push.apply(keys, symbols);
131
- }
132
-
133
- return keys;
134
- }
135
-
136
- function _objectSpread2(target) {
137
- for (var i = 1; i < arguments.length; i++) {
138
- var source = arguments[i] != null ? arguments[i] : {};
139
-
140
- if (i % 2) {
141
- ownKeys(Object(source), true).forEach(function (key) {
142
- _defineProperty(target, key, source[key]);
143
- });
144
- } else if (Object.getOwnPropertyDescriptors) {
145
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
146
- } else {
147
- ownKeys(Object(source)).forEach(function (key) {
148
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
149
- });
150
- }
151
- }
152
-
153
- return target;
154
- }
155
-
156
- class WrappedError extends Error {
157
- static maybe(maybeError) {
158
- if (maybeError instanceof Error) {
159
- return maybeError;
160
- }
161
-
162
- return WrappedError.from(maybeError);
163
- }
164
-
165
- static from(data) {
166
- return new WrappedError(data);
167
- }
168
-
169
- constructor(data) {
170
- super('Something was thrown, but it was not an instance of Error, so a WrappedError was created.');
171
- this.data = data;
172
- }
173
-
174
- }
175
- class KaitoError extends Error {
176
- constructor(status, message) {
177
- super(message);
178
- this.status = status;
179
- }
180
-
181
- }
182
-
183
114
  function createGetContext(callback) {
184
115
  return callback;
185
116
  }
@@ -222,6 +153,11 @@ function _getInput() {
222
153
 
223
154
  default:
224
155
  {
156
+ if (process.env.NODE_ENV === 'development') {
157
+ console.warn('[kaito] Unsupported content type:', type);
158
+ console.warn('[kaito] This message is only shown in development mode.');
159
+ }
160
+
225
161
  return null;
226
162
  }
227
163
  }
@@ -235,12 +171,21 @@ class KaitoRequest {
235
171
 
236
172
  this.raw = raw;
237
173
  }
174
+ /**
175
+ * The full URL of the request, including the protocol, hostname, and path.
176
+ * Note: does not include the query string or hash
177
+ */
178
+
238
179
 
239
180
  get fullURL() {
240
181
  var _this$raw$url;
241
182
 
242
183
  return "".concat(this.protocol, "://").concat(this.hostname).concat((_this$raw$url = this.raw.url) !== null && _this$raw$url !== void 0 ? _this$raw$url : '');
243
184
  }
185
+ /**
186
+ * A new URL instance for the full URL of the request.
187
+ */
188
+
244
189
 
245
190
  get url() {
246
191
  if (this._url) {
@@ -250,6 +195,10 @@ class KaitoRequest {
250
195
  this._url = new URL(this.fullURL);
251
196
  return this._url;
252
197
  }
198
+ /**
199
+ * The HTTP method of the request.
200
+ */
201
+
253
202
 
254
203
  get method() {
255
204
  if (!this.raw.method) {
@@ -258,18 +207,30 @@ class KaitoRequest {
258
207
 
259
208
  return this.raw.method;
260
209
  }
210
+ /**
211
+ * The protocol of the request, either `http` or `https`.
212
+ */
213
+
261
214
 
262
215
  get protocol() {
263
- if (this.raw.socket instanceof tls.TLSSocket) {
216
+ if (this.raw.socket instanceof node_tls.TLSSocket) {
264
217
  return this.raw.socket.encrypted ? 'https' : 'http';
265
218
  }
266
219
 
267
220
  return 'http';
268
221
  }
222
+ /**
223
+ * The request headers
224
+ */
225
+
269
226
 
270
227
  get headers() {
271
228
  return this.raw.headers;
272
229
  }
230
+ /**
231
+ * The hostname of the request.
232
+ */
233
+
273
234
 
274
235
  get hostname() {
275
236
  var _this$raw$headers$hos, _this$raw$headers$Au;
@@ -283,16 +244,48 @@ class KaitoResponse {
283
244
  constructor(raw) {
284
245
  this.raw = raw;
285
246
  }
247
+ /**
248
+ * Send a response
249
+ * @param key The key of the header
250
+ * @param value The value of the header
251
+ * @returns The response object
252
+ */
253
+
286
254
 
287
255
  header(key, value) {
288
256
  this.raw.setHeader(key, value);
289
257
  return this;
290
258
  }
259
+ /**
260
+ * Set the status code of the response
261
+ * @param code The status code
262
+ * @returns The response object
263
+ */
264
+
291
265
 
292
266
  status(code) {
293
267
  this.raw.statusCode = code;
294
268
  return this;
295
269
  }
270
+ /**
271
+ * Set a cookie
272
+ * @param name The name of the cookie
273
+ * @param value The value of the cookie
274
+ * @param options The options for the cookie
275
+ * @returns The response object
276
+ */
277
+
278
+
279
+ cookie(name, value, options) {
280
+ this.raw.setHeader('Set-Cookie', cookie.serialize(name, value, options));
281
+ return this;
282
+ }
283
+ /**
284
+ * Send a JSON APIResponse body
285
+ * @param data The data to send
286
+ * @returns The response object
287
+ */
288
+
296
289
 
297
290
  json(data) {
298
291
  var json = JSON.stringify(data);
@@ -304,21 +297,129 @@ class KaitoResponse {
304
297
 
305
298
  }
306
299
 
300
+ function ownKeys(object, enumerableOnly) {
301
+ var keys = Object.keys(object);
302
+
303
+ if (Object.getOwnPropertySymbols) {
304
+ var symbols = Object.getOwnPropertySymbols(object);
305
+
306
+ if (enumerableOnly) {
307
+ symbols = symbols.filter(function (sym) {
308
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
309
+ });
310
+ }
311
+
312
+ keys.push.apply(keys, symbols);
313
+ }
314
+
315
+ return keys;
316
+ }
317
+
318
+ function _objectSpread2(target) {
319
+ for (var i = 1; i < arguments.length; i++) {
320
+ var source = arguments[i] != null ? arguments[i] : {};
321
+
322
+ if (i % 2) {
323
+ ownKeys(Object(source), true).forEach(function (key) {
324
+ _defineProperty(target, key, source[key]);
325
+ });
326
+ } else if (Object.getOwnPropertyDescriptors) {
327
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
328
+ } else {
329
+ ownKeys(Object(source)).forEach(function (key) {
330
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
331
+ });
332
+ }
333
+ }
334
+
335
+ return target;
336
+ }
337
+
307
338
  class Router {
308
- static create() {
309
- return new Router({});
339
+ constructor(routes) {
340
+ _defineProperty(this, "add", route => new Router([...this.routes, route]));
341
+
342
+ _defineProperty(this, "merge", (pathPrefix, other) => {
343
+ var newRoutes = other.routes.map(route => _objectSpread2(_objectSpread2({}, route), {}, {
344
+ path: "".concat(pathPrefix).concat(route.path)
345
+ }));
346
+ return new Router([...this.routes, ...newRoutes]);
347
+ });
348
+
349
+ _defineProperty(this, "toFindMyWay", server => {
350
+ var instance = fmw__default["default"]({
351
+ ignoreTrailingSlash: true,
352
+
353
+ defaultRoute(req, serverResponse) {
354
+ return _asyncToGenerator(function* () {
355
+ var _req$url;
356
+
357
+ var res = new KaitoResponse(serverResponse);
358
+ var message = "Cannot ".concat(req.method, " ").concat((_req$url = req.url) !== null && _req$url !== void 0 ? _req$url : '/');
359
+ res.status(404).json({
360
+ success: false,
361
+ data: null,
362
+ message
363
+ });
364
+ return {
365
+ success: false,
366
+ data: {
367
+ status: 404,
368
+ message
369
+ }
370
+ };
371
+ })();
372
+ }
373
+
374
+ });
375
+
376
+ var _loop = function _loop(route) {
377
+ var handler = /*#__PURE__*/function () {
378
+ var _ref = _asyncToGenerator(function* (incomingMessage, serverResponse, params) {
379
+ var req = new KaitoRequest(incomingMessage);
380
+ var res = new KaitoResponse(serverResponse);
381
+ return Router.handle(server, route, {
382
+ params,
383
+ req,
384
+ res
385
+ });
386
+ });
387
+
388
+ return function handler(_x, _x2, _x3) {
389
+ return _ref.apply(this, arguments);
390
+ };
391
+ }();
392
+
393
+ if (route.method === '*') {
394
+ instance.all(route.path, handler);
395
+ return "continue";
396
+ }
397
+
398
+ instance.on(route.method, route.path, handler);
399
+ };
400
+
401
+ for (var route of this.routes) {
402
+ var _ret = _loop(route);
403
+
404
+ if (_ret === "continue") continue;
405
+ }
406
+
407
+ return instance;
408
+ });
409
+
410
+ this.routes = routes;
310
411
  }
311
412
 
312
- static handle(server, options) {
413
+ static handle(server, route, options) {
313
414
  return _asyncToGenerator(function* () {
314
415
  try {
315
- var _options$route$input$, _options$route$input;
416
+ var _route$input$parse, _route$input;
316
417
 
317
- var context = yield server.getContext(options.req, options.res);
418
+ var ctx = yield server.getContext(options.req, options.res);
318
419
  var body = yield getInput(options.req);
319
- var input = (_options$route$input$ = (_options$route$input = options.route.input) === null || _options$route$input === void 0 ? void 0 : _options$route$input.parse(body)) !== null && _options$route$input$ !== void 0 ? _options$route$input$ : undefined;
320
- var result = yield options.route.run({
321
- ctx: context,
420
+ var input = (_route$input$parse = (_route$input = route.input) === null || _route$input === void 0 ? void 0 : _route$input.parse(body)) !== null && _route$input$parse !== void 0 ? _route$input$parse : undefined;
421
+ var result = yield route.run({
422
+ ctx,
322
423
  input,
323
424
  params: options.params
324
425
  });
@@ -327,6 +428,10 @@ class Router {
327
428
  data: result,
328
429
  message: 'OK'
329
430
  });
431
+ return {
432
+ success: true,
433
+ data: result
434
+ };
330
435
  } catch (e) {
331
436
  var error = WrappedError.maybe(e);
332
437
 
@@ -355,163 +460,82 @@ class Router {
355
460
  data: null,
356
461
  message
357
462
  });
463
+ return {
464
+ success: false,
465
+ data: {
466
+ status,
467
+ message
468
+ }
469
+ };
358
470
  }
359
471
  })();
360
472
  }
361
473
 
362
- constructor(routes) {
363
- _defineProperty(this, 'acl', this.make('ACL'));
364
-
365
- _defineProperty(this, 'bind', this.make('BIND'));
366
-
367
- _defineProperty(this, 'checkout', this.make('CHECKOUT'));
368
-
369
- _defineProperty(this, 'connect', this.make('CONNECT'));
370
-
371
- _defineProperty(this, 'copy', this.make('COPY'));
372
-
373
- _defineProperty(this, 'delete', this.make('DELETE'));
374
-
375
- _defineProperty(this, 'get', this.make('GET'));
376
-
377
- _defineProperty(this, 'head', this.make('HEAD'));
378
-
379
- _defineProperty(this, 'link', this.make('LINK'));
380
-
381
- _defineProperty(this, 'lock', this.make('LOCK'));
382
-
383
- _defineProperty(this, 'm_search', this.make('M-SEARCH'));
384
-
385
- _defineProperty(this, 'mkactivity', this.make('MKACTIVITY'));
386
-
387
- _defineProperty(this, 'mkcalendar', this.make('MKCALENDAR'));
388
-
389
- _defineProperty(this, 'mkcol', this.make('MKCOL'));
390
-
391
- _defineProperty(this, 'move', this.make('MOVE'));
392
-
393
- _defineProperty(this, 'notify', this.make('NOTIFY'));
394
-
395
- _defineProperty(this, 'patch', this.make('PATCH'));
396
-
397
- _defineProperty(this, 'post', this.make('POST'));
398
-
399
- _defineProperty(this, 'propfind', this.make('PROPFIND'));
400
-
401
- _defineProperty(this, 'proppatch', this.make('PROPPATCH'));
402
-
403
- _defineProperty(this, 'purge', this.make('PURGE'));
404
-
405
- _defineProperty(this, 'put', this.make('PUT'));
406
-
407
- _defineProperty(this, 'rebind', this.make('REBIND'));
408
-
409
- _defineProperty(this, 'report', this.make('REPORT'));
410
-
411
- _defineProperty(this, 'search', this.make('SEARCH'));
474
+ }
412
475
 
413
- _defineProperty(this, 'source', this.make('SOURCE'));
476
+ _defineProperty(Router, "create", () => new Router([]));
414
477
 
415
- _defineProperty(this, 'subscribe', this.make('SUBSCRIBE'));
478
+ function createFMWServer(config) {
479
+ var _config$rawRoutes;
416
480
 
417
- _defineProperty(this, 'trace', this.make('TRACE'));
481
+ var fmw = config.router.toFindMyWay(config);
482
+ var rawRoutes = (_config$rawRoutes = config.rawRoutes) !== null && _config$rawRoutes !== void 0 ? _config$rawRoutes : {};
418
483
 
419
- _defineProperty(this, 'unbind', this.make('UNBIND'));
484
+ for (var method in rawRoutes) {
485
+ if (!Object.prototype.hasOwnProperty.call(rawRoutes, method)) {
486
+ continue;
487
+ }
420
488
 
421
- _defineProperty(this, 'unlink', this.make('UNLINK'));
489
+ var routes = rawRoutes[method];
422
490
 
423
- _defineProperty(this, 'unlock', this.make('UNLOCK'));
491
+ if (!routes || routes.length === 0) {
492
+ continue;
493
+ }
424
494
 
425
- _defineProperty(this, 'unsubscribe', this.make('UNSUBSCRIBE'));
495
+ for (var route of routes) {
496
+ if (method === '*') {
497
+ fmw.all(route.path, route.handler);
498
+ continue;
499
+ }
426
500
 
427
- this.routes = routes;
501
+ fmw[method.toLowerCase()](route.path, route.handler);
502
+ }
428
503
  }
429
504
 
430
- merge(prefix, router) {
431
- var newRoutes = Object.fromEntries(Object.entries(router.routes).map(_ref => {
432
- var [k, v] = _ref;
433
- return ["".concat(prefix).concat(k), v];
434
- }));
505
+ var server = http__namespace.createServer( /*#__PURE__*/function () {
506
+ var _ref = _asyncToGenerator(function* (req, res) {
507
+ var before;
435
508
 
436
- var merged = _objectSpread2(_objectSpread2({}, this.routes), newRoutes);
509
+ if (config.before) {
510
+ before = yield config.before(req, res);
511
+ } else {
512
+ before = null;
513
+ } // If the user has sent a response (e.g. replying to CORS), we don't want to do anything else.
437
514
 
438
- return this._copy(merged);
439
- }
440
515
 
441
- toFindMyWay(server) {
442
- var _this = this;
443
-
444
- var instance = fmw__default["default"]({
445
- ignoreTrailingSlash: true,
516
+ if (res.headersSent) {
517
+ return;
518
+ }
446
519
 
447
- defaultRoute(req, serverResponse) {
448
- var _req$url;
520
+ var result = yield fmw.lookup(req, res);
449
521
 
450
- var res = new KaitoResponse(serverResponse);
451
- res.status(404).json({
452
- success: false,
453
- data: null,
454
- message: "Cannot ".concat(req.method, " ").concat((_req$url = req.url) !== null && _req$url !== void 0 ? _req$url : '/')
455
- });
522
+ if ('after' in config && config.after) {
523
+ yield config.after(before, result);
456
524
  }
457
-
458
525
  });
459
- var paths = Object.keys(this.routes);
460
-
461
- var _loop = function _loop(path) {
462
- var route = _this.routes[path];
463
- instance.on(route.method, path, /*#__PURE__*/function () {
464
- var _ref2 = _asyncToGenerator(function* (incomingMessage, serverResponse, params) {
465
- var req = new KaitoRequest(incomingMessage);
466
- var res = new KaitoResponse(serverResponse);
467
- yield Router.handle(server, {
468
- route,
469
- params,
470
- req,
471
- res
472
- });
473
- });
474
-
475
- return function (_x, _x2, _x3) {
476
- return _ref2.apply(this, arguments);
477
- };
478
- }());
479
- };
480
-
481
- for (var path of paths) {
482
- _loop(path);
483
- }
484
-
485
- return instance;
486
- }
487
526
 
488
- _copy(routes) {
489
- return new Router(routes);
490
- }
491
-
492
- make(method) {
493
- return (path, route) => {
494
- var addedRoute = _objectSpread2(_objectSpread2({}, route), {}, {
495
- method
496
- }); // `as unknown` is required because otherwise
497
- // this type just gets massive and too slow,
498
- // so we have to write it out specifically
499
-
500
-
501
- var merged = _objectSpread2(_objectSpread2({}, this.routes), {}, {
502
- [path]: addedRoute
503
- });
504
-
505
- return this._copy(merged);
527
+ return function (_x, _x2) {
528
+ return _ref.apply(this, arguments);
506
529
  };
507
- }
508
-
530
+ }());
531
+ return {
532
+ server,
533
+ fmw
534
+ };
535
+ }
536
+ function createServer(config) {
537
+ return createFMWServer(config).server;
509
538
  }
510
- /**
511
- * @deprecated Please use Router#create instead
512
- */
513
-
514
- var createRouter = Router.create;
515
539
 
516
540
  exports.KaitoError = KaitoError;
517
541
  exports.KaitoRequest = KaitoRequest;
@@ -520,7 +544,6 @@ exports.Router = Router;
520
544
  exports.WrappedError = WrappedError;
521
545
  exports.createFMWServer = createFMWServer;
522
546
  exports.createGetContext = createGetContext;
523
- exports.createRouter = createRouter;
524
547
  exports.createServer = createServer;
525
548
  exports.getInput = getInput;
526
549
  exports.getLastEntryInMultiHeaderValue = getLastEntryInMultiHeaderValue;