@kaito-http/core 2.0.0 → 2.1.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.
- package/dist/declarations/src/error.d.ts +5 -0
- package/dist/declarations/src/req.d.ts +13 -0
- package/dist/declarations/src/res.d.ts +21 -0
- package/dist/declarations/src/server.d.ts +90 -21
- package/dist/declarations/src/util.d.ts +4 -0
- package/dist/kaito-http-core.cjs.dev.js +221 -78
- package/dist/kaito-http-core.cjs.prod.js +221 -78
- package/dist/kaito-http-core.esm.js +220 -78
- package/package.json +11 -11
|
@@ -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
|
|
2
|
+
import http from 'http';
|
|
3
3
|
import { z, ZodTypeAny } from 'zod';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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;
|
|
@@ -32,7 +29,9 @@ export declare class Router<Ctx, Procs extends ProcsInit<Ctx>> {
|
|
|
32
29
|
constructor(procs: Procs);
|
|
33
30
|
getProcs(): Procs;
|
|
34
31
|
private readonly create;
|
|
35
|
-
readonly merge: <NewCtx
|
|
32
|
+
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"> & {
|
|
33
|
+
name: Key;
|
|
34
|
+
}; }>;
|
|
36
35
|
readonly get: <Name extends string, Result, Input extends z.ZodTypeAny>(name: Name, proc: Readonly<{
|
|
37
36
|
input?: Input | undefined;
|
|
38
37
|
run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
|
|
@@ -40,7 +39,7 @@ export declare class Router<Ctx, Procs extends ProcsInit<Ctx>> {
|
|
|
40
39
|
input?: Input | undefined;
|
|
41
40
|
run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
|
|
42
41
|
}> & {
|
|
43
|
-
method:
|
|
42
|
+
method: "GET";
|
|
44
43
|
name: Name;
|
|
45
44
|
}>>;
|
|
46
45
|
readonly post: <Name extends string, Result, Input extends z.ZodTypeAny>(name: Name, proc: Readonly<{
|
|
@@ -50,7 +49,17 @@ export declare class Router<Ctx, Procs extends ProcsInit<Ctx>> {
|
|
|
50
49
|
input?: Input | undefined;
|
|
51
50
|
run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
|
|
52
51
|
}> & {
|
|
53
|
-
method:
|
|
52
|
+
method: "POST";
|
|
53
|
+
name: Name;
|
|
54
|
+
}>>;
|
|
55
|
+
readonly put: <Name extends string, Result, Input extends z.ZodTypeAny>(name: Name, 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<Name, Readonly<{
|
|
59
|
+
input?: Input | undefined;
|
|
60
|
+
run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
|
|
61
|
+
}> & {
|
|
62
|
+
method: "PUT";
|
|
54
63
|
name: Name;
|
|
55
64
|
}>>;
|
|
56
65
|
readonly patch: <Name extends string, Result, Input extends z.ZodTypeAny>(name: Name, proc: Readonly<{
|
|
@@ -60,7 +69,7 @@ export declare class Router<Ctx, Procs extends ProcsInit<Ctx>> {
|
|
|
60
69
|
input?: Input | undefined;
|
|
61
70
|
run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
|
|
62
71
|
}> & {
|
|
63
|
-
method:
|
|
72
|
+
method: "PATCH";
|
|
64
73
|
name: Name;
|
|
65
74
|
}>>;
|
|
66
75
|
readonly delete: <Name extends string, Result, Input extends z.ZodTypeAny>(name: Name, proc: Readonly<{
|
|
@@ -70,17 +79,77 @@ export declare class Router<Ctx, Procs extends ProcsInit<Ctx>> {
|
|
|
70
79
|
input?: Input | undefined;
|
|
71
80
|
run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
|
|
72
81
|
}> & {
|
|
73
|
-
method:
|
|
82
|
+
method: "DELETE";
|
|
83
|
+
name: Name;
|
|
84
|
+
}>>;
|
|
85
|
+
readonly head: <Name extends string, Result, Input extends z.ZodTypeAny>(name: Name, proc: Readonly<{
|
|
86
|
+
input?: Input | undefined;
|
|
87
|
+
run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
|
|
88
|
+
}>) => Router<Ctx, Procs & Record<Name, Readonly<{
|
|
89
|
+
input?: Input | undefined;
|
|
90
|
+
run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
|
|
91
|
+
}> & {
|
|
92
|
+
method: "HEAD";
|
|
93
|
+
name: Name;
|
|
94
|
+
}>>;
|
|
95
|
+
readonly options: <Name extends string, Result, Input extends z.ZodTypeAny>(name: Name, proc: Readonly<{
|
|
96
|
+
input?: Input | undefined;
|
|
97
|
+
run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
|
|
98
|
+
}>) => Router<Ctx, Procs & Record<Name, Readonly<{
|
|
99
|
+
input?: Input | undefined;
|
|
100
|
+
run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
|
|
101
|
+
}> & {
|
|
102
|
+
method: "OPTIONS";
|
|
103
|
+
name: Name;
|
|
104
|
+
}>>;
|
|
105
|
+
readonly connect: <Name extends string, Result, Input extends z.ZodTypeAny>(name: Name, proc: Readonly<{
|
|
106
|
+
input?: Input | undefined;
|
|
107
|
+
run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
|
|
108
|
+
}>) => Router<Ctx, Procs & Record<Name, Readonly<{
|
|
109
|
+
input?: Input | undefined;
|
|
110
|
+
run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
|
|
111
|
+
}> & {
|
|
112
|
+
method: "CONNECT";
|
|
113
|
+
name: Name;
|
|
114
|
+
}>>;
|
|
115
|
+
readonly trace: <Name extends string, Result, Input extends z.ZodTypeAny>(name: Name, proc: Readonly<{
|
|
116
|
+
input?: Input | undefined;
|
|
117
|
+
run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
|
|
118
|
+
}>) => Router<Ctx, Procs & Record<Name, Readonly<{
|
|
119
|
+
input?: Input | undefined;
|
|
120
|
+
run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
|
|
121
|
+
}> & {
|
|
122
|
+
method: "TRACE";
|
|
123
|
+
name: Name;
|
|
124
|
+
}>>;
|
|
125
|
+
readonly acl: <Name extends string, Result, Input extends z.ZodTypeAny>(name: Name, proc: Readonly<{
|
|
126
|
+
input?: Input | undefined;
|
|
127
|
+
run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
|
|
128
|
+
}>) => Router<Ctx, Procs & Record<Name, Readonly<{
|
|
129
|
+
input?: Input | undefined;
|
|
130
|
+
run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
|
|
131
|
+
}> & {
|
|
132
|
+
method: "ACL";
|
|
133
|
+
name: Name;
|
|
134
|
+
}>>;
|
|
135
|
+
readonly bind: <Name extends string, Result, Input extends z.ZodTypeAny>(name: Name, proc: Readonly<{
|
|
136
|
+
input?: Input | undefined;
|
|
137
|
+
run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
|
|
138
|
+
}>) => Router<Ctx, Procs & Record<Name, Readonly<{
|
|
139
|
+
input?: Input | undefined;
|
|
140
|
+
run(arg: ContextWithInput<Ctx, Input extends z.ZodTypeAny ? z.TypeOf<Input> : undefined>): Promise<Result>;
|
|
141
|
+
}> & {
|
|
142
|
+
method: "BIND";
|
|
74
143
|
name: Name;
|
|
75
144
|
}>>;
|
|
76
145
|
}
|
|
77
146
|
export declare class KaitoError extends Error {
|
|
78
|
-
readonly
|
|
147
|
+
readonly status: number;
|
|
79
148
|
readonly cause?: Error | undefined;
|
|
80
|
-
constructor(
|
|
149
|
+
constructor(status: number, message: string, cause?: Error | undefined);
|
|
81
150
|
}
|
|
82
151
|
export declare function createRouter<Ctx>(): Router<Ctx, {}>;
|
|
83
|
-
export declare type
|
|
152
|
+
export declare type InferAPIResponseType<R extends AnyRouter<unknown>, M extends Method, Path extends Extract<Values<ReturnType<R['getProcs']>>, {
|
|
84
153
|
method: M;
|
|
85
154
|
}>['name']> = ReturnType<ReturnType<R['getProcs']>[Path]['run']> extends Promise<infer V> ? V : never;
|
|
86
155
|
export declare function createServer<Ctx, R extends Router<Ctx, ProcsInit<Ctx>>>(config: {
|
|
@@ -88,12 +157,12 @@ export declare function createServer<Ctx, R extends Router<Ctx, ProcsInit<Ctx>>>
|
|
|
88
157
|
router: R;
|
|
89
158
|
onError(error: {
|
|
90
159
|
error: Error;
|
|
91
|
-
req:
|
|
92
|
-
res:
|
|
160
|
+
req: KaitoRequest;
|
|
161
|
+
res: KaitoResponse;
|
|
93
162
|
}): Promise<{
|
|
94
|
-
|
|
163
|
+
status: number;
|
|
95
164
|
message: string;
|
|
96
165
|
}>;
|
|
97
|
-
log?: (message: string) => unknown | false;
|
|
98
|
-
}):
|
|
166
|
+
log?: ((message: string) => unknown) | false;
|
|
167
|
+
}): http.Server;
|
|
99
168
|
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
|
|
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
|
|
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,14 +100,128 @@ function _objectSpread2(target) {
|
|
|
97
100
|
return target;
|
|
98
101
|
}
|
|
99
102
|
|
|
100
|
-
|
|
103
|
+
class WrappedError extends Error {
|
|
104
|
+
static from(maybeError) {
|
|
105
|
+
if (maybeError instanceof Error) {
|
|
106
|
+
return maybeError;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return new WrappedError(maybeError);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
constructor(data) {
|
|
113
|
+
super('Something was thrown, but it was not an instance of Error, so a WrappedError was created.');
|
|
114
|
+
this.data = data;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function getLastEntryInMultiHeaderValue(headerValue) {
|
|
120
|
+
var normalized = Array.isArray(headerValue) ? headerValue.join(',') : headerValue;
|
|
121
|
+
var lastIndex = normalized.lastIndexOf(',');
|
|
122
|
+
return lastIndex === -1 ? normalized.trim() : normalized.slice(lastIndex + 1).trim();
|
|
123
|
+
} // Type for import('http').METHODS
|
|
124
|
+
|
|
125
|
+
function getInput(_x) {
|
|
126
|
+
return _getInput.apply(this, arguments);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function _getInput() {
|
|
130
|
+
_getInput = _asyncToGenerator(function* (req) {
|
|
131
|
+
if (req.method === 'GET') {
|
|
132
|
+
var input = req.url.searchParams.get('input');
|
|
133
|
+
|
|
134
|
+
if (!input) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return JSON.parse(input);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
var buffer = yield getRawBody__default["default"](req.raw);
|
|
142
|
+
|
|
143
|
+
switch (req.headers['content-type']) {
|
|
144
|
+
case 'application/json':
|
|
145
|
+
{
|
|
146
|
+
return JSON.parse(buffer.toString());
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
default:
|
|
150
|
+
{
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
return _getInput.apply(this, arguments);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
class KaitoRequest {
|
|
159
|
+
constructor(raw) {
|
|
160
|
+
this.raw = raw;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
get fullURL() {
|
|
164
|
+
var _this$raw$url;
|
|
101
165
|
|
|
102
|
-
(
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
166
|
+
return "".concat(this.protocol, "://").concat(this.hostname).concat((_this$raw$url = this.raw.url) !== null && _this$raw$url !== void 0 ? _this$raw$url : '');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
get url() {
|
|
170
|
+
return new URL(this.fullURL);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
get method() {
|
|
174
|
+
if (!this.raw.method) {
|
|
175
|
+
throw new Error('Request method is not defined, somehow...');
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return this.raw.method;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
get protocol() {
|
|
182
|
+
if (this.raw.socket instanceof tls.TLSSocket) {
|
|
183
|
+
return this.raw.socket.encrypted ? 'https' : 'http';
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return 'http';
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
get headers() {
|
|
190
|
+
return this.raw.headers;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
get hostname() {
|
|
194
|
+
var _this$raw$headers$hos, _this$raw$headers$Au;
|
|
195
|
+
|
|
196
|
+
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 : []);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
class KaitoResponse {
|
|
202
|
+
constructor(raw) {
|
|
203
|
+
this.raw = raw;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
header(key, value) {
|
|
207
|
+
this.raw.setHeader(key, value);
|
|
208
|
+
return this;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
status(code) {
|
|
212
|
+
this.raw.statusCode = code;
|
|
213
|
+
return this;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
json(data) {
|
|
217
|
+
var json = JSON.stringify(data);
|
|
218
|
+
this.raw.setHeader('Content-Type', 'application/json');
|
|
219
|
+
this.raw.setHeader('Content-Length', Buffer.byteLength(json));
|
|
220
|
+
this.raw.end(json);
|
|
221
|
+
return this;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
}
|
|
108
225
|
|
|
109
226
|
function createGetContext(getContext) {
|
|
110
227
|
return getContext;
|
|
@@ -120,15 +237,42 @@ class Router {
|
|
|
120
237
|
}));
|
|
121
238
|
});
|
|
122
239
|
|
|
123
|
-
_defineProperty(this, "merge", router =>
|
|
240
|
+
_defineProperty(this, "merge", (prefix, router) => {
|
|
241
|
+
var newProcs = Object.entries(router.getProcs()).reduce((all, entry) => {
|
|
242
|
+
var [name, proc] = entry;
|
|
243
|
+
return _objectSpread2(_objectSpread2({}, all), {}, {
|
|
244
|
+
["".concat(prefix).concat(name)]: _objectSpread2(_objectSpread2({}, proc), {}, {
|
|
245
|
+
name: "".concat(prefix).concat(name)
|
|
246
|
+
})
|
|
247
|
+
});
|
|
248
|
+
}, {});
|
|
249
|
+
|
|
250
|
+
var mergedProcs = _objectSpread2(_objectSpread2({}, this.procs), newProcs);
|
|
251
|
+
|
|
252
|
+
return new Router(mergedProcs);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
_defineProperty(this, "get", this.create('GET'));
|
|
124
256
|
|
|
125
|
-
_defineProperty(this, "
|
|
257
|
+
_defineProperty(this, "post", this.create('POST'));
|
|
126
258
|
|
|
127
|
-
_defineProperty(this, "
|
|
259
|
+
_defineProperty(this, "put", this.create('PUT'));
|
|
128
260
|
|
|
129
|
-
_defineProperty(this, "patch", this.create(
|
|
261
|
+
_defineProperty(this, "patch", this.create('PATCH'));
|
|
130
262
|
|
|
131
|
-
_defineProperty(this, "delete", this.create(
|
|
263
|
+
_defineProperty(this, "delete", this.create('DELETE'));
|
|
264
|
+
|
|
265
|
+
_defineProperty(this, "head", this.create('HEAD'));
|
|
266
|
+
|
|
267
|
+
_defineProperty(this, "options", this.create('OPTIONS'));
|
|
268
|
+
|
|
269
|
+
_defineProperty(this, "connect", this.create('CONNECT'));
|
|
270
|
+
|
|
271
|
+
_defineProperty(this, "trace", this.create('TRACE'));
|
|
272
|
+
|
|
273
|
+
_defineProperty(this, "acl", this.create('ACL'));
|
|
274
|
+
|
|
275
|
+
_defineProperty(this, "bind", this.create('BIND'));
|
|
132
276
|
|
|
133
277
|
this.procs = procs;
|
|
134
278
|
}
|
|
@@ -139,9 +283,9 @@ class Router {
|
|
|
139
283
|
|
|
140
284
|
}
|
|
141
285
|
class KaitoError extends Error {
|
|
142
|
-
constructor(
|
|
286
|
+
constructor(status, message, cause) {
|
|
143
287
|
super(message);
|
|
144
|
-
this.
|
|
288
|
+
this.status = status;
|
|
145
289
|
this.cause = cause;
|
|
146
290
|
}
|
|
147
291
|
|
|
@@ -150,79 +294,78 @@ function createRouter() {
|
|
|
150
294
|
return new Router({});
|
|
151
295
|
}
|
|
152
296
|
function createServer(config) {
|
|
153
|
-
var
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
data: null,
|
|
161
|
-
message: error.message
|
|
162
|
-
});
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
var {
|
|
167
|
-
code,
|
|
168
|
-
message
|
|
169
|
-
} = yield config.onError({
|
|
170
|
-
error,
|
|
171
|
-
req,
|
|
172
|
-
res
|
|
173
|
-
}).catch(() => ({
|
|
174
|
-
code: 500,
|
|
175
|
-
message: 'Something went wrong'
|
|
176
|
-
}));
|
|
177
|
-
yield res.status(code).send({
|
|
178
|
-
success: false,
|
|
179
|
-
data: null,
|
|
180
|
-
message
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
return function (_x, _x2, _x3) {
|
|
185
|
-
return _ref.apply(this, arguments);
|
|
186
|
-
};
|
|
187
|
-
}());
|
|
188
|
-
app.all('*', /*#__PURE__*/function () {
|
|
189
|
-
var _ref2 = _asyncToGenerator(function* (req, res) {
|
|
190
|
-
var _handler$input$parse, _handler$input;
|
|
191
|
-
|
|
192
|
-
var logMessage = "".concat(req.hostname, " ").concat(req.method, " ").concat(req.routerPath);
|
|
297
|
+
var log = message => {
|
|
298
|
+
if (config.log === undefined) {
|
|
299
|
+
console.log(message);
|
|
300
|
+
} else if (config.log) {
|
|
301
|
+
config.log(message);
|
|
302
|
+
}
|
|
303
|
+
};
|
|
193
304
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
305
|
+
var tree = config.router.getProcs();
|
|
306
|
+
var server = http__default["default"].createServer( /*#__PURE__*/function () {
|
|
307
|
+
var _ref = _asyncToGenerator(function* (incomingMessage, serverResponse) {
|
|
308
|
+
var start = Date.now();
|
|
309
|
+
var req = new KaitoRequest(incomingMessage);
|
|
310
|
+
var res = new KaitoResponse(serverResponse);
|
|
199
311
|
|
|
200
|
-
|
|
201
|
-
|
|
312
|
+
try {
|
|
313
|
+
var _handler$input, _yield$getInput;
|
|
202
314
|
|
|
203
|
-
|
|
204
|
-
throw new KaitoError(404, "Cannot ".concat(req.method, " this route."));
|
|
205
|
-
}
|
|
315
|
+
var handler = tree[req.url.pathname];
|
|
206
316
|
|
|
207
|
-
|
|
317
|
+
if (!handler) {
|
|
318
|
+
throw new KaitoError(404, "Cannot ".concat(req.method, " this route."));
|
|
319
|
+
}
|
|
208
320
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
213
|
-
data: yield handler.run({
|
|
321
|
+
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);
|
|
322
|
+
var context = yield config.getContext(req, res);
|
|
323
|
+
var data = yield handler.run({
|
|
214
324
|
ctx: context,
|
|
215
325
|
input
|
|
216
|
-
})
|
|
217
|
-
|
|
218
|
-
|
|
326
|
+
});
|
|
327
|
+
res.json({
|
|
328
|
+
success: true,
|
|
329
|
+
data,
|
|
330
|
+
message: 'OK'
|
|
331
|
+
});
|
|
332
|
+
} catch (error) {
|
|
333
|
+
if (error instanceof KaitoError) {
|
|
334
|
+
res.status(error.status).json({
|
|
335
|
+
success: false,
|
|
336
|
+
data: null,
|
|
337
|
+
message: error.message
|
|
338
|
+
});
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
var {
|
|
343
|
+
status: _status,
|
|
344
|
+
message: _message
|
|
345
|
+
} = yield config.onError({
|
|
346
|
+
error: WrappedError.from(error),
|
|
347
|
+
req,
|
|
348
|
+
res
|
|
349
|
+
}).catch(() => ({
|
|
350
|
+
status: 500,
|
|
351
|
+
message: 'Something went wrong'
|
|
352
|
+
}));
|
|
353
|
+
res.status(_status).json({
|
|
354
|
+
success: false,
|
|
355
|
+
data: null,
|
|
356
|
+
message: _message
|
|
357
|
+
});
|
|
358
|
+
} finally {
|
|
359
|
+
var finish = Date.now();
|
|
360
|
+
log("".concat(req.method, " ").concat(req.fullURL, " ").concat(res.raw.statusCode, " ").concat(finish - start, "ms"));
|
|
361
|
+
}
|
|
219
362
|
});
|
|
220
363
|
|
|
221
|
-
return function (
|
|
222
|
-
return
|
|
364
|
+
return function (_x, _x2) {
|
|
365
|
+
return _ref.apply(this, arguments);
|
|
223
366
|
};
|
|
224
367
|
}());
|
|
225
|
-
return
|
|
368
|
+
return server;
|
|
226
369
|
}
|
|
227
370
|
|
|
228
371
|
exports.KaitoError = KaitoError;
|
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var
|
|
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
|
|
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,14 +100,128 @@ function _objectSpread2(target) {
|
|
|
97
100
|
return target;
|
|
98
101
|
}
|
|
99
102
|
|
|
100
|
-
|
|
103
|
+
class WrappedError extends Error {
|
|
104
|
+
static from(maybeError) {
|
|
105
|
+
if (maybeError instanceof Error) {
|
|
106
|
+
return maybeError;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return new WrappedError(maybeError);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
constructor(data) {
|
|
113
|
+
super('Something was thrown, but it was not an instance of Error, so a WrappedError was created.');
|
|
114
|
+
this.data = data;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function getLastEntryInMultiHeaderValue(headerValue) {
|
|
120
|
+
var normalized = Array.isArray(headerValue) ? headerValue.join(',') : headerValue;
|
|
121
|
+
var lastIndex = normalized.lastIndexOf(',');
|
|
122
|
+
return lastIndex === -1 ? normalized.trim() : normalized.slice(lastIndex + 1).trim();
|
|
123
|
+
} // Type for import('http').METHODS
|
|
124
|
+
|
|
125
|
+
function getInput(_x) {
|
|
126
|
+
return _getInput.apply(this, arguments);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function _getInput() {
|
|
130
|
+
_getInput = _asyncToGenerator(function* (req) {
|
|
131
|
+
if (req.method === 'GET') {
|
|
132
|
+
var input = req.url.searchParams.get('input');
|
|
133
|
+
|
|
134
|
+
if (!input) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return JSON.parse(input);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
var buffer = yield getRawBody__default["default"](req.raw);
|
|
142
|
+
|
|
143
|
+
switch (req.headers['content-type']) {
|
|
144
|
+
case 'application/json':
|
|
145
|
+
{
|
|
146
|
+
return JSON.parse(buffer.toString());
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
default:
|
|
150
|
+
{
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
return _getInput.apply(this, arguments);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
class KaitoRequest {
|
|
159
|
+
constructor(raw) {
|
|
160
|
+
this.raw = raw;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
get fullURL() {
|
|
164
|
+
var _this$raw$url;
|
|
101
165
|
|
|
102
|
-
(
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
166
|
+
return "".concat(this.protocol, "://").concat(this.hostname).concat((_this$raw$url = this.raw.url) !== null && _this$raw$url !== void 0 ? _this$raw$url : '');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
get url() {
|
|
170
|
+
return new URL(this.fullURL);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
get method() {
|
|
174
|
+
if (!this.raw.method) {
|
|
175
|
+
throw new Error('Request method is not defined, somehow...');
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return this.raw.method;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
get protocol() {
|
|
182
|
+
if (this.raw.socket instanceof tls.TLSSocket) {
|
|
183
|
+
return this.raw.socket.encrypted ? 'https' : 'http';
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return 'http';
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
get headers() {
|
|
190
|
+
return this.raw.headers;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
get hostname() {
|
|
194
|
+
var _this$raw$headers$hos, _this$raw$headers$Au;
|
|
195
|
+
|
|
196
|
+
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 : []);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
class KaitoResponse {
|
|
202
|
+
constructor(raw) {
|
|
203
|
+
this.raw = raw;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
header(key, value) {
|
|
207
|
+
this.raw.setHeader(key, value);
|
|
208
|
+
return this;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
status(code) {
|
|
212
|
+
this.raw.statusCode = code;
|
|
213
|
+
return this;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
json(data) {
|
|
217
|
+
var json = JSON.stringify(data);
|
|
218
|
+
this.raw.setHeader('Content-Type', 'application/json');
|
|
219
|
+
this.raw.setHeader('Content-Length', Buffer.byteLength(json));
|
|
220
|
+
this.raw.end(json);
|
|
221
|
+
return this;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
}
|
|
108
225
|
|
|
109
226
|
function createGetContext(getContext) {
|
|
110
227
|
return getContext;
|
|
@@ -120,15 +237,42 @@ class Router {
|
|
|
120
237
|
}));
|
|
121
238
|
});
|
|
122
239
|
|
|
123
|
-
_defineProperty(this, "merge", router =>
|
|
240
|
+
_defineProperty(this, "merge", (prefix, router) => {
|
|
241
|
+
var newProcs = Object.entries(router.getProcs()).reduce((all, entry) => {
|
|
242
|
+
var [name, proc] = entry;
|
|
243
|
+
return _objectSpread2(_objectSpread2({}, all), {}, {
|
|
244
|
+
["".concat(prefix).concat(name)]: _objectSpread2(_objectSpread2({}, proc), {}, {
|
|
245
|
+
name: "".concat(prefix).concat(name)
|
|
246
|
+
})
|
|
247
|
+
});
|
|
248
|
+
}, {});
|
|
249
|
+
|
|
250
|
+
var mergedProcs = _objectSpread2(_objectSpread2({}, this.procs), newProcs);
|
|
251
|
+
|
|
252
|
+
return new Router(mergedProcs);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
_defineProperty(this, "get", this.create('GET'));
|
|
124
256
|
|
|
125
|
-
_defineProperty(this, "
|
|
257
|
+
_defineProperty(this, "post", this.create('POST'));
|
|
126
258
|
|
|
127
|
-
_defineProperty(this, "
|
|
259
|
+
_defineProperty(this, "put", this.create('PUT'));
|
|
128
260
|
|
|
129
|
-
_defineProperty(this, "patch", this.create(
|
|
261
|
+
_defineProperty(this, "patch", this.create('PATCH'));
|
|
130
262
|
|
|
131
|
-
_defineProperty(this, "delete", this.create(
|
|
263
|
+
_defineProperty(this, "delete", this.create('DELETE'));
|
|
264
|
+
|
|
265
|
+
_defineProperty(this, "head", this.create('HEAD'));
|
|
266
|
+
|
|
267
|
+
_defineProperty(this, "options", this.create('OPTIONS'));
|
|
268
|
+
|
|
269
|
+
_defineProperty(this, "connect", this.create('CONNECT'));
|
|
270
|
+
|
|
271
|
+
_defineProperty(this, "trace", this.create('TRACE'));
|
|
272
|
+
|
|
273
|
+
_defineProperty(this, "acl", this.create('ACL'));
|
|
274
|
+
|
|
275
|
+
_defineProperty(this, "bind", this.create('BIND'));
|
|
132
276
|
|
|
133
277
|
this.procs = procs;
|
|
134
278
|
}
|
|
@@ -139,9 +283,9 @@ class Router {
|
|
|
139
283
|
|
|
140
284
|
}
|
|
141
285
|
class KaitoError extends Error {
|
|
142
|
-
constructor(
|
|
286
|
+
constructor(status, message, cause) {
|
|
143
287
|
super(message);
|
|
144
|
-
this.
|
|
288
|
+
this.status = status;
|
|
145
289
|
this.cause = cause;
|
|
146
290
|
}
|
|
147
291
|
|
|
@@ -150,79 +294,78 @@ function createRouter() {
|
|
|
150
294
|
return new Router({});
|
|
151
295
|
}
|
|
152
296
|
function createServer(config) {
|
|
153
|
-
var
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
data: null,
|
|
161
|
-
message: error.message
|
|
162
|
-
});
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
var {
|
|
167
|
-
code,
|
|
168
|
-
message
|
|
169
|
-
} = yield config.onError({
|
|
170
|
-
error,
|
|
171
|
-
req,
|
|
172
|
-
res
|
|
173
|
-
}).catch(() => ({
|
|
174
|
-
code: 500,
|
|
175
|
-
message: 'Something went wrong'
|
|
176
|
-
}));
|
|
177
|
-
yield res.status(code).send({
|
|
178
|
-
success: false,
|
|
179
|
-
data: null,
|
|
180
|
-
message
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
return function (_x, _x2, _x3) {
|
|
185
|
-
return _ref.apply(this, arguments);
|
|
186
|
-
};
|
|
187
|
-
}());
|
|
188
|
-
app.all('*', /*#__PURE__*/function () {
|
|
189
|
-
var _ref2 = _asyncToGenerator(function* (req, res) {
|
|
190
|
-
var _handler$input$parse, _handler$input;
|
|
191
|
-
|
|
192
|
-
var logMessage = "".concat(req.hostname, " ").concat(req.method, " ").concat(req.routerPath);
|
|
297
|
+
var log = message => {
|
|
298
|
+
if (config.log === undefined) {
|
|
299
|
+
console.log(message);
|
|
300
|
+
} else if (config.log) {
|
|
301
|
+
config.log(message);
|
|
302
|
+
}
|
|
303
|
+
};
|
|
193
304
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
305
|
+
var tree = config.router.getProcs();
|
|
306
|
+
var server = http__default["default"].createServer( /*#__PURE__*/function () {
|
|
307
|
+
var _ref = _asyncToGenerator(function* (incomingMessage, serverResponse) {
|
|
308
|
+
var start = Date.now();
|
|
309
|
+
var req = new KaitoRequest(incomingMessage);
|
|
310
|
+
var res = new KaitoResponse(serverResponse);
|
|
199
311
|
|
|
200
|
-
|
|
201
|
-
|
|
312
|
+
try {
|
|
313
|
+
var _handler$input, _yield$getInput;
|
|
202
314
|
|
|
203
|
-
|
|
204
|
-
throw new KaitoError(404, "Cannot ".concat(req.method, " this route."));
|
|
205
|
-
}
|
|
315
|
+
var handler = tree[req.url.pathname];
|
|
206
316
|
|
|
207
|
-
|
|
317
|
+
if (!handler) {
|
|
318
|
+
throw new KaitoError(404, "Cannot ".concat(req.method, " this route."));
|
|
319
|
+
}
|
|
208
320
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
213
|
-
data: yield handler.run({
|
|
321
|
+
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);
|
|
322
|
+
var context = yield config.getContext(req, res);
|
|
323
|
+
var data = yield handler.run({
|
|
214
324
|
ctx: context,
|
|
215
325
|
input
|
|
216
|
-
})
|
|
217
|
-
|
|
218
|
-
|
|
326
|
+
});
|
|
327
|
+
res.json({
|
|
328
|
+
success: true,
|
|
329
|
+
data,
|
|
330
|
+
message: 'OK'
|
|
331
|
+
});
|
|
332
|
+
} catch (error) {
|
|
333
|
+
if (error instanceof KaitoError) {
|
|
334
|
+
res.status(error.status).json({
|
|
335
|
+
success: false,
|
|
336
|
+
data: null,
|
|
337
|
+
message: error.message
|
|
338
|
+
});
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
var {
|
|
343
|
+
status: _status,
|
|
344
|
+
message: _message
|
|
345
|
+
} = yield config.onError({
|
|
346
|
+
error: WrappedError.from(error),
|
|
347
|
+
req,
|
|
348
|
+
res
|
|
349
|
+
}).catch(() => ({
|
|
350
|
+
status: 500,
|
|
351
|
+
message: 'Something went wrong'
|
|
352
|
+
}));
|
|
353
|
+
res.status(_status).json({
|
|
354
|
+
success: false,
|
|
355
|
+
data: null,
|
|
356
|
+
message: _message
|
|
357
|
+
});
|
|
358
|
+
} finally {
|
|
359
|
+
var finish = Date.now();
|
|
360
|
+
log("".concat(req.method, " ").concat(req.fullURL, " ").concat(res.raw.statusCode, " ").concat(finish - start, "ms"));
|
|
361
|
+
}
|
|
219
362
|
});
|
|
220
363
|
|
|
221
|
-
return function (
|
|
222
|
-
return
|
|
364
|
+
return function (_x, _x2) {
|
|
365
|
+
return _ref.apply(this, arguments);
|
|
223
366
|
};
|
|
224
367
|
}());
|
|
225
|
-
return
|
|
368
|
+
return server;
|
|
226
369
|
}
|
|
227
370
|
|
|
228
371
|
exports.KaitoError = KaitoError;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import http from 'http';
|
|
2
|
+
import { TLSSocket } from 'tls';
|
|
3
|
+
import getRawBody from 'raw-body';
|
|
2
4
|
|
|
3
5
|
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
4
6
|
try {
|
|
@@ -89,14 +91,128 @@ function _objectSpread2(target) {
|
|
|
89
91
|
return target;
|
|
90
92
|
}
|
|
91
93
|
|
|
92
|
-
|
|
94
|
+
class WrappedError extends Error {
|
|
95
|
+
static from(maybeError) {
|
|
96
|
+
if (maybeError instanceof Error) {
|
|
97
|
+
return maybeError;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return new WrappedError(maybeError);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
constructor(data) {
|
|
104
|
+
super('Something was thrown, but it was not an instance of Error, so a WrappedError was created.');
|
|
105
|
+
this.data = data;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function getLastEntryInMultiHeaderValue(headerValue) {
|
|
111
|
+
var normalized = Array.isArray(headerValue) ? headerValue.join(',') : headerValue;
|
|
112
|
+
var lastIndex = normalized.lastIndexOf(',');
|
|
113
|
+
return lastIndex === -1 ? normalized.trim() : normalized.slice(lastIndex + 1).trim();
|
|
114
|
+
} // Type for import('http').METHODS
|
|
115
|
+
|
|
116
|
+
function getInput(_x) {
|
|
117
|
+
return _getInput.apply(this, arguments);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function _getInput() {
|
|
121
|
+
_getInput = _asyncToGenerator(function* (req) {
|
|
122
|
+
if (req.method === 'GET') {
|
|
123
|
+
var input = req.url.searchParams.get('input');
|
|
124
|
+
|
|
125
|
+
if (!input) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return JSON.parse(input);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
var buffer = yield getRawBody(req.raw);
|
|
133
|
+
|
|
134
|
+
switch (req.headers['content-type']) {
|
|
135
|
+
case 'application/json':
|
|
136
|
+
{
|
|
137
|
+
return JSON.parse(buffer.toString());
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
default:
|
|
141
|
+
{
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
return _getInput.apply(this, arguments);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
class KaitoRequest {
|
|
150
|
+
constructor(raw) {
|
|
151
|
+
this.raw = raw;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
get fullURL() {
|
|
155
|
+
var _this$raw$url;
|
|
93
156
|
|
|
94
|
-
(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
157
|
+
return "".concat(this.protocol, "://").concat(this.hostname).concat((_this$raw$url = this.raw.url) !== null && _this$raw$url !== void 0 ? _this$raw$url : '');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
get url() {
|
|
161
|
+
return new URL(this.fullURL);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
get method() {
|
|
165
|
+
if (!this.raw.method) {
|
|
166
|
+
throw new Error('Request method is not defined, somehow...');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return this.raw.method;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
get protocol() {
|
|
173
|
+
if (this.raw.socket instanceof TLSSocket) {
|
|
174
|
+
return this.raw.socket.encrypted ? 'https' : 'http';
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return 'http';
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
get headers() {
|
|
181
|
+
return this.raw.headers;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
get hostname() {
|
|
185
|
+
var _this$raw$headers$hos, _this$raw$headers$Au;
|
|
186
|
+
|
|
187
|
+
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 : []);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
class KaitoResponse {
|
|
193
|
+
constructor(raw) {
|
|
194
|
+
this.raw = raw;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
header(key, value) {
|
|
198
|
+
this.raw.setHeader(key, value);
|
|
199
|
+
return this;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
status(code) {
|
|
203
|
+
this.raw.statusCode = code;
|
|
204
|
+
return this;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
json(data) {
|
|
208
|
+
var json = JSON.stringify(data);
|
|
209
|
+
this.raw.setHeader('Content-Type', 'application/json');
|
|
210
|
+
this.raw.setHeader('Content-Length', Buffer.byteLength(json));
|
|
211
|
+
this.raw.end(json);
|
|
212
|
+
return this;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
}
|
|
100
216
|
|
|
101
217
|
function createGetContext(getContext) {
|
|
102
218
|
return getContext;
|
|
@@ -112,15 +228,42 @@ class Router {
|
|
|
112
228
|
}));
|
|
113
229
|
});
|
|
114
230
|
|
|
115
|
-
_defineProperty(this, "merge", router =>
|
|
231
|
+
_defineProperty(this, "merge", (prefix, router) => {
|
|
232
|
+
var newProcs = Object.entries(router.getProcs()).reduce((all, entry) => {
|
|
233
|
+
var [name, proc] = entry;
|
|
234
|
+
return _objectSpread2(_objectSpread2({}, all), {}, {
|
|
235
|
+
["".concat(prefix).concat(name)]: _objectSpread2(_objectSpread2({}, proc), {}, {
|
|
236
|
+
name: "".concat(prefix).concat(name)
|
|
237
|
+
})
|
|
238
|
+
});
|
|
239
|
+
}, {});
|
|
240
|
+
|
|
241
|
+
var mergedProcs = _objectSpread2(_objectSpread2({}, this.procs), newProcs);
|
|
242
|
+
|
|
243
|
+
return new Router(mergedProcs);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
_defineProperty(this, "get", this.create('GET'));
|
|
116
247
|
|
|
117
|
-
_defineProperty(this, "
|
|
248
|
+
_defineProperty(this, "post", this.create('POST'));
|
|
118
249
|
|
|
119
|
-
_defineProperty(this, "
|
|
250
|
+
_defineProperty(this, "put", this.create('PUT'));
|
|
120
251
|
|
|
121
|
-
_defineProperty(this, "patch", this.create(
|
|
252
|
+
_defineProperty(this, "patch", this.create('PATCH'));
|
|
122
253
|
|
|
123
|
-
_defineProperty(this, "delete", this.create(
|
|
254
|
+
_defineProperty(this, "delete", this.create('DELETE'));
|
|
255
|
+
|
|
256
|
+
_defineProperty(this, "head", this.create('HEAD'));
|
|
257
|
+
|
|
258
|
+
_defineProperty(this, "options", this.create('OPTIONS'));
|
|
259
|
+
|
|
260
|
+
_defineProperty(this, "connect", this.create('CONNECT'));
|
|
261
|
+
|
|
262
|
+
_defineProperty(this, "trace", this.create('TRACE'));
|
|
263
|
+
|
|
264
|
+
_defineProperty(this, "acl", this.create('ACL'));
|
|
265
|
+
|
|
266
|
+
_defineProperty(this, "bind", this.create('BIND'));
|
|
124
267
|
|
|
125
268
|
this.procs = procs;
|
|
126
269
|
}
|
|
@@ -131,9 +274,9 @@ class Router {
|
|
|
131
274
|
|
|
132
275
|
}
|
|
133
276
|
class KaitoError extends Error {
|
|
134
|
-
constructor(
|
|
277
|
+
constructor(status, message, cause) {
|
|
135
278
|
super(message);
|
|
136
|
-
this.
|
|
279
|
+
this.status = status;
|
|
137
280
|
this.cause = cause;
|
|
138
281
|
}
|
|
139
282
|
|
|
@@ -142,79 +285,78 @@ function createRouter() {
|
|
|
142
285
|
return new Router({});
|
|
143
286
|
}
|
|
144
287
|
function createServer(config) {
|
|
145
|
-
var
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
data: null,
|
|
153
|
-
message: error.message
|
|
154
|
-
});
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
var {
|
|
159
|
-
code,
|
|
160
|
-
message
|
|
161
|
-
} = yield config.onError({
|
|
162
|
-
error,
|
|
163
|
-
req,
|
|
164
|
-
res
|
|
165
|
-
}).catch(() => ({
|
|
166
|
-
code: 500,
|
|
167
|
-
message: 'Something went wrong'
|
|
168
|
-
}));
|
|
169
|
-
yield res.status(code).send({
|
|
170
|
-
success: false,
|
|
171
|
-
data: null,
|
|
172
|
-
message
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
return function (_x, _x2, _x3) {
|
|
177
|
-
return _ref.apply(this, arguments);
|
|
178
|
-
};
|
|
179
|
-
}());
|
|
180
|
-
app.all('*', /*#__PURE__*/function () {
|
|
181
|
-
var _ref2 = _asyncToGenerator(function* (req, res) {
|
|
182
|
-
var _handler$input$parse, _handler$input;
|
|
183
|
-
|
|
184
|
-
var logMessage = "".concat(req.hostname, " ").concat(req.method, " ").concat(req.routerPath);
|
|
288
|
+
var log = message => {
|
|
289
|
+
if (config.log === undefined) {
|
|
290
|
+
console.log(message);
|
|
291
|
+
} else if (config.log) {
|
|
292
|
+
config.log(message);
|
|
293
|
+
}
|
|
294
|
+
};
|
|
185
295
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
296
|
+
var tree = config.router.getProcs();
|
|
297
|
+
var server = http.createServer( /*#__PURE__*/function () {
|
|
298
|
+
var _ref = _asyncToGenerator(function* (incomingMessage, serverResponse) {
|
|
299
|
+
var start = Date.now();
|
|
300
|
+
var req = new KaitoRequest(incomingMessage);
|
|
301
|
+
var res = new KaitoResponse(serverResponse);
|
|
191
302
|
|
|
192
|
-
|
|
193
|
-
|
|
303
|
+
try {
|
|
304
|
+
var _handler$input, _yield$getInput;
|
|
194
305
|
|
|
195
|
-
|
|
196
|
-
throw new KaitoError(404, "Cannot ".concat(req.method, " this route."));
|
|
197
|
-
}
|
|
306
|
+
var handler = tree[req.url.pathname];
|
|
198
307
|
|
|
199
|
-
|
|
308
|
+
if (!handler) {
|
|
309
|
+
throw new KaitoError(404, "Cannot ".concat(req.method, " this route."));
|
|
310
|
+
}
|
|
200
311
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
205
|
-
data: yield handler.run({
|
|
312
|
+
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);
|
|
313
|
+
var context = yield config.getContext(req, res);
|
|
314
|
+
var data = yield handler.run({
|
|
206
315
|
ctx: context,
|
|
207
316
|
input
|
|
208
|
-
})
|
|
209
|
-
|
|
210
|
-
|
|
317
|
+
});
|
|
318
|
+
res.json({
|
|
319
|
+
success: true,
|
|
320
|
+
data,
|
|
321
|
+
message: 'OK'
|
|
322
|
+
});
|
|
323
|
+
} catch (error) {
|
|
324
|
+
if (error instanceof KaitoError) {
|
|
325
|
+
res.status(error.status).json({
|
|
326
|
+
success: false,
|
|
327
|
+
data: null,
|
|
328
|
+
message: error.message
|
|
329
|
+
});
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
var {
|
|
334
|
+
status: _status,
|
|
335
|
+
message: _message
|
|
336
|
+
} = yield config.onError({
|
|
337
|
+
error: WrappedError.from(error),
|
|
338
|
+
req,
|
|
339
|
+
res
|
|
340
|
+
}).catch(() => ({
|
|
341
|
+
status: 500,
|
|
342
|
+
message: 'Something went wrong'
|
|
343
|
+
}));
|
|
344
|
+
res.status(_status).json({
|
|
345
|
+
success: false,
|
|
346
|
+
data: null,
|
|
347
|
+
message: _message
|
|
348
|
+
});
|
|
349
|
+
} finally {
|
|
350
|
+
var finish = Date.now();
|
|
351
|
+
log("".concat(req.method, " ").concat(req.fullURL, " ").concat(res.raw.statusCode, " ").concat(finish - start, "ms"));
|
|
352
|
+
}
|
|
211
353
|
});
|
|
212
354
|
|
|
213
|
-
return function (
|
|
214
|
-
return
|
|
355
|
+
return function (_x, _x2) {
|
|
356
|
+
return _ref.apply(this, arguments);
|
|
215
357
|
};
|
|
216
358
|
}());
|
|
217
|
-
return
|
|
359
|
+
return server;
|
|
218
360
|
}
|
|
219
361
|
|
|
220
|
-
export { KaitoError,
|
|
362
|
+
export { KaitoError, Router, createGetContext, createRouter, createServer };
|
package/package.json
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaito-http/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Functional HTTP Framework for TypeScript",
|
|
5
|
-
"repository":
|
|
6
|
-
"type": "git",
|
|
7
|
-
"url": "git+https://github.com/kaito-http/kaito.git"
|
|
8
|
-
},
|
|
5
|
+
"repository": "https://github.com/kaito-http/kaito",
|
|
9
6
|
"author": "Alistair Smith <hi@alistair.sh>",
|
|
10
7
|
"license": "MIT",
|
|
11
8
|
"main": "dist/kaito-http-core.cjs.js",
|
|
@@ -14,7 +11,6 @@
|
|
|
14
11
|
"devDependencies": {
|
|
15
12
|
"@types/body-parser": "^1.19.2",
|
|
16
13
|
"@types/node": "^17.0.24",
|
|
17
|
-
"@types/node-fetch": "^2.6.1",
|
|
18
14
|
"typescript": "4.6",
|
|
19
15
|
"zod": "^3.14.4"
|
|
20
16
|
},
|
|
@@ -23,15 +19,19 @@
|
|
|
23
19
|
"readme.md",
|
|
24
20
|
"dist"
|
|
25
21
|
],
|
|
26
|
-
"dependencies": {
|
|
27
|
-
"colorette": "^2.0.16",
|
|
28
|
-
"fastify": "^3.28.0"
|
|
29
|
-
},
|
|
30
22
|
"bugs": {
|
|
31
23
|
"url": "https://github.com/kaito-http/kaito/issues"
|
|
32
24
|
},
|
|
33
|
-
"homepage": "https://github.com/kaito-http/kaito
|
|
25
|
+
"homepage": "https://github.com/kaito-http/kaito",
|
|
34
26
|
"peerDependencies": {
|
|
35
27
|
"zod": "*"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"typescript",
|
|
31
|
+
"http",
|
|
32
|
+
"framework"
|
|
33
|
+
],
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"raw-body": "^2.5.1"
|
|
36
36
|
}
|
|
37
37
|
}
|