@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.
@@ -0,0 +1,6 @@
1
+ export declare class WrappedError<T> extends Error {
2
+ readonly data: T;
3
+ static maybe<T>(maybeError: T): (T & Error) | WrappedError<T>;
4
+ static from<T>(data: T): WrappedError<T>;
5
+ private constructor();
6
+ }
@@ -0,0 +1,13 @@
1
+ /// <reference types="node" />
2
+ import { IncomingMessage } from 'http';
3
+ import { Method } from './util';
4
+ export declare class KaitoRequest {
5
+ readonly raw: IncomingMessage;
6
+ constructor(raw: IncomingMessage);
7
+ get fullURL(): string;
8
+ get url(): URL;
9
+ get method(): Method;
10
+ get protocol(): 'http' | 'https';
11
+ get headers(): import("http").IncomingHttpHeaders;
12
+ get hostname(): string;
13
+ }
@@ -0,0 +1,21 @@
1
+ /// <reference types="node" />
2
+ import { ServerResponse } from 'http';
3
+ export declare type ErroredAPIResponse = {
4
+ success: false;
5
+ data: null;
6
+ message: string;
7
+ };
8
+ export declare type SuccessfulAPIResponse<T> = {
9
+ success: true;
10
+ data: T;
11
+ message: 'OK';
12
+ };
13
+ export declare type APIResponse<T> = ErroredAPIResponse | SuccessfulAPIResponse<T>;
14
+ export declare type AnyResponse = APIResponse<unknown>;
15
+ export declare class KaitoResponse<T = unknown> {
16
+ readonly raw: ServerResponse;
17
+ constructor(raw: ServerResponse);
18
+ header(key: string, value: string | readonly string[]): this;
19
+ status(code: number): this;
20
+ json(data: APIResponse<T>): this;
21
+ }
@@ -1,13 +1,10 @@
1
1
  /// <reference types="node" />
2
- import { FastifyReply, FastifyRequest } from 'fastify';
2
+ import http from 'http';
3
3
  import { z, ZodTypeAny } from 'zod';
4
- export declare enum Method {
5
- GET = "GET",
6
- POST = "POST",
7
- PATCH = "PATCH",
8
- DELETE = "DELETE"
9
- }
10
- export declare type GetContext<T> = (req: FastifyRequest, res: FastifyReply) => Promise<T>;
4
+ import { KaitoRequest } from './req';
5
+ import { KaitoResponse } from './res';
6
+ import { Method } from './util';
7
+ export declare type GetContext<T> = (req: KaitoRequest, res: KaitoResponse) => Promise<T>;
11
8
  declare type Never = [never];
12
9
  export declare function createGetContext<T>(getContext: GetContext<T>): GetContext<T>;
13
10
  export declare type InferContext<T> = T extends GetContext<infer Value> ? Value : never;
@@ -16,86 +13,136 @@ export declare type ContextWithInput<Ctx, Input> = {
16
13
  input: Input;
17
14
  };
18
15
  declare type Values<T> = T[keyof T];
19
- declare type Proc<Ctx, Result, Input extends z.ZodTypeAny | Never = Never> = Readonly<{
16
+ export declare type Proc<Ctx, Result, Input extends z.ZodTypeAny | Never = Never> = Readonly<{
20
17
  input?: Input;
21
18
  run(arg: ContextWithInput<Ctx, Input extends ZodTypeAny ? z.infer<Input> : undefined>): Promise<Result>;
22
19
  }>;
23
- declare type ProcsInit<Ctx> = {
24
- [Key in string]: Proc<Ctx, unknown, z.ZodTypeAny> & {
25
- method: Method;
26
- name: Key;
27
- };
20
+ export interface RouterProc<Path extends string = string, M extends Method = Method> {
21
+ method: M;
22
+ path: Path;
23
+ pattern: RegExp;
24
+ }
25
+ export declare type AnyProcs<Ctx> = {
26
+ [Path in string]: Proc<Ctx, unknown, z.ZodTypeAny> & RouterProc<Path>;
28
27
  };
29
- declare type AnyRouter<Ctx> = Router<Ctx, ProcsInit<Ctx>>;
30
- export declare class Router<Ctx, Procs extends ProcsInit<Ctx>> {
28
+ export declare type AnyRouter<Ctx> = Router<Ctx, AnyProcs<Ctx>>;
29
+ export declare class Router<Ctx, Procs extends AnyProcs<Ctx>> {
31
30
  private readonly procs;
31
+ private readonly _procsArray;
32
+ /**
33
+ * Ensures that the path does not start or end with a slash.
34
+ * @param path
35
+ * @private
36
+ */
37
+ private static stripSlashes;
32
38
  constructor(procs: Procs);
33
39
  getProcs(): Procs;
40
+ find(method: Method, url: string): (Readonly<{
41
+ input?: z.ZodTypeAny | undefined;
42
+ run(arg: ContextWithInput<Ctx, any>): Promise<unknown>;
43
+ }> & RouterProc<string, Method>) | null;
34
44
  private readonly create;
35
- readonly merge: <Prefix extends string, NewCtx, NewProcs extends ProcsInit<NewCtx>>(prefix: Prefix, router: Router<NewCtx, NewProcs>) => Router<NewCtx & Ctx, Procs & { [Key in `${Prefix}${Extract<keyof NewProcs, string>}`]: Omit<NewProcs[Key extends `${Prefix}${infer Rest}` ? Rest : never], "name"> & {
36
- name: Key;
45
+ readonly merge: <Prefix extends string, NewCtx, NewProcs extends AnyProcs<NewCtx>>(prefix: Prefix, router: Router<NewCtx, NewProcs>) => Router<NewCtx & Ctx, Procs & { [P in `${Prefix}${Extract<keyof NewProcs, string>}`]: Omit<NewProcs[P extends `${Prefix}${infer Rest}` ? Rest : never], "path"> & {
46
+ path: P;
37
47
  }; }>;
38
- readonly get: <Name extends string, Result, Input extends z.ZodTypeAny>(name: Name, proc: Readonly<{
48
+ readonly get: <Path extends string, Result, Input extends z.ZodTypeAny>(path: Path, proc: Readonly<{
49
+ input?: Input | undefined;
50
+ run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
51
+ }>) => Router<Ctx, Procs & Record<Path, Readonly<{
52
+ input?: Input | undefined;
53
+ run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
54
+ }> & RouterProc<Path, "GET">>>;
55
+ readonly post: <Path extends string, Result, Input extends z.ZodTypeAny>(path: Path, proc: Readonly<{
56
+ input?: Input | undefined;
57
+ run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
58
+ }>) => Router<Ctx, Procs & Record<Path, Readonly<{
59
+ input?: Input | undefined;
60
+ run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
61
+ }> & RouterProc<Path, "POST">>>;
62
+ readonly put: <Path extends string, Result, Input extends z.ZodTypeAny>(path: Path, proc: Readonly<{
63
+ input?: Input | undefined;
64
+ run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
65
+ }>) => Router<Ctx, Procs & Record<Path, Readonly<{
66
+ input?: Input | undefined;
67
+ run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
68
+ }> & RouterProc<Path, "PUT">>>;
69
+ readonly patch: <Path extends string, Result, Input extends z.ZodTypeAny>(path: Path, proc: Readonly<{
70
+ input?: Input | undefined;
71
+ run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
72
+ }>) => Router<Ctx, Procs & Record<Path, Readonly<{
73
+ input?: Input | undefined;
74
+ run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
75
+ }> & RouterProc<Path, "PATCH">>>;
76
+ readonly delete: <Path extends string, Result, Input extends z.ZodTypeAny>(path: Path, proc: Readonly<{
77
+ input?: Input | undefined;
78
+ run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
79
+ }>) => Router<Ctx, Procs & Record<Path, Readonly<{
80
+ input?: Input | undefined;
81
+ run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
82
+ }> & RouterProc<Path, "DELETE">>>;
83
+ readonly head: <Path extends string, Result, Input extends z.ZodTypeAny>(path: Path, proc: Readonly<{
84
+ input?: Input | undefined;
85
+ run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
86
+ }>) => Router<Ctx, Procs & Record<Path, Readonly<{
87
+ input?: Input | undefined;
88
+ run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
89
+ }> & RouterProc<Path, "HEAD">>>;
90
+ readonly options: <Path extends string, Result, Input extends z.ZodTypeAny>(path: Path, proc: Readonly<{
91
+ input?: Input | undefined;
92
+ run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
93
+ }>) => Router<Ctx, Procs & Record<Path, Readonly<{
94
+ input?: Input | undefined;
95
+ run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
96
+ }> & RouterProc<Path, "OPTIONS">>>;
97
+ readonly connect: <Path extends string, Result, Input extends z.ZodTypeAny>(path: Path, proc: Readonly<{
39
98
  input?: Input | undefined;
40
99
  run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
41
- }>) => Router<Ctx, Procs & Record<Name, Readonly<{
100
+ }>) => Router<Ctx, Procs & Record<Path, Readonly<{
42
101
  input?: Input | undefined;
43
102
  run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
44
- }> & {
45
- method: Method.GET;
46
- name: Name;
47
- }>>;
48
- readonly post: <Name extends string, Result, Input extends z.ZodTypeAny>(name: Name, proc: Readonly<{
103
+ }> & RouterProc<Path, "CONNECT">>>;
104
+ readonly trace: <Path extends string, Result, Input extends z.ZodTypeAny>(path: Path, proc: Readonly<{
49
105
  input?: Input | undefined;
50
106
  run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
51
- }>) => Router<Ctx, Procs & Record<Name, Readonly<{
107
+ }>) => Router<Ctx, Procs & Record<Path, Readonly<{
52
108
  input?: Input | undefined;
53
109
  run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
54
- }> & {
55
- method: Method.POST;
56
- name: Name;
57
- }>>;
58
- readonly patch: <Name extends string, Result, Input extends z.ZodTypeAny>(name: Name, proc: Readonly<{
110
+ }> & RouterProc<Path, "TRACE">>>;
111
+ readonly acl: <Path extends string, Result, Input extends z.ZodTypeAny>(path: Path, proc: Readonly<{
59
112
  input?: Input | undefined;
60
113
  run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
61
- }>) => Router<Ctx, Procs & Record<Name, Readonly<{
114
+ }>) => Router<Ctx, Procs & Record<Path, Readonly<{
62
115
  input?: Input | undefined;
63
116
  run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
64
- }> & {
65
- method: Method.PATCH;
66
- name: Name;
67
- }>>;
68
- readonly delete: <Name extends string, Result, Input extends z.ZodTypeAny>(name: Name, proc: Readonly<{
117
+ }> & RouterProc<Path, "ACL">>>;
118
+ readonly bind: <Path extends string, Result, Input extends z.ZodTypeAny>(path: Path, proc: Readonly<{
69
119
  input?: Input | undefined;
70
120
  run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
71
- }>) => Router<Ctx, Procs & Record<Name, Readonly<{
121
+ }>) => Router<Ctx, Procs & Record<Path, Readonly<{
72
122
  input?: Input | undefined;
73
123
  run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
74
- }> & {
75
- method: Method.DELETE;
76
- name: Name;
77
- }>>;
124
+ }> & RouterProc<Path, "BIND">>>;
78
125
  }
79
126
  export declare class KaitoError extends Error {
80
- readonly code: number;
127
+ readonly status: number;
81
128
  readonly cause?: Error | undefined;
82
- constructor(code: number, message: string, cause?: Error | undefined);
129
+ constructor(status: number, message: string, cause?: Error | undefined);
83
130
  }
84
131
  export declare function createRouter<Ctx>(): Router<Ctx, {}>;
85
- export declare type InferApiResponseType<R extends AnyRouter<unknown>, M extends Method, Path extends Extract<Values<ReturnType<R['getProcs']>>, {
132
+ export declare type InferAPIResponseType<R extends AnyRouter<unknown>, M extends Method, Path extends Extract<Values<ReturnType<R['getProcs']>>, {
86
133
  method: M;
87
- }>['name']> = ReturnType<ReturnType<R['getProcs']>[Path]['run']> extends Promise<infer V> ? V : never;
88
- export declare function createServer<Ctx, R extends Router<Ctx, ProcsInit<Ctx>>>(config: {
134
+ }>['path']> = ReturnType<ReturnType<R['getProcs']>[Path]['run']> extends Promise<infer V> ? V : never;
135
+ export declare function createServer<Ctx, R extends Router<Ctx, AnyProcs<Ctx>>>(config: {
89
136
  getContext: GetContext<Ctx>;
90
137
  router: R;
91
138
  onError(error: {
92
139
  error: Error;
93
- req: FastifyRequest;
94
- res: FastifyReply;
140
+ req: KaitoRequest;
141
+ res: KaitoResponse;
95
142
  }): Promise<{
96
- code: number;
143
+ status: number;
97
144
  message: string;
98
145
  }>;
99
- log?: (message: string) => unknown | false;
100
- }): import("fastify").FastifyInstance<import("http").Server, import("http").IncomingMessage, import("http").ServerResponse, import("fastify").FastifyLoggerInstance> & PromiseLike<import("fastify").FastifyInstance<import("http").Server, import("http").IncomingMessage, import("http").ServerResponse, import("fastify").FastifyLoggerInstance>>;
146
+ log?: ((message: string) => unknown) | false;
147
+ }): http.Server;
101
148
  export {};
@@ -0,0 +1,4 @@
1
+ import { KaitoRequest } from './req';
2
+ export declare function getLastEntryInMultiHeaderValue(headerValue: string | string[]): string;
3
+ export declare type Method = 'ACL' | 'BIND' | 'CHECKOUT' | 'CONNECT' | 'COPY' | 'DELETE' | 'GET' | 'HEAD' | 'LINK' | 'LOCK' | 'M-SEARCH' | 'MERGE' | 'MKACTIVITY' | 'MKCALENDAR' | 'MKCOL' | 'MOVE' | 'NOTIFY' | 'OPTIONS' | 'PATCH' | 'POST' | 'PRI' | 'PROPFIND' | 'PROPPATCH' | 'PURGE' | 'PUT' | 'REBIND' | 'REPORT' | 'SEARCH' | 'SOURCE' | 'SUBSCRIBE' | 'TRACE' | 'UNBIND' | 'UNLINK' | 'UNLOCK' | 'UNSUBSCRIBE';
4
+ export declare function getInput(req: KaitoRequest): Promise<unknown>;
@@ -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;