@kaito-http/core 2.0.1 → 2.2.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,11 +2,14 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var fastify = require('fastify');
5
+ var http = require('http');
6
+ var tls = require('tls');
7
+ var getRawBody = require('raw-body');
6
8
 
7
9
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
8
10
 
9
- var fastify__default = /*#__PURE__*/_interopDefault(fastify);
11
+ var http__default = /*#__PURE__*/_interopDefault(http);
12
+ var getRawBody__default = /*#__PURE__*/_interopDefault(getRawBody);
10
13
 
11
14
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
12
15
  try {
@@ -97,35 +100,176 @@ function _objectSpread2(target) {
97
100
  return target;
98
101
  }
99
102
 
100
- exports.Method = void 0;
103
+ class WrappedError extends Error {
104
+ static maybe(maybeError) {
105
+ if (maybeError instanceof Error) {
106
+ return maybeError;
107
+ }
108
+
109
+ return WrappedError.from(maybeError);
110
+ }
111
+
112
+ static from(data) {
113
+ return new WrappedError(data);
114
+ }
115
+
116
+ constructor(data) {
117
+ super('Something was thrown, but it was not an instance of Error, so a WrappedError was created.');
118
+ this.data = data;
119
+ }
120
+
121
+ }
122
+
123
+ function getLastEntryInMultiHeaderValue(headerValue) {
124
+ var normalized = Array.isArray(headerValue) ? headerValue.join(',') : headerValue;
125
+ var lastIndex = normalized.lastIndexOf(',');
126
+ return lastIndex === -1 ? normalized.trim() : normalized.slice(lastIndex + 1).trim();
127
+ } // Type for import('http').METHODS
128
+
129
+ function getInput(_x) {
130
+ return _getInput.apply(this, arguments);
131
+ }
132
+
133
+ function _getInput() {
134
+ _getInput = _asyncToGenerator(function* (req) {
135
+ if (req.method === 'GET') {
136
+ var input = req.url.searchParams.get('input');
137
+
138
+ if (!input) {
139
+ return null;
140
+ }
141
+
142
+ return JSON.parse(input);
143
+ }
144
+
145
+ var buffer = yield getRawBody__default["default"](req.raw);
146
+
147
+ switch (req.headers['content-type']) {
148
+ case 'application/json':
149
+ {
150
+ return JSON.parse(buffer.toString());
151
+ }
152
+
153
+ default:
154
+ {
155
+ return null;
156
+ }
157
+ }
158
+ });
159
+ return _getInput.apply(this, arguments);
160
+ }
161
+
162
+ class KaitoRequest {
163
+ constructor(raw) {
164
+ this.raw = raw;
165
+ }
166
+
167
+ get fullURL() {
168
+ var _this$raw$url;
169
+
170
+ return "".concat(this.protocol, "://").concat(this.hostname).concat((_this$raw$url = this.raw.url) !== null && _this$raw$url !== void 0 ? _this$raw$url : '');
171
+ }
172
+
173
+ get url() {
174
+ return new URL(this.fullURL);
175
+ }
176
+
177
+ get method() {
178
+ if (!this.raw.method) {
179
+ throw new Error('Request method is not defined, somehow...');
180
+ }
181
+
182
+ return this.raw.method;
183
+ }
184
+
185
+ get protocol() {
186
+ if (this.raw.socket instanceof tls.TLSSocket) {
187
+ return this.raw.socket.encrypted ? 'https' : 'http';
188
+ }
189
+
190
+ return 'http';
191
+ }
192
+
193
+ get headers() {
194
+ return this.raw.headers;
195
+ }
196
+
197
+ get hostname() {
198
+ var _this$raw$headers$hos, _this$raw$headers$Au;
199
+
200
+ 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 : []);
201
+ }
202
+
203
+ }
204
+
205
+ class KaitoResponse {
206
+ constructor(raw) {
207
+ this.raw = raw;
208
+ }
209
+
210
+ header(key, value) {
211
+ this.raw.setHeader(key, value);
212
+ return this;
213
+ }
214
+
215
+ status(code) {
216
+ this.raw.statusCode = code;
217
+ return this;
218
+ }
101
219
 
102
- (function (Method) {
103
- Method["GET"] = "GET";
104
- Method["POST"] = "POST";
105
- Method["PATCH"] = "PATCH";
106
- Method["DELETE"] = "DELETE";
107
- })(exports.Method || (exports.Method = {}));
220
+ json(data) {
221
+ var json = JSON.stringify(data);
222
+ this.raw.setHeader('Content-Type', 'application/json');
223
+ this.raw.setHeader('Content-Length', Buffer.byteLength(json));
224
+ this.raw.end(json);
225
+ return this;
226
+ }
227
+
228
+ }
108
229
 
109
230
  function createGetContext(getContext) {
110
231
  return getContext;
111
232
  }
112
233
  class Router {
234
+ /**
235
+ * Ensures that the path does not start or end with a slash.
236
+ * @param path
237
+ * @private
238
+ */
239
+ static stripSlashes(path) {
240
+ if (path.startsWith('/')) {
241
+ path = path.slice(1);
242
+ }
243
+
244
+ if (path.endsWith('/')) {
245
+ path = path.slice(-1);
246
+ }
247
+
248
+ return path;
249
+ }
250
+
113
251
  constructor(procs) {
114
- _defineProperty(this, "create", method => (name, proc) => {
115
- return new Router(_objectSpread2(_objectSpread2({}, this.procs), {}, {
116
- [name]: _objectSpread2(_objectSpread2({}, proc), {}, {
252
+ _defineProperty(this, "create", method => (path, proc) => {
253
+ var stripped = Router.stripSlashes(path);
254
+ var pattern = new RegExp("^/".concat(stripped, "/?$"), 'i');
255
+
256
+ var merged = _objectSpread2(_objectSpread2({}, this.procs), {}, {
257
+ [path]: _objectSpread2(_objectSpread2({}, proc), {}, {
117
258
  method,
118
- name
259
+ path,
260
+ pattern
119
261
  })
120
- }));
262
+ });
263
+
264
+ return new Router(merged);
121
265
  });
122
266
 
123
267
  _defineProperty(this, "merge", (prefix, router) => {
124
268
  var newProcs = Object.entries(router.getProcs()).reduce((all, entry) => {
125
- var [name, proc] = entry;
269
+ var [path, proc] = entry;
126
270
  return _objectSpread2(_objectSpread2({}, all), {}, {
127
- ["".concat(prefix).concat(name)]: _objectSpread2(_objectSpread2({}, proc), {}, {
128
- name: "".concat(prefix).concat(name)
271
+ ["".concat(prefix).concat(path)]: _objectSpread2(_objectSpread2({}, proc), {}, {
272
+ path: "".concat(prefix).concat(path)
129
273
  })
130
274
  });
131
275
  }, {});
@@ -135,26 +279,55 @@ class Router {
135
279
  return new Router(mergedProcs);
136
280
  });
137
281
 
138
- _defineProperty(this, "get", this.create(exports.Method.GET));
282
+ _defineProperty(this, "get", this.create('GET'));
283
+
284
+ _defineProperty(this, "post", this.create('POST'));
139
285
 
140
- _defineProperty(this, "post", this.create(exports.Method.POST));
286
+ _defineProperty(this, "put", this.create('PUT'));
141
287
 
142
- _defineProperty(this, "patch", this.create(exports.Method.PATCH));
288
+ _defineProperty(this, "patch", this.create('PATCH'));
143
289
 
144
- _defineProperty(this, "delete", this.create(exports.Method.DELETE));
290
+ _defineProperty(this, "delete", this.create('DELETE'));
291
+
292
+ _defineProperty(this, "head", this.create('HEAD'));
293
+
294
+ _defineProperty(this, "options", this.create('OPTIONS'));
295
+
296
+ _defineProperty(this, "connect", this.create('CONNECT'));
297
+
298
+ _defineProperty(this, "trace", this.create('TRACE'));
299
+
300
+ _defineProperty(this, "acl", this.create('ACL'));
301
+
302
+ _defineProperty(this, "bind", this.create('BIND'));
145
303
 
146
304
  this.procs = procs;
305
+ this._procsArray = Object.values(procs);
147
306
  }
148
307
 
149
308
  getProcs() {
150
309
  return this.procs;
151
310
  }
152
311
 
312
+ find(method, url) {
313
+ for (var proc of this._procsArray) {
314
+ if (proc.method !== method) {
315
+ continue;
316
+ }
317
+
318
+ if (proc.pattern.test(url)) {
319
+ return proc;
320
+ }
321
+ }
322
+
323
+ return null;
324
+ }
325
+
153
326
  }
154
327
  class KaitoError extends Error {
155
- constructor(code, message, cause) {
328
+ constructor(status, message, cause) {
156
329
  super(message);
157
- this.code = code;
330
+ this.status = status;
158
331
  this.cause = cause;
159
332
  }
160
333
 
@@ -163,79 +336,76 @@ function createRouter() {
163
336
  return new Router({});
164
337
  }
165
338
  function createServer(config) {
166
- var tree = config.router.getProcs();
167
- var app = fastify__default["default"]();
168
- app.setErrorHandler( /*#__PURE__*/function () {
169
- var _ref = _asyncToGenerator(function* (error, req, res) {
170
- if (error instanceof KaitoError) {
171
- yield res.status(error.code).send({
172
- success: false,
173
- data: null,
174
- message: error.message
175
- });
176
- return;
177
- }
178
-
179
- var {
180
- code,
181
- message
182
- } = yield config.onError({
183
- error,
184
- req,
185
- res
186
- }).catch(() => ({
187
- code: 500,
188
- message: 'Something went wrong'
189
- }));
190
- yield res.status(code).send({
191
- success: false,
192
- data: null,
193
- message
194
- });
195
- });
196
-
197
- return function (_x, _x2, _x3) {
198
- return _ref.apply(this, arguments);
199
- };
200
- }());
201
- app.all('*', /*#__PURE__*/function () {
202
- var _ref2 = _asyncToGenerator(function* (req, res) {
203
- var _handler$input$parse, _handler$input;
204
-
205
- var logMessage = "".concat(req.hostname, " ").concat(req.method, " ").concat(req.routerPath);
339
+ var log = message => {
340
+ if (config.log === undefined) {
341
+ console.log(message);
342
+ } else if (config.log) {
343
+ config.log(message);
344
+ }
345
+ };
206
346
 
207
- if (config.log === undefined) {
208
- console.log(logMessage);
209
- } else if (config.log) {
210
- config.log(logMessage);
211
- }
347
+ return http__default["default"].createServer( /*#__PURE__*/function () {
348
+ var _ref = _asyncToGenerator(function* (incomingMessage, serverResponse) {
349
+ var start = Date.now();
350
+ var req = new KaitoRequest(incomingMessage);
351
+ var res = new KaitoResponse(serverResponse);
212
352
 
213
- var url = new URL("".concat(req.protocol, "://").concat(req.hostname).concat(req.url));
214
- var handler = tree[url.pathname];
353
+ try {
354
+ var _handler$input, _yield$getInput;
215
355
 
216
- if (!handler) {
217
- throw new KaitoError(404, "Cannot ".concat(req.method, " this route."));
218
- }
356
+ var handler = config.router.find(req.method, req.url.pathname);
219
357
 
220
- var context = yield config.getContext(req, res); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
358
+ if (!handler) {
359
+ throw new KaitoError(404, "Cannot ".concat(req.method, " this route."));
360
+ }
221
361
 
222
- var input = (_handler$input$parse = (_handler$input = handler.input) === null || _handler$input === void 0 ? void 0 : _handler$input.parse(req.method === 'GET' ? req.query : req.body)) !== null && _handler$input$parse !== void 0 ? _handler$input$parse : null;
223
- yield res.send({
224
- success: true,
225
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
226
- data: yield handler.run({
362
+ var input = (_handler$input = handler.input) === null || _handler$input === void 0 ? void 0 : _handler$input.parse((_yield$getInput = yield getInput(req)) !== null && _yield$getInput !== void 0 ? _yield$getInput : undefined);
363
+ var context = yield config.getContext(req, res);
364
+ var data = yield handler.run({
227
365
  ctx: context,
228
366
  input
229
- }),
230
- message: 'OK'
231
- });
367
+ });
368
+ res.json({
369
+ success: true,
370
+ data,
371
+ message: 'OK'
372
+ });
373
+ } catch (error) {
374
+ if (error instanceof KaitoError) {
375
+ res.status(error.status).json({
376
+ success: false,
377
+ data: null,
378
+ message: error.message
379
+ });
380
+ return;
381
+ }
382
+
383
+ var {
384
+ status: _status,
385
+ message: _message
386
+ } = yield config.onError({
387
+ error: WrappedError.maybe(error),
388
+ req,
389
+ res
390
+ }).catch(() => ({
391
+ status: 500,
392
+ message: 'Something went wrong'
393
+ }));
394
+ res.status(_status).json({
395
+ success: false,
396
+ data: null,
397
+ message: _message
398
+ });
399
+ } finally {
400
+ var finish = Date.now();
401
+ log("".concat(req.method, " ").concat(req.fullURL, " ").concat(res.raw.statusCode, " ").concat(finish - start, "ms"));
402
+ }
232
403
  });
233
404
 
234
- return function (_x4, _x5) {
235
- return _ref2.apply(this, arguments);
405
+ return function (_x, _x2) {
406
+ return _ref.apply(this, arguments);
236
407
  };
237
408
  }());
238
- return app;
239
409
  }
240
410
 
241
411
  exports.KaitoError = KaitoError;