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