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