@kevisual/router 0.1.2 → 0.1.4
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/package.json +3 -3
- package/src/commander.ts +103 -23
- package/dist/app.d.ts +0 -5
- package/dist/app.js +0 -20175
- package/dist/commander.d.ts +0 -816
- package/dist/commander.js +0 -2790
- package/dist/opencode.d.ts +0 -811
- package/dist/opencode.js +0 -15308
- package/dist/router-browser.d.ts +0 -676
- package/dist/router-browser.js +0 -33383
- package/dist/router-define.d.ts +0 -560
- package/dist/router-define.js +0 -135
- package/dist/router-simple.d.ts +0 -110
- package/dist/router-simple.js +0 -708
- package/dist/router.d.ts +0 -1082
- package/dist/router.js +0 -19059
- package/dist/ws.d.ts +0 -860
- package/dist/ws.js +0 -3041
package/dist/router-simple.js
DELETED
|
@@ -1,708 +0,0 @@
|
|
|
1
|
-
var __create = Object.create;
|
|
2
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
function __accessProp(key) {
|
|
7
|
-
return this[key];
|
|
8
|
-
}
|
|
9
|
-
var __toESMCache_node;
|
|
10
|
-
var __toESMCache_esm;
|
|
11
|
-
var __toESM = (mod, isNodeMode, target) => {
|
|
12
|
-
var canCache = mod != null && typeof mod === "object";
|
|
13
|
-
if (canCache) {
|
|
14
|
-
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
15
|
-
var cached = cache.get(mod);
|
|
16
|
-
if (cached)
|
|
17
|
-
return cached;
|
|
18
|
-
}
|
|
19
|
-
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
20
|
-
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
21
|
-
for (let key of __getOwnPropNames(mod))
|
|
22
|
-
if (!__hasOwnProp.call(to, key))
|
|
23
|
-
__defProp(to, key, {
|
|
24
|
-
get: __accessProp.bind(mod, key),
|
|
25
|
-
enumerable: true
|
|
26
|
-
});
|
|
27
|
-
if (canCache)
|
|
28
|
-
cache.set(mod, to);
|
|
29
|
-
return to;
|
|
30
|
-
};
|
|
31
|
-
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
32
|
-
|
|
33
|
-
// ../../node_modules/.pnpm/path-to-regexp@8.3.0/node_modules/path-to-regexp/dist/index.js
|
|
34
|
-
var require_dist = __commonJS((exports) => {
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.PathError = exports.TokenData = undefined;
|
|
37
|
-
exports.parse = parse;
|
|
38
|
-
exports.compile = compile;
|
|
39
|
-
exports.match = match;
|
|
40
|
-
exports.pathToRegexp = pathToRegexp;
|
|
41
|
-
exports.stringify = stringify;
|
|
42
|
-
var DEFAULT_DELIMITER = "/";
|
|
43
|
-
var NOOP_VALUE = (value) => value;
|
|
44
|
-
var ID_START = /^[$_\p{ID_Start}]$/u;
|
|
45
|
-
var ID_CONTINUE = /^[$\u200c\u200d\p{ID_Continue}]$/u;
|
|
46
|
-
var SIMPLE_TOKENS = {
|
|
47
|
-
"{": "{",
|
|
48
|
-
"}": "}",
|
|
49
|
-
"(": "(",
|
|
50
|
-
")": ")",
|
|
51
|
-
"[": "[",
|
|
52
|
-
"]": "]",
|
|
53
|
-
"+": "+",
|
|
54
|
-
"?": "?",
|
|
55
|
-
"!": "!"
|
|
56
|
-
};
|
|
57
|
-
function escapeText(str) {
|
|
58
|
-
return str.replace(/[{}()\[\]+?!:*\\]/g, "\\$&");
|
|
59
|
-
}
|
|
60
|
-
function escape(str) {
|
|
61
|
-
return str.replace(/[.+*?^${}()[\]|/\\]/g, "\\$&");
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
class TokenData {
|
|
65
|
-
constructor(tokens, originalPath) {
|
|
66
|
-
this.tokens = tokens;
|
|
67
|
-
this.originalPath = originalPath;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
exports.TokenData = TokenData;
|
|
71
|
-
|
|
72
|
-
class PathError extends TypeError {
|
|
73
|
-
constructor(message, originalPath) {
|
|
74
|
-
let text = message;
|
|
75
|
-
if (originalPath)
|
|
76
|
-
text += `: ${originalPath}`;
|
|
77
|
-
text += `; visit https://git.new/pathToRegexpError for info`;
|
|
78
|
-
super(text);
|
|
79
|
-
this.originalPath = originalPath;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
exports.PathError = PathError;
|
|
83
|
-
function parse(str, options = {}) {
|
|
84
|
-
const { encodePath = NOOP_VALUE } = options;
|
|
85
|
-
const chars = [...str];
|
|
86
|
-
const tokens = [];
|
|
87
|
-
let index = 0;
|
|
88
|
-
let pos = 0;
|
|
89
|
-
function name() {
|
|
90
|
-
let value = "";
|
|
91
|
-
if (ID_START.test(chars[index])) {
|
|
92
|
-
do {
|
|
93
|
-
value += chars[index++];
|
|
94
|
-
} while (ID_CONTINUE.test(chars[index]));
|
|
95
|
-
} else if (chars[index] === '"') {
|
|
96
|
-
let quoteStart = index;
|
|
97
|
-
while (index++ < chars.length) {
|
|
98
|
-
if (chars[index] === '"') {
|
|
99
|
-
index++;
|
|
100
|
-
quoteStart = 0;
|
|
101
|
-
break;
|
|
102
|
-
}
|
|
103
|
-
if (chars[index] === "\\")
|
|
104
|
-
index++;
|
|
105
|
-
value += chars[index];
|
|
106
|
-
}
|
|
107
|
-
if (quoteStart) {
|
|
108
|
-
throw new PathError(`Unterminated quote at index ${quoteStart}`, str);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
if (!value) {
|
|
112
|
-
throw new PathError(`Missing parameter name at index ${index}`, str);
|
|
113
|
-
}
|
|
114
|
-
return value;
|
|
115
|
-
}
|
|
116
|
-
while (index < chars.length) {
|
|
117
|
-
const value = chars[index];
|
|
118
|
-
const type = SIMPLE_TOKENS[value];
|
|
119
|
-
if (type) {
|
|
120
|
-
tokens.push({ type, index: index++, value });
|
|
121
|
-
} else if (value === "\\") {
|
|
122
|
-
tokens.push({ type: "escape", index: index++, value: chars[index++] });
|
|
123
|
-
} else if (value === ":") {
|
|
124
|
-
tokens.push({ type: "param", index: index++, value: name() });
|
|
125
|
-
} else if (value === "*") {
|
|
126
|
-
tokens.push({ type: "wildcard", index: index++, value: name() });
|
|
127
|
-
} else {
|
|
128
|
-
tokens.push({ type: "char", index: index++, value });
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
tokens.push({ type: "end", index, value: "" });
|
|
132
|
-
function consumeUntil(endType) {
|
|
133
|
-
const output = [];
|
|
134
|
-
while (true) {
|
|
135
|
-
const token = tokens[pos++];
|
|
136
|
-
if (token.type === endType)
|
|
137
|
-
break;
|
|
138
|
-
if (token.type === "char" || token.type === "escape") {
|
|
139
|
-
let path = token.value;
|
|
140
|
-
let cur = tokens[pos];
|
|
141
|
-
while (cur.type === "char" || cur.type === "escape") {
|
|
142
|
-
path += cur.value;
|
|
143
|
-
cur = tokens[++pos];
|
|
144
|
-
}
|
|
145
|
-
output.push({
|
|
146
|
-
type: "text",
|
|
147
|
-
value: encodePath(path)
|
|
148
|
-
});
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
if (token.type === "param" || token.type === "wildcard") {
|
|
152
|
-
output.push({
|
|
153
|
-
type: token.type,
|
|
154
|
-
name: token.value
|
|
155
|
-
});
|
|
156
|
-
continue;
|
|
157
|
-
}
|
|
158
|
-
if (token.type === "{") {
|
|
159
|
-
output.push({
|
|
160
|
-
type: "group",
|
|
161
|
-
tokens: consumeUntil("}")
|
|
162
|
-
});
|
|
163
|
-
continue;
|
|
164
|
-
}
|
|
165
|
-
throw new PathError(`Unexpected ${token.type} at index ${token.index}, expected ${endType}`, str);
|
|
166
|
-
}
|
|
167
|
-
return output;
|
|
168
|
-
}
|
|
169
|
-
return new TokenData(consumeUntil("end"), str);
|
|
170
|
-
}
|
|
171
|
-
function compile(path, options = {}) {
|
|
172
|
-
const { encode = encodeURIComponent, delimiter = DEFAULT_DELIMITER } = options;
|
|
173
|
-
const data = typeof path === "object" ? path : parse(path, options);
|
|
174
|
-
const fn = tokensToFunction(data.tokens, delimiter, encode);
|
|
175
|
-
return function path2(params = {}) {
|
|
176
|
-
const [path3, ...missing] = fn(params);
|
|
177
|
-
if (missing.length) {
|
|
178
|
-
throw new TypeError(`Missing parameters: ${missing.join(", ")}`);
|
|
179
|
-
}
|
|
180
|
-
return path3;
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
function tokensToFunction(tokens, delimiter, encode) {
|
|
184
|
-
const encoders = tokens.map((token) => tokenToFunction(token, delimiter, encode));
|
|
185
|
-
return (data) => {
|
|
186
|
-
const result = [""];
|
|
187
|
-
for (const encoder of encoders) {
|
|
188
|
-
const [value, ...extras] = encoder(data);
|
|
189
|
-
result[0] += value;
|
|
190
|
-
result.push(...extras);
|
|
191
|
-
}
|
|
192
|
-
return result;
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
function tokenToFunction(token, delimiter, encode) {
|
|
196
|
-
if (token.type === "text")
|
|
197
|
-
return () => [token.value];
|
|
198
|
-
if (token.type === "group") {
|
|
199
|
-
const fn = tokensToFunction(token.tokens, delimiter, encode);
|
|
200
|
-
return (data) => {
|
|
201
|
-
const [value, ...missing] = fn(data);
|
|
202
|
-
if (!missing.length)
|
|
203
|
-
return [value];
|
|
204
|
-
return [""];
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
const encodeValue = encode || NOOP_VALUE;
|
|
208
|
-
if (token.type === "wildcard" && encode !== false) {
|
|
209
|
-
return (data) => {
|
|
210
|
-
const value = data[token.name];
|
|
211
|
-
if (value == null)
|
|
212
|
-
return ["", token.name];
|
|
213
|
-
if (!Array.isArray(value) || value.length === 0) {
|
|
214
|
-
throw new TypeError(`Expected "${token.name}" to be a non-empty array`);
|
|
215
|
-
}
|
|
216
|
-
return [
|
|
217
|
-
value.map((value2, index) => {
|
|
218
|
-
if (typeof value2 !== "string") {
|
|
219
|
-
throw new TypeError(`Expected "${token.name}/${index}" to be a string`);
|
|
220
|
-
}
|
|
221
|
-
return encodeValue(value2);
|
|
222
|
-
}).join(delimiter)
|
|
223
|
-
];
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
return (data) => {
|
|
227
|
-
const value = data[token.name];
|
|
228
|
-
if (value == null)
|
|
229
|
-
return ["", token.name];
|
|
230
|
-
if (typeof value !== "string") {
|
|
231
|
-
throw new TypeError(`Expected "${token.name}" to be a string`);
|
|
232
|
-
}
|
|
233
|
-
return [encodeValue(value)];
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
function match(path, options = {}) {
|
|
237
|
-
const { decode = decodeURIComponent, delimiter = DEFAULT_DELIMITER } = options;
|
|
238
|
-
const { regexp, keys } = pathToRegexp(path, options);
|
|
239
|
-
const decoders = keys.map((key) => {
|
|
240
|
-
if (decode === false)
|
|
241
|
-
return NOOP_VALUE;
|
|
242
|
-
if (key.type === "param")
|
|
243
|
-
return decode;
|
|
244
|
-
return (value) => value.split(delimiter).map(decode);
|
|
245
|
-
});
|
|
246
|
-
return function match2(input) {
|
|
247
|
-
const m = regexp.exec(input);
|
|
248
|
-
if (!m)
|
|
249
|
-
return false;
|
|
250
|
-
const path2 = m[0];
|
|
251
|
-
const params = Object.create(null);
|
|
252
|
-
for (let i = 1;i < m.length; i++) {
|
|
253
|
-
if (m[i] === undefined)
|
|
254
|
-
continue;
|
|
255
|
-
const key = keys[i - 1];
|
|
256
|
-
const decoder = decoders[i - 1];
|
|
257
|
-
params[key.name] = decoder(m[i]);
|
|
258
|
-
}
|
|
259
|
-
return { path: path2, params };
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
function pathToRegexp(path, options = {}) {
|
|
263
|
-
const { delimiter = DEFAULT_DELIMITER, end = true, sensitive = false, trailing = true } = options;
|
|
264
|
-
const keys = [];
|
|
265
|
-
const flags = sensitive ? "" : "i";
|
|
266
|
-
const sources = [];
|
|
267
|
-
for (const input of pathsToArray(path, [])) {
|
|
268
|
-
const data = typeof input === "object" ? input : parse(input, options);
|
|
269
|
-
for (const tokens of flatten(data.tokens, 0, [])) {
|
|
270
|
-
sources.push(toRegExpSource(tokens, delimiter, keys, data.originalPath));
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
let pattern = `^(?:${sources.join("|")})`;
|
|
274
|
-
if (trailing)
|
|
275
|
-
pattern += `(?:${escape(delimiter)}$)?`;
|
|
276
|
-
pattern += end ? "$" : `(?=${escape(delimiter)}|$)`;
|
|
277
|
-
const regexp = new RegExp(pattern, flags);
|
|
278
|
-
return { regexp, keys };
|
|
279
|
-
}
|
|
280
|
-
function pathsToArray(paths, init) {
|
|
281
|
-
if (Array.isArray(paths)) {
|
|
282
|
-
for (const p of paths)
|
|
283
|
-
pathsToArray(p, init);
|
|
284
|
-
} else {
|
|
285
|
-
init.push(paths);
|
|
286
|
-
}
|
|
287
|
-
return init;
|
|
288
|
-
}
|
|
289
|
-
function* flatten(tokens, index, init) {
|
|
290
|
-
if (index === tokens.length) {
|
|
291
|
-
return yield init;
|
|
292
|
-
}
|
|
293
|
-
const token = tokens[index];
|
|
294
|
-
if (token.type === "group") {
|
|
295
|
-
for (const seq of flatten(token.tokens, 0, init.slice())) {
|
|
296
|
-
yield* flatten(tokens, index + 1, seq);
|
|
297
|
-
}
|
|
298
|
-
} else {
|
|
299
|
-
init.push(token);
|
|
300
|
-
}
|
|
301
|
-
yield* flatten(tokens, index + 1, init);
|
|
302
|
-
}
|
|
303
|
-
function toRegExpSource(tokens, delimiter, keys, originalPath) {
|
|
304
|
-
let result = "";
|
|
305
|
-
let backtrack = "";
|
|
306
|
-
let isSafeSegmentParam = true;
|
|
307
|
-
for (const token of tokens) {
|
|
308
|
-
if (token.type === "text") {
|
|
309
|
-
result += escape(token.value);
|
|
310
|
-
backtrack += token.value;
|
|
311
|
-
isSafeSegmentParam || (isSafeSegmentParam = token.value.includes(delimiter));
|
|
312
|
-
continue;
|
|
313
|
-
}
|
|
314
|
-
if (token.type === "param" || token.type === "wildcard") {
|
|
315
|
-
if (!isSafeSegmentParam && !backtrack) {
|
|
316
|
-
throw new PathError(`Missing text before "${token.name}" ${token.type}`, originalPath);
|
|
317
|
-
}
|
|
318
|
-
if (token.type === "param") {
|
|
319
|
-
result += `(${negate(delimiter, isSafeSegmentParam ? "" : backtrack)}+)`;
|
|
320
|
-
} else {
|
|
321
|
-
result += `([\\s\\S]+)`;
|
|
322
|
-
}
|
|
323
|
-
keys.push(token);
|
|
324
|
-
backtrack = "";
|
|
325
|
-
isSafeSegmentParam = false;
|
|
326
|
-
continue;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
return result;
|
|
330
|
-
}
|
|
331
|
-
function negate(delimiter, backtrack) {
|
|
332
|
-
if (backtrack.length < 2) {
|
|
333
|
-
if (delimiter.length < 2)
|
|
334
|
-
return `[^${escape(delimiter + backtrack)}]`;
|
|
335
|
-
return `(?:(?!${escape(delimiter)})[^${escape(backtrack)}])`;
|
|
336
|
-
}
|
|
337
|
-
if (delimiter.length < 2) {
|
|
338
|
-
return `(?:(?!${escape(backtrack)})[^${escape(delimiter)}])`;
|
|
339
|
-
}
|
|
340
|
-
return `(?:(?!${escape(backtrack)}|${escape(delimiter)})[\\s\\S])`;
|
|
341
|
-
}
|
|
342
|
-
function stringifyTokens(tokens) {
|
|
343
|
-
let value = "";
|
|
344
|
-
let i = 0;
|
|
345
|
-
function name(value2) {
|
|
346
|
-
const isSafe = isNameSafe(value2) && isNextNameSafe(tokens[i]);
|
|
347
|
-
return isSafe ? value2 : JSON.stringify(value2);
|
|
348
|
-
}
|
|
349
|
-
while (i < tokens.length) {
|
|
350
|
-
const token = tokens[i++];
|
|
351
|
-
if (token.type === "text") {
|
|
352
|
-
value += escapeText(token.value);
|
|
353
|
-
continue;
|
|
354
|
-
}
|
|
355
|
-
if (token.type === "group") {
|
|
356
|
-
value += `{${stringifyTokens(token.tokens)}}`;
|
|
357
|
-
continue;
|
|
358
|
-
}
|
|
359
|
-
if (token.type === "param") {
|
|
360
|
-
value += `:${name(token.name)}`;
|
|
361
|
-
continue;
|
|
362
|
-
}
|
|
363
|
-
if (token.type === "wildcard") {
|
|
364
|
-
value += `*${name(token.name)}`;
|
|
365
|
-
continue;
|
|
366
|
-
}
|
|
367
|
-
throw new TypeError(`Unknown token type: ${token.type}`);
|
|
368
|
-
}
|
|
369
|
-
return value;
|
|
370
|
-
}
|
|
371
|
-
function stringify(data) {
|
|
372
|
-
return stringifyTokens(data.tokens);
|
|
373
|
-
}
|
|
374
|
-
function isNameSafe(name) {
|
|
375
|
-
const [first, ...rest] = name;
|
|
376
|
-
return ID_START.test(first) && rest.every((char) => ID_CONTINUE.test(char));
|
|
377
|
-
}
|
|
378
|
-
function isNextNameSafe(token) {
|
|
379
|
-
if (token && token.type === "text")
|
|
380
|
-
return !ID_CONTINUE.test(token.value[0]);
|
|
381
|
-
return true;
|
|
382
|
-
}
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
// src/router-simple.ts
|
|
386
|
-
var import_path_to_regexp = __toESM(require_dist(), 1);
|
|
387
|
-
|
|
388
|
-
// src/server/parse-body.ts
|
|
389
|
-
import url from "node:url";
|
|
390
|
-
|
|
391
|
-
// src/utils/is-engine.ts
|
|
392
|
-
var isNode = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
|
|
393
|
-
var isBrowser = typeof window !== "undefined" && typeof document !== "undefined" && typeof document.createElement === "function";
|
|
394
|
-
var isDeno = typeof Deno !== "undefined" && typeof Deno.version === "object" && typeof Deno.version.deno === "string";
|
|
395
|
-
var isBun = typeof Bun !== "undefined" && typeof Bun.version === "string";
|
|
396
|
-
|
|
397
|
-
// src/server/parse-body.ts
|
|
398
|
-
var parseBody = async (req) => {
|
|
399
|
-
const resolveBody = (body) => {
|
|
400
|
-
const contentType = req.headers["content-type"] || "";
|
|
401
|
-
const resolve = (data) => {
|
|
402
|
-
return data;
|
|
403
|
-
};
|
|
404
|
-
if (contentType.includes("application/json")) {
|
|
405
|
-
return resolve(JSON.parse(body));
|
|
406
|
-
}
|
|
407
|
-
if (contentType.includes("application/x-www-form-urlencoded")) {
|
|
408
|
-
const formData = new URLSearchParams(body);
|
|
409
|
-
const result = {};
|
|
410
|
-
formData.forEach((value, key) => {
|
|
411
|
-
try {
|
|
412
|
-
result[key] = JSON.parse(value);
|
|
413
|
-
} catch {
|
|
414
|
-
result[key] = value;
|
|
415
|
-
}
|
|
416
|
-
});
|
|
417
|
-
return resolve(result);
|
|
418
|
-
}
|
|
419
|
-
try {
|
|
420
|
-
return resolve(JSON.parse(body));
|
|
421
|
-
} catch {
|
|
422
|
-
return resolve({});
|
|
423
|
-
}
|
|
424
|
-
};
|
|
425
|
-
if (isBun) {
|
|
426
|
-
const body = req.body;
|
|
427
|
-
if (body) {
|
|
428
|
-
return resolveBody(body);
|
|
429
|
-
}
|
|
430
|
-
return {};
|
|
431
|
-
}
|
|
432
|
-
return new Promise((resolve, reject) => {
|
|
433
|
-
const arr = [];
|
|
434
|
-
req.on("data", (chunk) => {
|
|
435
|
-
arr.push(chunk);
|
|
436
|
-
});
|
|
437
|
-
req.on("end", () => {
|
|
438
|
-
try {
|
|
439
|
-
const body = Buffer.concat(arr).toString();
|
|
440
|
-
resolve(resolveBody(body));
|
|
441
|
-
} catch (e) {
|
|
442
|
-
resolve({});
|
|
443
|
-
}
|
|
444
|
-
});
|
|
445
|
-
});
|
|
446
|
-
};
|
|
447
|
-
var parseSearch = (req) => {
|
|
448
|
-
const parsedUrl = url.parse(req.url, true);
|
|
449
|
-
return parsedUrl.query;
|
|
450
|
-
};
|
|
451
|
-
var parseSearchValue = (value, opts) => {
|
|
452
|
-
if (!value)
|
|
453
|
-
return {};
|
|
454
|
-
const decode = opts?.decode ?? false;
|
|
455
|
-
if (decode) {
|
|
456
|
-
value = decodeURIComponent(value);
|
|
457
|
-
}
|
|
458
|
-
try {
|
|
459
|
-
return JSON.parse(value);
|
|
460
|
-
} catch (e) {
|
|
461
|
-
return {};
|
|
462
|
-
}
|
|
463
|
-
};
|
|
464
|
-
|
|
465
|
-
// src/router-simple.ts
|
|
466
|
-
class SimpleRouter {
|
|
467
|
-
routes = [];
|
|
468
|
-
exclude = [];
|
|
469
|
-
constructor(opts) {
|
|
470
|
-
this.exclude = opts?.exclude || ["/api/router"];
|
|
471
|
-
}
|
|
472
|
-
getBody(req) {
|
|
473
|
-
return parseBody(req);
|
|
474
|
-
}
|
|
475
|
-
getSearch(req) {
|
|
476
|
-
return parseSearch(req);
|
|
477
|
-
}
|
|
478
|
-
parseSearchValue = parseSearchValue;
|
|
479
|
-
use(method, route, ...fns) {
|
|
480
|
-
const handlers = Array.isArray(fns) ? fns.flat() : [];
|
|
481
|
-
const pattern = import_path_to_regexp.pathToRegexp(route);
|
|
482
|
-
this.routes.push({ method: method.toLowerCase(), regexp: pattern.regexp, keys: pattern.keys, handlers });
|
|
483
|
-
return this;
|
|
484
|
-
}
|
|
485
|
-
get(route, ...fns) {
|
|
486
|
-
return this.use("get", route, ...fns);
|
|
487
|
-
}
|
|
488
|
-
post(route, ...fns) {
|
|
489
|
-
return this.use("post", route, ...fns);
|
|
490
|
-
}
|
|
491
|
-
sse(route, ...fns) {
|
|
492
|
-
return this.use("sse", route, ...fns);
|
|
493
|
-
}
|
|
494
|
-
all(route, ...fns) {
|
|
495
|
-
this.use("post", route, ...fns);
|
|
496
|
-
this.use("get", route, ...fns);
|
|
497
|
-
this.use("sse", route, ...fns);
|
|
498
|
-
return this;
|
|
499
|
-
}
|
|
500
|
-
getJson(v) {
|
|
501
|
-
if (typeof v === "object") {
|
|
502
|
-
return v;
|
|
503
|
-
}
|
|
504
|
-
try {
|
|
505
|
-
return JSON.parse(v);
|
|
506
|
-
} catch (e) {
|
|
507
|
-
return {};
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
isSse(req) {
|
|
511
|
-
const { headers } = req;
|
|
512
|
-
if (!headers)
|
|
513
|
-
return false;
|
|
514
|
-
if (headers["accept"] && headers["accept"].includes("text/event-stream")) {
|
|
515
|
-
return true;
|
|
516
|
-
}
|
|
517
|
-
if (headers["content-type"] && headers["content-type"].includes("text/event-stream")) {
|
|
518
|
-
return true;
|
|
519
|
-
}
|
|
520
|
-
return false;
|
|
521
|
-
}
|
|
522
|
-
parse(req, res) {
|
|
523
|
-
const { pathname } = new URL(req.url, "http://localhost");
|
|
524
|
-
let method = req.method.toLowerCase();
|
|
525
|
-
if (this.exclude.includes(pathname)) {
|
|
526
|
-
return "is_exclude";
|
|
527
|
-
}
|
|
528
|
-
const isSse = this.isSse(req);
|
|
529
|
-
if (isSse)
|
|
530
|
-
method = "sse";
|
|
531
|
-
const route = this.routes.find((route2) => {
|
|
532
|
-
const matchResult = route2.regexp.exec(pathname);
|
|
533
|
-
if (matchResult && route2.method === method) {
|
|
534
|
-
const params = {};
|
|
535
|
-
route2.keys.forEach((key, i) => {
|
|
536
|
-
params[key.name] = matchResult[i + 1];
|
|
537
|
-
});
|
|
538
|
-
req.params = params;
|
|
539
|
-
return true;
|
|
540
|
-
}
|
|
541
|
-
});
|
|
542
|
-
if (route) {
|
|
543
|
-
const { handlers } = route;
|
|
544
|
-
return handlers.reduce((promiseChain, handler) => promiseChain.then(() => Promise.resolve(handler(req, res))), Promise.resolve());
|
|
545
|
-
}
|
|
546
|
-
return "not_found";
|
|
547
|
-
}
|
|
548
|
-
chain(req, res) {
|
|
549
|
-
const chain = new HttpChain({ req, res, simpleRouter: this });
|
|
550
|
-
return chain;
|
|
551
|
-
}
|
|
552
|
-
static Chain(opts) {
|
|
553
|
-
return new HttpChain(opts);
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
class HttpChain {
|
|
558
|
-
req;
|
|
559
|
-
res;
|
|
560
|
-
simpleRouter;
|
|
561
|
-
server;
|
|
562
|
-
hasSetHeader = false;
|
|
563
|
-
isSseSet = false;
|
|
564
|
-
constructor(opts) {
|
|
565
|
-
if (opts?.res) {
|
|
566
|
-
this.res = opts.res;
|
|
567
|
-
}
|
|
568
|
-
if (opts?.req) {
|
|
569
|
-
this.req = opts.req;
|
|
570
|
-
}
|
|
571
|
-
this.simpleRouter = opts?.simpleRouter;
|
|
572
|
-
}
|
|
573
|
-
setReq(req) {
|
|
574
|
-
this.req = req;
|
|
575
|
-
return this;
|
|
576
|
-
}
|
|
577
|
-
setRes(res) {
|
|
578
|
-
this.res = res;
|
|
579
|
-
return this;
|
|
580
|
-
}
|
|
581
|
-
setRouter(router) {
|
|
582
|
-
this.simpleRouter = router;
|
|
583
|
-
return this;
|
|
584
|
-
}
|
|
585
|
-
setServer(server) {
|
|
586
|
-
this.server = server;
|
|
587
|
-
return this;
|
|
588
|
-
}
|
|
589
|
-
status(status) {
|
|
590
|
-
if (!this.res)
|
|
591
|
-
return this;
|
|
592
|
-
if (this.hasSetHeader) {
|
|
593
|
-
return this;
|
|
594
|
-
}
|
|
595
|
-
this.hasSetHeader = true;
|
|
596
|
-
this.res.writeHead(status);
|
|
597
|
-
return this;
|
|
598
|
-
}
|
|
599
|
-
writeHead(status) {
|
|
600
|
-
if (!this.res)
|
|
601
|
-
return this;
|
|
602
|
-
if (this.hasSetHeader) {
|
|
603
|
-
return this;
|
|
604
|
-
}
|
|
605
|
-
this.hasSetHeader = true;
|
|
606
|
-
this.res.writeHead(status);
|
|
607
|
-
return this;
|
|
608
|
-
}
|
|
609
|
-
json(data) {
|
|
610
|
-
if (!this.res)
|
|
611
|
-
return this;
|
|
612
|
-
this.res.end(JSON.stringify(data));
|
|
613
|
-
return this;
|
|
614
|
-
}
|
|
615
|
-
end(data) {
|
|
616
|
-
if (!this.res)
|
|
617
|
-
return this;
|
|
618
|
-
if (typeof data === "object") {
|
|
619
|
-
this.res.end(JSON.stringify(data));
|
|
620
|
-
} else if (typeof data === "string") {
|
|
621
|
-
this.res.end(data);
|
|
622
|
-
} else {
|
|
623
|
-
this.res.end("nothing");
|
|
624
|
-
}
|
|
625
|
-
return this;
|
|
626
|
-
}
|
|
627
|
-
listen(opts, callback) {
|
|
628
|
-
this.server.listen(opts, callback);
|
|
629
|
-
return this;
|
|
630
|
-
}
|
|
631
|
-
parse(opts) {
|
|
632
|
-
const { listenOptions, listenCallBack } = opts || {};
|
|
633
|
-
if (!this.server || !this.simpleRouter) {
|
|
634
|
-
throw new Error("Server and SimpleRouter must be set before calling parse");
|
|
635
|
-
}
|
|
636
|
-
const that = this;
|
|
637
|
-
const listener = (req, res) => {
|
|
638
|
-
try {
|
|
639
|
-
that.simpleRouter.parse(req, res);
|
|
640
|
-
} catch (error) {
|
|
641
|
-
console.error("Error parsing request:", error);
|
|
642
|
-
if (!res.headersSent) {
|
|
643
|
-
res.writeHead(500);
|
|
644
|
-
res.end(JSON.stringify({ code: 500, message: "Internal Server Error" }));
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
};
|
|
648
|
-
if (listenOptions) {
|
|
649
|
-
this.server.listen(listenOptions, listenCallBack);
|
|
650
|
-
}
|
|
651
|
-
this.server.on("request", listener);
|
|
652
|
-
return () => {
|
|
653
|
-
that.server.removeListener("request", listener);
|
|
654
|
-
};
|
|
655
|
-
}
|
|
656
|
-
getString(value) {
|
|
657
|
-
if (typeof value === "string") {
|
|
658
|
-
return value;
|
|
659
|
-
}
|
|
660
|
-
return JSON.stringify(value);
|
|
661
|
-
}
|
|
662
|
-
sse(value) {
|
|
663
|
-
const res = this.res;
|
|
664
|
-
const req = this.req;
|
|
665
|
-
if (!res || !req)
|
|
666
|
-
return;
|
|
667
|
-
const data = this.getString(value);
|
|
668
|
-
if (this.isSseSet) {
|
|
669
|
-
res.write(`data: ${data}
|
|
670
|
-
|
|
671
|
-
`);
|
|
672
|
-
return this;
|
|
673
|
-
}
|
|
674
|
-
const headersMap = new Map([
|
|
675
|
-
["Content-Type", "text/event-stream"],
|
|
676
|
-
["Cache-Control", "no-cache"],
|
|
677
|
-
["Connection", "keep-alive"]
|
|
678
|
-
]);
|
|
679
|
-
this.isSseSet = true;
|
|
680
|
-
let intervalId;
|
|
681
|
-
if (!this.hasSetHeader) {
|
|
682
|
-
this.hasSetHeader = true;
|
|
683
|
-
res.setHeaders(headersMap);
|
|
684
|
-
setInterval(() => {
|
|
685
|
-
res.write(`
|
|
686
|
-
`);
|
|
687
|
-
}, 3000);
|
|
688
|
-
req.on("close", () => {
|
|
689
|
-
clearInterval(intervalId);
|
|
690
|
-
res.end();
|
|
691
|
-
});
|
|
692
|
-
}
|
|
693
|
-
this.res.write(`data: ${data}
|
|
694
|
-
|
|
695
|
-
`);
|
|
696
|
-
return this;
|
|
697
|
-
}
|
|
698
|
-
close() {
|
|
699
|
-
if (this.req?.destroy) {
|
|
700
|
-
this.req.destroy();
|
|
701
|
-
}
|
|
702
|
-
return this;
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
export {
|
|
706
|
-
SimpleRouter,
|
|
707
|
-
HttpChain
|
|
708
|
-
};
|