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