@kaito-http/core 2.4.0 → 2.6.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,81 @@
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');
7
+ var node_stream = require('node:stream');
8
+ var consumers = require('node:stream/consumers');
9
9
  var getRawBody = require('raw-body');
10
+ var cookie = require('cookie');
11
+ var fmw = require('find-my-way');
12
+ var zod = require('zod');
13
+ var http = require('node:http');
10
14
 
11
15
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
12
16
 
13
17
  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);
18
+ if (e && e.__esModule) return e;
19
+ var n = Object.create(null);
20
+ if (e) {
21
+ Object.keys(e).forEach(function (k) {
22
+ if (k !== 'default') {
23
+ var d = Object.getOwnPropertyDescriptor(e, k);
24
+ Object.defineProperty(n, k, d.get ? d : {
25
+ enumerable: true,
26
+ get: function () { return e[k]; }
27
+ });
28
+ }
29
+ });
30
+ }
31
+ n["default"] = e;
32
+ return Object.freeze(n);
29
33
  }
30
34
 
31
- var http__namespace = /*#__PURE__*/_interopNamespace(http);
32
- var fmw__default = /*#__PURE__*/_interopDefault(fmw);
33
35
  var getRawBody__default = /*#__PURE__*/_interopDefault(getRawBody);
36
+ var fmw__default = /*#__PURE__*/_interopDefault(fmw);
37
+ var http__namespace = /*#__PURE__*/_interopNamespace(http);
38
+
39
+ class WrappedError extends Error {
40
+ static maybe(maybeError) {
41
+ if (maybeError instanceof Error) {
42
+ return maybeError;
43
+ }
44
+
45
+ return WrappedError.from(maybeError);
46
+ }
47
+
48
+ static from(data) {
49
+ return new WrappedError(data);
50
+ }
51
+
52
+ constructor(data) {
53
+ super('Something was thrown, but it was not an instance of Error, so a WrappedError was created.');
54
+ this.data = data;
55
+ }
56
+
57
+ }
58
+ class KaitoError extends Error {
59
+ constructor(status, message) {
60
+ super(message);
61
+ this.status = status;
62
+ }
63
+
64
+ }
65
+
66
+ function _defineProperty(obj, key, value) {
67
+ if (key in obj) {
68
+ Object.defineProperty(obj, key, {
69
+ value: value,
70
+ enumerable: true,
71
+ configurable: true,
72
+ writable: true
73
+ });
74
+ } else {
75
+ obj[key] = value;
76
+ }
77
+
78
+ return obj;
79
+ }
34
80
 
35
81
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
36
82
  try {
@@ -68,118 +114,6 @@ function _asyncToGenerator(fn) {
68
114
  };
69
115
  }
70
116
 
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
117
  function createGetContext(callback) {
184
118
  return callback;
185
119
  }
@@ -188,28 +122,17 @@ function getLastEntryInMultiHeaderValue(headerValue) {
188
122
  var lastIndex = normalized.lastIndexOf(',');
189
123
  return lastIndex === -1 ? normalized.trim() : normalized.slice(lastIndex + 1).trim();
190
124
  }
191
- function getInput(_x) {
192
- return _getInput.apply(this, arguments);
125
+ function getBody(_x) {
126
+ return _getBody.apply(this, arguments);
193
127
  }
194
128
 
195
- function _getInput() {
196
- _getInput = _asyncToGenerator(function* (req) {
197
- if (req.method === 'GET') {
198
- var input = req.url.searchParams.get('input');
199
-
200
- if (!input) {
201
- return null;
202
- }
203
-
204
- return JSON.parse(input);
205
- }
206
-
207
- var buffer = yield getRawBody__default["default"](req.raw);
208
-
129
+ function _getBody() {
130
+ _getBody = _asyncToGenerator(function* (req) {
209
131
  if (!req.headers['content-type']) {
210
132
  return null;
211
133
  }
212
134
 
135
+ var buffer = yield getRawBody__default["default"](req.raw);
213
136
  var {
214
137
  type
215
138
  } = contentType.parse(req.headers['content-type']);
@@ -217,16 +140,17 @@ function _getInput() {
217
140
  switch (type) {
218
141
  case 'application/json':
219
142
  {
220
- return JSON.parse(buffer.toString());
143
+ return consumers.json(node_stream.Readable.from(buffer));
221
144
  }
222
145
 
223
146
  default:
224
147
  {
148
+
225
149
  return null;
226
150
  }
227
151
  }
228
152
  });
229
- return _getInput.apply(this, arguments);
153
+ return _getBody.apply(this, arguments);
230
154
  }
231
155
 
232
156
  class KaitoRequest {
@@ -235,12 +159,21 @@ class KaitoRequest {
235
159
 
236
160
  this.raw = raw;
237
161
  }
162
+ /**
163
+ * The full URL of the request, including the protocol, hostname, and path.
164
+ * Note: does not include the query string or hash
165
+ */
166
+
238
167
 
239
168
  get fullURL() {
240
169
  var _this$raw$url;
241
170
 
242
171
  return "".concat(this.protocol, "://").concat(this.hostname).concat((_this$raw$url = this.raw.url) !== null && _this$raw$url !== void 0 ? _this$raw$url : '');
243
172
  }
173
+ /**
174
+ * A new URL instance for the full URL of the request.
175
+ */
176
+
244
177
 
245
178
  get url() {
246
179
  if (this._url) {
@@ -250,6 +183,10 @@ class KaitoRequest {
250
183
  this._url = new URL(this.fullURL);
251
184
  return this._url;
252
185
  }
186
+ /**
187
+ * The HTTP method of the request.
188
+ */
189
+
253
190
 
254
191
  get method() {
255
192
  if (!this.raw.method) {
@@ -258,18 +195,30 @@ class KaitoRequest {
258
195
 
259
196
  return this.raw.method;
260
197
  }
198
+ /**
199
+ * The protocol of the request, either `http` or `https`.
200
+ */
201
+
261
202
 
262
203
  get protocol() {
263
- if (this.raw.socket instanceof tls.TLSSocket) {
204
+ if (this.raw.socket instanceof node_tls.TLSSocket) {
264
205
  return this.raw.socket.encrypted ? 'https' : 'http';
265
206
  }
266
207
 
267
208
  return 'http';
268
209
  }
210
+ /**
211
+ * The request headers
212
+ */
213
+
269
214
 
270
215
  get headers() {
271
216
  return this.raw.headers;
272
217
  }
218
+ /**
219
+ * The hostname of the request.
220
+ */
221
+
273
222
 
274
223
  get hostname() {
275
224
  var _this$raw$headers$hos, _this$raw$headers$Au;
@@ -283,16 +232,48 @@ class KaitoResponse {
283
232
  constructor(raw) {
284
233
  this.raw = raw;
285
234
  }
235
+ /**
236
+ * Send a response
237
+ * @param key The key of the header
238
+ * @param value The value of the header
239
+ * @returns The response object
240
+ */
241
+
286
242
 
287
243
  header(key, value) {
288
244
  this.raw.setHeader(key, value);
289
245
  return this;
290
246
  }
247
+ /**
248
+ * Set the status code of the response
249
+ * @param code The status code
250
+ * @returns The response object
251
+ */
252
+
291
253
 
292
254
  status(code) {
293
255
  this.raw.statusCode = code;
294
256
  return this;
295
257
  }
258
+ /**
259
+ * Set a cookie
260
+ * @param name The name of the cookie
261
+ * @param value The value of the cookie
262
+ * @param options The options for the cookie
263
+ * @returns The response object
264
+ */
265
+
266
+
267
+ cookie(name, value, options) {
268
+ this.raw.setHeader('Set-Cookie', cookie.serialize(name, value, options));
269
+ return this;
270
+ }
271
+ /**
272
+ * Send a JSON APIResponse body
273
+ * @param data The data to send
274
+ * @returns The response object
275
+ */
276
+
296
277
 
297
278
  json(data) {
298
279
  var json = JSON.stringify(data);
@@ -304,22 +285,57 @@ class KaitoResponse {
304
285
 
305
286
  }
306
287
 
307
- class Router {
308
- static create() {
309
- return new Router([]);
288
+ function ownKeys(object, enumerableOnly) {
289
+ var keys = Object.keys(object);
290
+
291
+ if (Object.getOwnPropertySymbols) {
292
+ var symbols = Object.getOwnPropertySymbols(object);
293
+
294
+ if (enumerableOnly) {
295
+ symbols = symbols.filter(function (sym) {
296
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
297
+ });
298
+ }
299
+
300
+ keys.push.apply(keys, symbols);
301
+ }
302
+
303
+ return keys;
304
+ }
305
+
306
+ function _objectSpread2(target) {
307
+ for (var i = 1; i < arguments.length; i++) {
308
+ var source = arguments[i] != null ? arguments[i] : {};
309
+
310
+ if (i % 2) {
311
+ ownKeys(Object(source), true).forEach(function (key) {
312
+ _defineProperty(target, key, source[key]);
313
+ });
314
+ } else if (Object.getOwnPropertyDescriptors) {
315
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
316
+ } else {
317
+ ownKeys(Object(source)).forEach(function (key) {
318
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
319
+ });
320
+ }
310
321
  }
311
322
 
323
+ return target;
324
+ }
325
+
326
+ class Router {
312
327
  static handle(server, route, options) {
313
328
  return _asyncToGenerator(function* () {
314
329
  try {
315
- var _route$input$parse, _route$input;
330
+ var _yield$route$body$par, _route$body;
316
331
 
317
- var context = yield server.getContext(options.req, options.res);
318
- var body = yield getInput(options.req);
319
- 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;
332
+ var ctx = yield server.getContext(options.req, options.res);
333
+ var body = (_yield$route$body$par = yield (_route$body = route.body) === null || _route$body === void 0 ? void 0 : _route$body.parse(yield getBody(options.req))) !== null && _yield$route$body$par !== void 0 ? _yield$route$body$par : undefined;
334
+ var query = route.query ? zod.z.object(route.query).parse(Object.fromEntries(options.req.url.searchParams.entries())) : {};
320
335
  var result = yield route.run({
321
- ctx: context,
322
- input,
336
+ ctx,
337
+ body,
338
+ query,
323
339
  params: options.params
324
340
  });
325
341
  options.res.status(200).json({
@@ -327,6 +343,10 @@ class Router {
327
343
  data: result,
328
344
  message: 'OK'
329
345
  });
346
+ return {
347
+ success: true,
348
+ data: result
349
+ };
330
350
  } catch (e) {
331
351
  var error = WrappedError.maybe(e);
332
352
 
@@ -355,101 +375,156 @@ class Router {
355
375
  data: null,
356
376
  message
357
377
  });
378
+ return {
379
+ success: false,
380
+ data: {
381
+ status,
382
+ message
383
+ }
384
+ };
358
385
  }
359
386
  })();
360
387
  }
361
388
 
362
389
  constructor(routes) {
363
- this.routes = routes;
364
- }
390
+ _defineProperty(this, "add", route => new Router([...this.routes, route]));
365
391
 
366
- toFindMyWay(server) {
367
- var instance = fmw__default["default"]({
368
- ignoreTrailingSlash: true,
392
+ _defineProperty(this, "merge", (pathPrefix, other) => {
393
+ var newRoutes = other.routes.map(route => _objectSpread2(_objectSpread2({}, route), {}, {
394
+ path: "".concat(pathPrefix).concat(route.path)
395
+ }));
396
+ return new Router([...this.routes, ...newRoutes]);
397
+ });
369
398
 
370
- defaultRoute(req, serverResponse) {
371
- var _req$url;
399
+ _defineProperty(this, "toFindMyWay", server => {
400
+ var instance = fmw__default["default"]({
401
+ ignoreTrailingSlash: true,
402
+
403
+ defaultRoute(req, serverResponse) {
404
+ return _asyncToGenerator(function* () {
405
+ var _req$url;
406
+
407
+ var res = new KaitoResponse(serverResponse);
408
+ var message = "Cannot ".concat(req.method, " ").concat((_req$url = req.url) !== null && _req$url !== void 0 ? _req$url : '/');
409
+ res.status(404).json({
410
+ success: false,
411
+ data: null,
412
+ message
413
+ });
414
+ return {
415
+ success: false,
416
+ data: {
417
+ status: 404,
418
+ message
419
+ }
420
+ };
421
+ })();
422
+ }
372
423
 
373
- var res = new KaitoResponse(serverResponse);
374
- res.status(404).json({
375
- success: false,
376
- data: null,
377
- message: "Cannot ".concat(req.method, " ").concat((_req$url = req.url) !== null && _req$url !== void 0 ? _req$url : '/')
378
- });
424
+ });
425
+
426
+ var _loop = function _loop(route) {
427
+ var handler = /*#__PURE__*/function () {
428
+ var _ref = _asyncToGenerator(function* (incomingMessage, serverResponse, params) {
429
+ var req = new KaitoRequest(incomingMessage);
430
+ var res = new KaitoResponse(serverResponse);
431
+ return Router.handle(server, route, {
432
+ params,
433
+ req,
434
+ res
435
+ });
436
+ });
437
+
438
+ return function handler(_x, _x2, _x3) {
439
+ return _ref.apply(this, arguments);
440
+ };
441
+ }();
442
+
443
+ if (route.method === '*') {
444
+ instance.all(route.path, handler);
445
+ return "continue";
446
+ }
447
+
448
+ instance.on(route.method, route.path, handler);
449
+ };
450
+
451
+ for (var route of this.routes) {
452
+ var _ret = _loop(route);
453
+
454
+ if (_ret === "continue") continue;
379
455
  }
380
456
 
457
+ return instance;
381
458
  });
382
459
 
383
- var _loop = function _loop(route) {
384
- var handler = /*#__PURE__*/function () {
385
- var _ref = _asyncToGenerator(function* (incomingMessage, serverResponse, params) {
386
- var req = new KaitoRequest(incomingMessage);
387
- var res = new KaitoResponse(serverResponse);
388
- yield Router.handle(server, route, {
389
- params,
390
- req,
391
- res
392
- });
393
- });
460
+ this.routes = routes;
461
+ }
394
462
 
395
- return function handler(_x, _x2, _x3) {
396
- return _ref.apply(this, arguments);
397
- };
398
- }();
463
+ }
399
464
 
400
- if (route.method === '*') {
401
- instance.all(route.path, handler);
402
- return "continue";
403
- }
465
+ _defineProperty(Router, "create", () => new Router([]));
404
466
 
405
- instance.on(route.method, route.path, handler);
406
- };
467
+ function createFMWServer(config) {
468
+ var _config$rawRoutes;
407
469
 
408
- for (var route of this.routes) {
409
- var _ret = _loop(route);
470
+ var fmw = config.router.toFindMyWay(config);
471
+ var rawRoutes = (_config$rawRoutes = config.rawRoutes) !== null && _config$rawRoutes !== void 0 ? _config$rawRoutes : {};
410
472
 
411
- if (_ret === "continue") continue;
473
+ for (var method in rawRoutes) {
474
+ if (!Object.prototype.hasOwnProperty.call(rawRoutes, method)) {
475
+ continue;
412
476
  }
413
477
 
414
- return instance;
415
- }
478
+ var routes = rawRoutes[method];
479
+
480
+ if (!routes || routes.length === 0) {
481
+ continue;
482
+ }
416
483
 
417
- add(route) {
418
- return new Router([...this.routes, route]);
484
+ for (var route of routes) {
485
+ if (method === '*') {
486
+ fmw.all(route.path, route.handler);
487
+ continue;
488
+ }
489
+
490
+ fmw[method.toLowerCase()](route.path, route.handler);
491
+ }
419
492
  }
420
493
 
421
- map() {
422
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
423
- var result = {};
494
+ var server = http__namespace.createServer( /*#__PURE__*/function () {
495
+ var _ref = _asyncToGenerator(function* (req, res) {
496
+ var before;
424
497
 
425
- for (var route of this.routes) {
426
- var _result$method;
498
+ if (config.before) {
499
+ before = yield config.before(req, res);
500
+ } else {
501
+ before = undefined;
502
+ } // If the user has sent a response (e.g. replying to CORS), we don't want to do anything else.
427
503
 
428
- var method = route.method;
429
- result[method] = _objectSpread2(_objectSpread2({}, (_result$method = result[method]) !== null && _result$method !== void 0 ? _result$method : {}), {}, {
430
- [route.path]: route
431
- });
432
- }
433
504
 
434
- return result;
435
- }
505
+ if (res.headersSent) {
506
+ return;
507
+ }
436
508
 
437
- merge(prefix, router) {
438
- return this.copyContext([...this.routes, ...router.routes.map(route => _objectSpread2(_objectSpread2({}, route), {}, {
439
- path: prefix + route.path
440
- }))]);
441
- }
509
+ var result = yield fmw.lookup(req, res);
442
510
 
443
- copyContext(routes) {
444
- return new Router(routes);
445
- }
511
+ if ('after' in config && config.after) {
512
+ yield config.after(before, result);
513
+ }
514
+ });
446
515
 
516
+ return function (_x, _x2) {
517
+ return _ref.apply(this, arguments);
518
+ };
519
+ }());
520
+ return {
521
+ server,
522
+ fmw
523
+ };
524
+ }
525
+ function createServer(config) {
526
+ return createFMWServer(config).server;
447
527
  }
448
- /**
449
- * @deprecated Please use Router#create instead
450
- */
451
-
452
- var createRouter = Router.create;
453
528
 
454
529
  exports.KaitoError = KaitoError;
455
530
  exports.KaitoRequest = KaitoRequest;
@@ -458,7 +533,6 @@ exports.Router = Router;
458
533
  exports.WrappedError = WrappedError;
459
534
  exports.createFMWServer = createFMWServer;
460
535
  exports.createGetContext = createGetContext;
461
- exports.createRouter = createRouter;
462
536
  exports.createServer = createServer;
463
- exports.getInput = getInput;
537
+ exports.getBody = getBody;
464
538
  exports.getLastEntryInMultiHeaderValue = getLastEntryInMultiHeaderValue;