k99 0.6.0 → 0.7.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/index.cjs +304 -198
- package/index.d.ts +82 -81
- package/index.js +304 -198
- package/index.min.js +3 -3
- package/index.min.mjs +3 -3
- package/index.mjs +304 -199
- package/package.json +2 -3
- package/services.cjs +6 -4
- package/services.d.ts +8 -7
- package/services.js +6 -4
- package/services.min.js +2 -2
- package/services.min.mjs +2 -2
- package/services.mjs +6 -4
- package/node/index.cjs +0 -140
- package/node/index.d.cts +0 -52
package/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* k99 v0.
|
|
3
|
-
* (c) 2019-
|
|
2
|
+
* k99 v0.7.0
|
|
3
|
+
* (c) 2019-2025 猛火Fierflame
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
6
6
|
(function (global, factory) {
|
|
@@ -17,20 +17,6 @@
|
|
|
17
17
|
function str2utf8bin(str) {
|
|
18
18
|
return new TextEncoder().encode(str);
|
|
19
19
|
}
|
|
20
|
-
/**
|
|
21
|
-
*
|
|
22
|
-
* @param {unknown} chunk
|
|
23
|
-
* @returns {chunk is ArrayBuffer | SharedArrayBuffer}
|
|
24
|
-
*/
|
|
25
|
-
function isBufferSource(chunk) {
|
|
26
|
-
if (chunk instanceof ArrayBuffer) { return true; }
|
|
27
|
-
try {
|
|
28
|
-
if (chunk instanceof SharedArrayBuffer) { return true; }
|
|
29
|
-
} catch {
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
34
20
|
/**
|
|
35
21
|
*
|
|
36
22
|
* @template T
|
|
@@ -55,7 +41,7 @@
|
|
|
55
41
|
if (ArrayBuffer.isView(chunk)) {
|
|
56
42
|
return writer.write(new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength));
|
|
57
43
|
}
|
|
58
|
-
if (
|
|
44
|
+
if (chunk instanceof ArrayBuffer) {
|
|
59
45
|
return writer.write(new Uint8Array(chunk));
|
|
60
46
|
}
|
|
61
47
|
if (!isIterable(chunk)) {
|
|
@@ -99,7 +85,7 @@
|
|
|
99
85
|
if (result instanceof FormData) {
|
|
100
86
|
return [result, 0, ''];
|
|
101
87
|
}
|
|
102
|
-
if (ArrayBuffer.isView(result) ||
|
|
88
|
+
if (ArrayBuffer.isView(result) || result instanceof ArrayBuffer) {
|
|
103
89
|
return [result, result.byteLength, ''];
|
|
104
90
|
}
|
|
105
91
|
if (typeof result === 'string') {
|
|
@@ -124,8 +110,7 @@
|
|
|
124
110
|
if (!data) { continue; }
|
|
125
111
|
await write(writer, data);
|
|
126
112
|
}
|
|
127
|
-
|
|
128
|
-
})().catch(() => {});
|
|
113
|
+
})().then(() => writable.close(), r => writable.abort(r)).catch(() => {});
|
|
129
114
|
return [readable, 0, ''];
|
|
130
115
|
}
|
|
131
116
|
/**
|
|
@@ -148,11 +133,12 @@
|
|
|
148
133
|
return body;
|
|
149
134
|
}
|
|
150
135
|
|
|
136
|
+
/** @import { Cookie, CookieOption } from './types' */
|
|
151
137
|
/**
|
|
152
138
|
*
|
|
153
|
-
* @param {
|
|
139
|
+
* @param {Cookie[]} sentCookies
|
|
154
140
|
* @param {string} [name]
|
|
155
|
-
* @returns {Iterable<
|
|
141
|
+
* @returns {Iterable<Cookie>}
|
|
156
142
|
*/
|
|
157
143
|
function *getCookie(sentCookies, name) {
|
|
158
144
|
const list = sentCookies;
|
|
@@ -165,7 +151,7 @@
|
|
|
165
151
|
/**
|
|
166
152
|
*
|
|
167
153
|
* @param {Headers} headers
|
|
168
|
-
* @param {
|
|
154
|
+
* @param {Cookie[]} cookies
|
|
169
155
|
* @returns {void}
|
|
170
156
|
*/
|
|
171
157
|
function setCookiesHeader(headers, cookies) {
|
|
@@ -199,10 +185,10 @@
|
|
|
199
185
|
}
|
|
200
186
|
/**
|
|
201
187
|
*
|
|
202
|
-
* @param {
|
|
188
|
+
* @param {Cookie[]} sentCookies
|
|
203
189
|
* @param {Record<string, string>} cookies
|
|
204
|
-
* @param {string |
|
|
205
|
-
* @param {
|
|
190
|
+
* @param {string | CookieOption} [name]
|
|
191
|
+
* @param {CookieOption | boolean} [opt]
|
|
206
192
|
* @returns {void}
|
|
207
193
|
*/
|
|
208
194
|
function clearCookie(
|
|
@@ -214,11 +200,11 @@
|
|
|
214
200
|
let expire = 'Fri, 31 Dec 1999 16:00:00 GMT';
|
|
215
201
|
if (typeof name === 'string') {
|
|
216
202
|
if (!name) { return; }
|
|
217
|
-
/** @type {
|
|
203
|
+
/** @type {CookieOption} */
|
|
218
204
|
const { domain, path, secure, httpOnly } = opt !== true && opt || {};
|
|
219
205
|
sentCookies.push({ name, value: 'delete', expire, domain, path, secure, httpOnly });
|
|
220
206
|
} else {
|
|
221
|
-
/** @type {
|
|
207
|
+
/** @type {CookieOption} */
|
|
222
208
|
const { domain, path, secure, httpOnly } = name || {};
|
|
223
209
|
sentCookies.length = 0;
|
|
224
210
|
if (opt) {
|
|
@@ -229,6 +215,9 @@
|
|
|
229
215
|
}
|
|
230
216
|
}
|
|
231
217
|
|
|
218
|
+
/** @import { Context, Cookie, CookieOption, FindHandler, Method, Options, Params, Service } from './types' */
|
|
219
|
+
|
|
220
|
+
|
|
232
221
|
const noBodyMethods = new Set(['GET', 'OPTIONS']);
|
|
233
222
|
/**
|
|
234
223
|
*
|
|
@@ -265,7 +254,7 @@
|
|
|
265
254
|
*
|
|
266
255
|
* @param {Request} request
|
|
267
256
|
* @param {string | ((request: Request) => string)} [toMethod]
|
|
268
|
-
* @returns {
|
|
257
|
+
* @returns {Method}
|
|
269
258
|
*/
|
|
270
259
|
function getMethod(request, toMethod) {
|
|
271
260
|
let methodStr = '';
|
|
@@ -277,13 +266,13 @@
|
|
|
277
266
|
if (!methodStr || typeof methodStr !== 'string') {
|
|
278
267
|
methodStr = request.method || 'GET';
|
|
279
268
|
}
|
|
280
|
-
return /** @type {
|
|
269
|
+
return /** @type {Method} */(methodStr.toUpperCase());
|
|
281
270
|
}
|
|
282
271
|
/**
|
|
283
272
|
*
|
|
284
273
|
* @param {Request} request
|
|
285
|
-
* @param {
|
|
286
|
-
* @param {
|
|
274
|
+
* @param {FindHandler} getHandler
|
|
275
|
+
* @param {Options} [options]
|
|
287
276
|
* @returns {Promise<Response | null>}
|
|
288
277
|
*/
|
|
289
278
|
function main(
|
|
@@ -293,7 +282,7 @@
|
|
|
293
282
|
/**
|
|
294
283
|
*
|
|
295
284
|
* @param {Request} request
|
|
296
|
-
* @param {
|
|
285
|
+
* @param {Context} [parent]
|
|
297
286
|
* @returns {Promise<Response | null>}
|
|
298
287
|
*/
|
|
299
288
|
function exec(request, parent) {
|
|
@@ -301,10 +290,10 @@
|
|
|
301
290
|
const url = new URL(request.url);
|
|
302
291
|
const { signal, headers } = request;
|
|
303
292
|
const aborted = signal2promise(signal);
|
|
304
|
-
/** @type {Map<
|
|
293
|
+
/** @type {Map<Service<any, any>, Function>} */
|
|
305
294
|
const services = new Map();
|
|
306
295
|
const cookies = getRequestCookies(headers.get('cookie') || '');
|
|
307
|
-
/** @type {
|
|
296
|
+
/** @type {Cookie[]} */
|
|
308
297
|
const sentCookies = [];
|
|
309
298
|
const responseHeaders = new Headers();
|
|
310
299
|
const root = parent?.root;
|
|
@@ -320,9 +309,9 @@
|
|
|
320
309
|
const donePromise = new Promise((a, b) => { resolve = a; reject = b; });
|
|
321
310
|
donePromise.catch(() => {});
|
|
322
311
|
|
|
323
|
-
/** @type {
|
|
312
|
+
/** @type {Params} */
|
|
324
313
|
let params = {};
|
|
325
|
-
/** @type {
|
|
314
|
+
/** @type {Context} */
|
|
326
315
|
const context = {
|
|
327
316
|
environment,
|
|
328
317
|
parent,
|
|
@@ -386,8 +375,8 @@
|
|
|
386
375
|
},
|
|
387
376
|
/**
|
|
388
377
|
*
|
|
389
|
-
* @param {string |
|
|
390
|
-
* @param {
|
|
378
|
+
* @param {string | CookieOption} [name]
|
|
379
|
+
* @param {CookieOption | boolean} [opt]
|
|
391
380
|
* @returns {void}
|
|
392
381
|
*/
|
|
393
382
|
clearCookie(name, opt) {
|
|
@@ -424,69 +413,72 @@
|
|
|
424
413
|
return exec(request);
|
|
425
414
|
}
|
|
426
415
|
|
|
416
|
+
/** @import { FindHandler, Options } from './main/types' */
|
|
417
|
+
|
|
427
418
|
/**
|
|
428
419
|
*
|
|
429
|
-
* @param {
|
|
430
|
-
* @param {
|
|
420
|
+
* @param {FindHandler} getHandler
|
|
421
|
+
* @param {Options} options
|
|
431
422
|
* @returns {(request: Request) => Promise<Response | null>}
|
|
432
423
|
*/
|
|
433
424
|
function make(getHandler, options) {
|
|
434
425
|
return r => main(r, getHandler, options);
|
|
435
426
|
}
|
|
436
427
|
|
|
428
|
+
/** @import { Context, Handler } from './main/types' */
|
|
437
429
|
/**
|
|
438
430
|
*
|
|
439
|
-
* @param {
|
|
440
|
-
* @param {
|
|
431
|
+
* @param {Context} context
|
|
432
|
+
* @param {Handler[]} handlers
|
|
441
433
|
* @returns {Promise<string | boolean | object | undefined>}
|
|
442
434
|
*/
|
|
443
435
|
async function runHandles(context, handlers) {
|
|
444
436
|
for (const handle of handlers) {
|
|
445
437
|
const result = await handle(context);
|
|
446
|
-
if (
|
|
447
|
-
if (!result) { continue; }
|
|
438
|
+
if (result === undefined) { continue; }
|
|
448
439
|
return result;
|
|
449
440
|
}
|
|
450
441
|
}
|
|
451
442
|
|
|
452
443
|
/**
|
|
453
444
|
*
|
|
454
|
-
* @param {...(
|
|
455
|
-
* @returns {
|
|
445
|
+
* @param {...(Handler | Handler[])} handlers
|
|
446
|
+
* @returns {Handler}
|
|
456
447
|
*/
|
|
457
448
|
function merge(...handlers) {
|
|
458
449
|
return ctx => runHandles(ctx, handlers.flat());
|
|
459
450
|
}
|
|
460
451
|
|
|
452
|
+
/** @import { Context, Service } from './main/types' */
|
|
461
453
|
/**
|
|
462
454
|
*
|
|
463
455
|
* @template T
|
|
464
456
|
* @template {any[]} P
|
|
465
457
|
* @overload
|
|
466
|
-
* @param {(ctx:
|
|
467
|
-
* @param {((ctx:
|
|
468
|
-
* @param {
|
|
469
|
-
* @returns {
|
|
458
|
+
* @param {(ctx: Context, ...p: P) => T} exec
|
|
459
|
+
* @param {((ctx: Context, error?: unknown) => PromiseLike<void> | void)?} [destroy]
|
|
460
|
+
* @param {Service.Options?} [options]
|
|
461
|
+
* @returns {Service<T, P>}
|
|
470
462
|
*/
|
|
471
463
|
/**
|
|
472
464
|
*
|
|
473
465
|
* @template T
|
|
474
466
|
* @template {any[]} P
|
|
475
467
|
* @overload
|
|
476
|
-
* @param {(ctx:
|
|
477
|
-
* @param {
|
|
478
|
-
* @returns {
|
|
468
|
+
* @param {(ctx: Context, ...p: P) => T} exec
|
|
469
|
+
* @param {Service.Options?} [options]
|
|
470
|
+
* @returns {Service<T, P>}
|
|
479
471
|
*/
|
|
480
472
|
/**
|
|
481
473
|
* @template T
|
|
482
474
|
* @template {any[]} P
|
|
483
|
-
* @param {(ctx:
|
|
484
|
-
* @param {((ctx:
|
|
485
|
-
* @param {
|
|
486
|
-
* @returns {
|
|
475
|
+
* @param {(ctx: Context, ...p: P) => T} exec
|
|
476
|
+
* @param {((ctx: Context, error?: unknown) => PromiseLike<void> | void) | Service.Options | null} [destroy]
|
|
477
|
+
* @param {Service.Options?} [options]
|
|
478
|
+
* @returns {Service<T, P>}
|
|
487
479
|
*/
|
|
488
480
|
function service(exec, destroy, options) {
|
|
489
|
-
/** @type {
|
|
481
|
+
/** @type {Service<T, P>} */
|
|
490
482
|
const service = function (ctx) {
|
|
491
483
|
if (typeof destroy === 'function') {
|
|
492
484
|
ctx.done(() => destroy(ctx), error => destroy(ctx, error));
|
|
@@ -505,43 +497,44 @@
|
|
|
505
497
|
return service;
|
|
506
498
|
}
|
|
507
499
|
|
|
500
|
+
/** @import { Context, Service, StateService } from './main/types' */
|
|
508
501
|
/**
|
|
509
502
|
*
|
|
510
503
|
* @template T
|
|
511
504
|
* @overload
|
|
512
|
-
* @param {(ctx:
|
|
513
|
-
* @param {
|
|
514
|
-
* @returns {
|
|
505
|
+
* @param {(ctx: Context) => T} init
|
|
506
|
+
* @param {Service.Options} [options]
|
|
507
|
+
* @returns {StateService<T>}
|
|
515
508
|
*/
|
|
516
509
|
/**
|
|
517
510
|
*
|
|
518
511
|
* @template T
|
|
519
512
|
* @overload
|
|
520
|
-
* @param {(ctx:
|
|
521
|
-
* @param {((state: T | undefined, ctx:
|
|
522
|
-
* @param {
|
|
523
|
-
* @returns {
|
|
513
|
+
* @param {(ctx: Context) => T} init
|
|
514
|
+
* @param {((state: T | undefined, ctx: Context, error?: unknown) => PromiseLike<void> | void)?} [destroy]
|
|
515
|
+
* @param {Service.Options?} [options]
|
|
516
|
+
* @returns {StateService<T>}
|
|
524
517
|
*/
|
|
525
518
|
/**
|
|
526
519
|
*
|
|
527
520
|
* @template T
|
|
528
521
|
* @overload
|
|
529
|
-
* @param {(ctx:
|
|
530
|
-
* @param {((state: T | undefined, ctx:
|
|
531
|
-
* @param {((state: T, ctx:
|
|
532
|
-
* @param {
|
|
533
|
-
* @returns {
|
|
522
|
+
* @param {(ctx: Context) => T} init
|
|
523
|
+
* @param {((state: T | undefined, ctx: Context, error?: unknown) => PromiseLike<void> | void)?} [destroy]
|
|
524
|
+
* @param {((state: T, ctx: Context) => any)?} [exec]
|
|
525
|
+
* @param {Service.Options?} [options]
|
|
526
|
+
* @returns {StateService<T>}
|
|
534
527
|
*/
|
|
535
528
|
/**
|
|
536
529
|
* @template T
|
|
537
|
-
* @param {(ctx:
|
|
538
|
-
* @param {((state: T | undefined, ctx:
|
|
539
|
-
* @param {((state: T, ctx:
|
|
540
|
-
* @param {
|
|
541
|
-
* @returns {
|
|
530
|
+
* @param {(ctx: Context) => T} init
|
|
531
|
+
* @param {((state: T | undefined, ctx: Context, error?: unknown) => PromiseLike<void> | void) | Service.Options | null} [destroy]
|
|
532
|
+
* @param {((state: T, ctx: Context) => any) | Service.Options | null} [exec]
|
|
533
|
+
* @param {Service.Options?} [options]
|
|
534
|
+
* @returns {StateService<T>}
|
|
542
535
|
*/
|
|
543
536
|
function stateService(init, destroy, exec, options) {
|
|
544
|
-
/** @type {
|
|
537
|
+
/** @type {StateService<T>} */
|
|
545
538
|
const service = function (ctx) {
|
|
546
539
|
const state = init(ctx) || /** @type {T} */({});
|
|
547
540
|
if (typeof destroy === 'function') {
|
|
@@ -565,39 +558,40 @@
|
|
|
565
558
|
return service;
|
|
566
559
|
}
|
|
567
560
|
|
|
561
|
+
/** @import { Context, Service, StoreService } from './main/types' */
|
|
568
562
|
/**
|
|
569
563
|
*
|
|
570
564
|
* @template T
|
|
571
565
|
* @overload
|
|
572
|
-
* @param {
|
|
573
|
-
* @returns {
|
|
566
|
+
* @param {Service.Options?} [options]
|
|
567
|
+
* @returns {StoreService<T>}
|
|
574
568
|
*/
|
|
575
569
|
/**
|
|
576
570
|
*
|
|
577
571
|
* @template T
|
|
578
572
|
* @overload
|
|
579
|
-
* @param {((state: T | undefined, ctx:
|
|
580
|
-
* @param {
|
|
581
|
-
* @returns {
|
|
573
|
+
* @param {((state: T | undefined, ctx: Context, error?: unknown) => PromiseLike<void> | void)?} [destroy]
|
|
574
|
+
* @param {Service.Options?} [options]
|
|
575
|
+
* @returns {StoreService<T>}
|
|
582
576
|
*/
|
|
583
577
|
/**
|
|
584
578
|
*
|
|
585
579
|
* @template T
|
|
586
580
|
* @overload
|
|
587
|
-
* @param {((state: T | undefined, ctx:
|
|
588
|
-
* @param {((state: T | undefined, ctx:
|
|
589
|
-
* @param {
|
|
590
|
-
* @returns {
|
|
581
|
+
* @param {((state: T | undefined, ctx: Context, error?: unknown) => PromiseLike<void> | void)?} [destroy]
|
|
582
|
+
* @param {((state: T | undefined, ctx: Context) => any)?} [exec]
|
|
583
|
+
* @param {Service.Options?} [options]
|
|
584
|
+
* @returns {StoreService<T>}
|
|
591
585
|
*/
|
|
592
586
|
/**
|
|
593
587
|
* @template T
|
|
594
|
-
* @param {((state: T | undefined, ctx:
|
|
595
|
-
* @param {((state: T | undefined, ctx:
|
|
596
|
-
* @param {
|
|
597
|
-
* @returns {
|
|
588
|
+
* @param {((state: T | undefined, ctx: Context, error?: unknown) => PromiseLike<void> | void) | Service.Options | null} [destroy]
|
|
589
|
+
* @param {((state: T | undefined, ctx: Context) => any) | Service.Options | null} [exec]
|
|
590
|
+
* @param {Service.Options?} [options]
|
|
591
|
+
* @returns {StoreService<T>}
|
|
598
592
|
*/
|
|
599
593
|
function storeService(destroy, exec, options) {
|
|
600
|
-
/** @type {
|
|
594
|
+
/** @type {StoreService<T>} */
|
|
601
595
|
const service = function (ctx) {
|
|
602
596
|
/** @type {T | undefined} */
|
|
603
597
|
let state;
|
|
@@ -634,16 +628,18 @@
|
|
|
634
628
|
return service;
|
|
635
629
|
}
|
|
636
630
|
|
|
631
|
+
/** @import { Handler } from './main/types' */
|
|
632
|
+
/** @import { Onionskin } from './onionskin.mjs' */
|
|
637
633
|
/**
|
|
638
634
|
* @callback Packer
|
|
639
|
-
* @param {
|
|
640
|
-
* @returns {
|
|
635
|
+
* @param {Handler} handler
|
|
636
|
+
* @returns {Handler}
|
|
641
637
|
*/
|
|
642
638
|
/** @type {Packer} */
|
|
643
639
|
const noop$1 = h => h;
|
|
644
640
|
/**
|
|
645
641
|
*
|
|
646
|
-
* @param {
|
|
642
|
+
* @param {Onionskin} onionskin
|
|
647
643
|
* @param {Packer} [packer]
|
|
648
644
|
* @returns {Packer}
|
|
649
645
|
*/
|
|
@@ -654,30 +650,33 @@
|
|
|
654
650
|
};
|
|
655
651
|
}
|
|
656
652
|
|
|
653
|
+
/** @import { Context, FindHandler, Handler, Method, Params } from './main/types' */
|
|
654
|
+
/** @import { Onionskin } from './onionskin.mjs' */
|
|
655
|
+
|
|
657
656
|
/**
|
|
658
657
|
* @callback Guard
|
|
659
|
-
* @param {
|
|
660
|
-
* @returns {PromiseLike<boolean |
|
|
658
|
+
* @param {Context} ctx
|
|
659
|
+
* @returns {PromiseLike<boolean | Handler | void> | boolean | Handler | void}
|
|
661
660
|
*/
|
|
662
661
|
/**
|
|
663
|
-
* @typedef {[
|
|
662
|
+
* @typedef {[Handler | Router, Record<string | symbol, any>, string[]]} FindItem
|
|
664
663
|
*/
|
|
665
664
|
/**
|
|
666
665
|
* @callback Finder
|
|
667
666
|
* @this {Router}
|
|
668
|
-
* @param {
|
|
667
|
+
* @param {Method} method
|
|
669
668
|
* @param {string[]} path
|
|
670
|
-
* @param {
|
|
669
|
+
* @param {Context} ctx
|
|
671
670
|
* @returns {AsyncIterable<FindItem> | Iterable<FindItem>}
|
|
672
671
|
*/
|
|
673
672
|
|
|
674
673
|
/**
|
|
675
674
|
*
|
|
676
675
|
* @param {Set<Guard>} guards
|
|
677
|
-
* @param {
|
|
676
|
+
* @param {Context} ctx
|
|
678
677
|
* @param {(v: any) => void} setParams
|
|
679
678
|
* @param {object} params
|
|
680
|
-
* @returns {Promise<boolean |
|
|
679
|
+
* @returns {Promise<boolean | Handler>}
|
|
681
680
|
*/
|
|
682
681
|
async function execGuard(guards, ctx, setParams, params) {
|
|
683
682
|
if (!guards.size) { return true; }
|
|
@@ -696,12 +695,12 @@
|
|
|
696
695
|
|
|
697
696
|
/**
|
|
698
697
|
*
|
|
699
|
-
* @param {Router |
|
|
698
|
+
* @param {Router | Handler} route
|
|
700
699
|
* @param {string[]} path
|
|
701
|
-
* @param {
|
|
702
|
-
* @param {(v:
|
|
703
|
-
* @param {
|
|
704
|
-
* @returns {Promise<
|
|
700
|
+
* @param {Context} ctx
|
|
701
|
+
* @param {(v: Params) => void} setParams
|
|
702
|
+
* @param {Params} params
|
|
703
|
+
* @returns {Promise<Handler | null>}
|
|
705
704
|
*/
|
|
706
705
|
async function find(route, path, ctx, setParams, params) {
|
|
707
706
|
if (!(route instanceof Router)) {
|
|
@@ -740,16 +739,16 @@
|
|
|
740
739
|
disabled = false;
|
|
741
740
|
/**
|
|
742
741
|
* @abstract
|
|
743
|
-
* @param {
|
|
742
|
+
* @param {Method} method
|
|
744
743
|
* @param {string[]} path
|
|
745
|
-
* @param {
|
|
744
|
+
* @param {Context} ctx
|
|
746
745
|
* @returns {AsyncIterable<FindItem> | Iterable<FindItem>}
|
|
747
746
|
*/
|
|
748
747
|
find(method, path, ctx) { return []; }
|
|
749
748
|
/**
|
|
750
749
|
*
|
|
751
750
|
* @param {Router[]} routers
|
|
752
|
-
* @returns {
|
|
751
|
+
* @returns {FindHandler}
|
|
753
752
|
*/
|
|
754
753
|
static make(routers) {
|
|
755
754
|
return async (ctx, setParams) => {
|
|
@@ -777,19 +776,21 @@
|
|
|
777
776
|
guards = new Set();
|
|
778
777
|
/**
|
|
779
778
|
*
|
|
780
|
-
* @param {
|
|
781
|
-
* @returns {
|
|
779
|
+
* @param {Handler} h
|
|
780
|
+
* @returns {Handler}
|
|
782
781
|
*/
|
|
783
782
|
__onionskin = (h) => h;
|
|
784
|
-
/** @param {
|
|
783
|
+
/** @param {Onionskin} os */
|
|
785
784
|
onionskin(os) { this.__onionskin = packer(os, this.__onionskin); }
|
|
786
785
|
}
|
|
787
786
|
|
|
787
|
+
/** @import { Match } from './index.mjs' */
|
|
788
|
+
/** @import { Params } from '../main/types.js' */
|
|
788
789
|
/**
|
|
789
790
|
* @typedef {object} Pattern
|
|
790
|
-
* @property {string} name
|
|
791
|
-
* @property {boolean} optional
|
|
792
|
-
* @property {boolean} many
|
|
791
|
+
* @property {string | symbol} name
|
|
792
|
+
* @property {boolean} [optional]
|
|
793
|
+
* @property {boolean} [many]
|
|
793
794
|
* @property {RegExp} pattern
|
|
794
795
|
*/
|
|
795
796
|
|
|
@@ -860,7 +861,7 @@
|
|
|
860
861
|
* @returns {[Record<string, string | string[]>, string[]] | undefined}
|
|
861
862
|
*/
|
|
862
863
|
function exec(match, path, end) {
|
|
863
|
-
/** @type {
|
|
864
|
+
/** @type {Params} */
|
|
864
865
|
const params = {};
|
|
865
866
|
for (let i = 0; i < match.length; i++) {
|
|
866
867
|
const m = match[i];
|
|
@@ -883,38 +884,101 @@
|
|
|
883
884
|
return [params, []];
|
|
884
885
|
|
|
885
886
|
}
|
|
887
|
+
/**
|
|
888
|
+
*
|
|
889
|
+
* @param {string[]} paths
|
|
890
|
+
* @param {*} values
|
|
891
|
+
* @returns {Iterable<[string[], any[]]>}
|
|
892
|
+
*/
|
|
893
|
+
function* split([...paths], [...values]) {
|
|
894
|
+
let els = (paths.shift() || '').split('/');
|
|
895
|
+
let list = [els.pop() || ''];
|
|
896
|
+
for (const f of els) {
|
|
897
|
+
yield [[f], []];
|
|
898
|
+
}
|
|
899
|
+
for (const path of paths) {
|
|
900
|
+
const els = path.split('/');
|
|
901
|
+
if (els.length <= 1) {
|
|
902
|
+
list.push(path);
|
|
903
|
+
continue;
|
|
904
|
+
}
|
|
905
|
+
const pathValue = values.splice(0, list.length);
|
|
906
|
+
list.push(els.shift() || '');
|
|
907
|
+
yield [list, pathValue];
|
|
908
|
+
list = [els.pop() || ''];
|
|
909
|
+
for (const f of els) {
|
|
910
|
+
yield [[f], []];
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
yield [list, values];
|
|
914
|
+
}
|
|
886
915
|
/**
|
|
887
916
|
*
|
|
888
|
-
* @param {string} path
|
|
917
|
+
* @param {string | [string[], any[]]} path
|
|
889
918
|
* @param {boolean} end
|
|
890
|
-
* @returns {
|
|
919
|
+
* @returns {Match | undefined}
|
|
891
920
|
*/
|
|
892
921
|
function toMatch(path, end) {
|
|
893
922
|
/** @type {(Pattern | string)[]} */
|
|
894
923
|
const list = [];
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
924
|
+
if (typeof path === 'string') {
|
|
925
|
+
for (const p of path.split('/')) {
|
|
926
|
+
if (!p || /^\.+$/.test(p)) { continue; }
|
|
927
|
+
list.push(parse(p));
|
|
928
|
+
}
|
|
929
|
+
} else {
|
|
930
|
+
for (const [paths, values] of split(...path)) {
|
|
931
|
+
if (paths.length === 2 && !paths[0]) {
|
|
932
|
+
const modifier = paths[1];
|
|
933
|
+
if (['', '?', '+', '*'].includes(modifier)) {
|
|
934
|
+
const value = values[0];
|
|
935
|
+
if (typeof value === 'symbol') {
|
|
936
|
+
list.push({
|
|
937
|
+
name: value, pattern: /^.*$/,
|
|
938
|
+
optional: modifier === '?' || modifier === '*',
|
|
939
|
+
many: modifier === '+' || modifier === '*',
|
|
940
|
+
});
|
|
941
|
+
continue;
|
|
942
|
+
} else if (value && typeof value === 'object') {
|
|
943
|
+
const {name, pattern} = value;
|
|
944
|
+
if (typeof name === 'symbol') {
|
|
945
|
+
list.push({
|
|
946
|
+
name, pattern: pattern instanceof RegExp ? pattern : /^.*$/,
|
|
947
|
+
optional: modifier === '?' || modifier === '*',
|
|
948
|
+
many: modifier === '+' || modifier === '*',
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
const last = paths.pop() || '';
|
|
955
|
+
const strings = paths.map((v, i) => [v, values[i]]).flat();
|
|
956
|
+
strings.push(last);
|
|
957
|
+
const p = strings.join('');
|
|
958
|
+
if (!p || /^\.+$/.test(p)) { continue; }
|
|
959
|
+
list.push(parse(p));
|
|
960
|
+
continue;
|
|
961
|
+
}
|
|
962
|
+
|
|
898
963
|
}
|
|
899
964
|
if (!list.length) { return; }
|
|
900
965
|
return path => exec(list, path, end);
|
|
901
966
|
}
|
|
902
967
|
|
|
968
|
+
/** @import { Handler, Method } from '../main/types' */
|
|
969
|
+
/** @import { Binder, Match, Route, RouterRoute } from './index.mjs' */
|
|
970
|
+
|
|
903
971
|
/**
|
|
904
972
|
*
|
|
905
|
-
* @param {(
|
|
906
|
-
* @param {
|
|
907
|
-
* @param {
|
|
908
|
-
* @param {
|
|
973
|
+
* @param {(Route | RouterRoute)[]} routes
|
|
974
|
+
* @param {Set<Method>} methods
|
|
975
|
+
* @param {Match | undefined} match
|
|
976
|
+
* @param {Handler[]} handlers
|
|
909
977
|
* @returns {() => void}
|
|
910
978
|
*/
|
|
911
|
-
function bind(routes, methods,
|
|
912
|
-
/** @type {
|
|
913
|
-
const route = {
|
|
914
|
-
match: toMatch(path || '', true),
|
|
915
|
-
methods: new Set(methods),
|
|
916
|
-
handler,
|
|
917
|
-
};
|
|
979
|
+
function bind(routes, methods, match, handlers) {
|
|
980
|
+
/** @type {Route} */
|
|
981
|
+
const route = { match, methods, handler: ctx => runHandles(ctx, handlers) };
|
|
918
982
|
routes.push(route);
|
|
919
983
|
let removed = false;
|
|
920
984
|
return () => {
|
|
@@ -925,43 +989,49 @@
|
|
|
925
989
|
routes.splice(index, 1);
|
|
926
990
|
};
|
|
927
991
|
}
|
|
928
|
-
/** @type {(v: any) => v is
|
|
992
|
+
/** @type {(v: any) => v is Handler} */
|
|
929
993
|
const findHandler = v => typeof v === 'function';
|
|
930
994
|
/**
|
|
931
995
|
*
|
|
932
|
-
* @param {(
|
|
933
|
-
* @param {
|
|
996
|
+
* @param {(Route | RouterRoute)[]} routes
|
|
997
|
+
* @param {Iterable<Method>} methods
|
|
934
998
|
* @param {any[]} p
|
|
935
|
-
* @returns {
|
|
999
|
+
* @returns {Binder | (() => void)}
|
|
936
1000
|
*/
|
|
937
1001
|
function verb(routes, methods, p) {
|
|
1002
|
+
const methodSet = new Set(methods);
|
|
938
1003
|
if (!p.length) {
|
|
939
|
-
|
|
1004
|
+
const match = undefined;
|
|
1005
|
+
/** @type {Binder} */
|
|
1006
|
+
return (...handlers) => bind(routes, methodSet, match, handlers);
|
|
940
1007
|
}
|
|
941
|
-
const [
|
|
942
|
-
if (
|
|
943
|
-
const
|
|
944
|
-
|
|
1008
|
+
const [path] = p;
|
|
1009
|
+
if (path && typeof path === 'object') {
|
|
1010
|
+
const match = toMatch([path, p.slice(1)], true);
|
|
1011
|
+
/** @type {Binder} */
|
|
1012
|
+
return (...handlers) => bind(routes, methodSet, match, handlers);
|
|
945
1013
|
}
|
|
946
|
-
const
|
|
947
|
-
const
|
|
948
|
-
if (!
|
|
949
|
-
|
|
1014
|
+
const match = toMatch(typeof path === 'string' ? path : '', true);
|
|
1015
|
+
const handlers = p.filter(findHandler);
|
|
1016
|
+
if (!handlers.length) {
|
|
1017
|
+
/** @type {Binder} */
|
|
1018
|
+
return (...handlers) => bind(routes, methodSet, match, handlers);
|
|
950
1019
|
}
|
|
951
|
-
return bind(routes,
|
|
1020
|
+
return bind(routes, methodSet, match, handlers);
|
|
952
1021
|
}
|
|
953
1022
|
|
|
1023
|
+
/** @import { Method } from '../main/types' */
|
|
954
1024
|
const methods = new Set(['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS']);
|
|
955
1025
|
/**
|
|
956
1026
|
*
|
|
957
1027
|
* @param {any} v
|
|
958
|
-
* @returns {v is
|
|
1028
|
+
* @returns {v is Method}
|
|
959
1029
|
*/
|
|
960
1030
|
function isMethod(v) { return methods.has(v); }
|
|
961
1031
|
/**
|
|
962
1032
|
*
|
|
963
|
-
* @param {
|
|
964
|
-
* @returns {
|
|
1033
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} [methods]
|
|
1034
|
+
* @returns {Method[]}
|
|
965
1035
|
*/
|
|
966
1036
|
function getMethods(methods) {
|
|
967
1037
|
if (!methods) {
|
|
@@ -975,25 +1045,24 @@
|
|
|
975
1045
|
.filter(isMethod);
|
|
976
1046
|
}
|
|
977
1047
|
|
|
1048
|
+
/** @import { Context, Handler, Method, Params } from '../main/types' */
|
|
1049
|
+
/** @import { Finder, FindItem } from '../Router.mjs' */
|
|
1050
|
+
|
|
978
1051
|
/**
|
|
979
1052
|
* @callback Match
|
|
980
1053
|
* @param {string[]} paths
|
|
981
|
-
* @returns {[
|
|
1054
|
+
* @returns {[Params, string[]] | undefined}
|
|
982
1055
|
*/
|
|
983
1056
|
|
|
984
|
-
/**
|
|
985
|
-
* @callback Binder
|
|
986
|
-
* @param {import('../main/types').Handler} handler
|
|
987
|
-
* @returns {() => void}
|
|
988
|
-
*/
|
|
1057
|
+
/** @typedef {(handler: Handler, ...handlers: Handler[]) => () => void} Binder */
|
|
989
1058
|
|
|
990
1059
|
/**
|
|
991
1060
|
* @typedef {object} Route
|
|
992
1061
|
* @property {Match} [match] 路径匹配
|
|
993
1062
|
* @property {null} [router]
|
|
994
1063
|
* @property {string} [plugin] 所属插件
|
|
995
|
-
* @property {
|
|
996
|
-
* @property {Set<
|
|
1064
|
+
* @property {Handler} handler 处理函数
|
|
1065
|
+
* @property {Set<Method>} methods 方法列表
|
|
997
1066
|
*/
|
|
998
1067
|
|
|
999
1068
|
/**
|
|
@@ -1004,16 +1073,16 @@
|
|
|
1004
1073
|
|
|
1005
1074
|
|
|
1006
1075
|
/**
|
|
1007
|
-
* @template {Router |
|
|
1076
|
+
* @template {Router | Finder} [T=ApiRouter]
|
|
1008
1077
|
* @callback RouteBinder
|
|
1009
1078
|
* @param {T} [router] 要注册的子路由或子路由的 Finder
|
|
1010
|
-
* @returns {T extends
|
|
1079
|
+
* @returns {T extends Finder ? Router : T}
|
|
1011
1080
|
*/
|
|
1012
1081
|
/**
|
|
1013
1082
|
*
|
|
1014
1083
|
* @param {(Route | RouterRoute)[]} routes
|
|
1015
|
-
* @param {string} path
|
|
1016
|
-
* @param {Router |
|
|
1084
|
+
* @param {string | [string[], any[]]} path
|
|
1085
|
+
* @param {Router | Finder} [r]
|
|
1017
1086
|
* @returns {Router}
|
|
1018
1087
|
*/
|
|
1019
1088
|
function bindRouter(routes, path, r) {
|
|
@@ -1028,18 +1097,18 @@
|
|
|
1028
1097
|
#routes = [];
|
|
1029
1098
|
/**
|
|
1030
1099
|
* 添加子路由
|
|
1031
|
-
* @template {Router |
|
|
1100
|
+
* @template {Router | Finder} [T=ApiRouter]
|
|
1032
1101
|
* @overload
|
|
1033
1102
|
* @param {T} [router] 要注册的子路由或子路由的 Finder
|
|
1034
|
-
* @returns {T extends
|
|
1103
|
+
* @returns {T extends Finder ? Router : T}
|
|
1035
1104
|
*/
|
|
1036
1105
|
/**
|
|
1037
1106
|
* 添加子路由
|
|
1038
|
-
* @template {Router |
|
|
1107
|
+
* @template {Router | Finder} [T=ApiRouter]
|
|
1039
1108
|
* @overload
|
|
1040
1109
|
* @param {string} path 要注册的路径
|
|
1041
1110
|
* @param {T} [router] 要注册的子路由或子路由的 Finder
|
|
1042
|
-
* @returns {T extends
|
|
1111
|
+
* @returns {T extends Finder ? Router : T}
|
|
1043
1112
|
*/
|
|
1044
1113
|
/**
|
|
1045
1114
|
* 添加子路由
|
|
@@ -1056,12 +1125,11 @@
|
|
|
1056
1125
|
route(...p) {
|
|
1057
1126
|
const [a] = p;
|
|
1058
1127
|
if (a && typeof a === 'object' && !(a instanceof Router)) {
|
|
1059
|
-
const path = String.raw(a, ...p.slice(1));
|
|
1060
1128
|
/**
|
|
1061
|
-
* @param {
|
|
1129
|
+
* @param { Finder | Router} [r];
|
|
1062
1130
|
* @returns {any}
|
|
1063
1131
|
*/
|
|
1064
|
-
return r => bindRouter(this.#routes,
|
|
1132
|
+
return r => bindRouter(this.#routes, [a, p.slice(1)], r);
|
|
1065
1133
|
}
|
|
1066
1134
|
const path = typeof a === 'string' ? a : '';
|
|
1067
1135
|
const r = typeof a === 'string' ? p[1] : a;
|
|
@@ -1069,10 +1137,10 @@
|
|
|
1069
1137
|
}
|
|
1070
1138
|
/**
|
|
1071
1139
|
*
|
|
1072
|
-
* @param {
|
|
1140
|
+
* @param {Method} method
|
|
1073
1141
|
* @param {string[]} path
|
|
1074
|
-
* @param {
|
|
1075
|
-
* @returns {Iterable<
|
|
1142
|
+
* @param {Context} ctx
|
|
1143
|
+
* @returns {Iterable<FindItem>}
|
|
1076
1144
|
*/
|
|
1077
1145
|
*find(method, path, ctx) {
|
|
1078
1146
|
for (const route of Array.from(this.#routes)) {
|
|
@@ -1093,29 +1161,29 @@
|
|
|
1093
1161
|
/**
|
|
1094
1162
|
* 注册处理函数
|
|
1095
1163
|
* @overload
|
|
1096
|
-
* @param {
|
|
1097
|
-
* @param {
|
|
1164
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} method 要注册的方法
|
|
1165
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1098
1166
|
* @returns {() => void}
|
|
1099
1167
|
*/
|
|
1100
1168
|
/**
|
|
1101
1169
|
* 注册处理函数
|
|
1102
1170
|
* @overload
|
|
1103
|
-
* @param {
|
|
1171
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} method 要注册的方法
|
|
1104
1172
|
* @param {string} path 要注册的路径
|
|
1105
|
-
* @param {
|
|
1173
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1106
1174
|
* @returns {() => void}
|
|
1107
1175
|
*/
|
|
1108
1176
|
/**
|
|
1109
1177
|
* 注册处理函数
|
|
1110
1178
|
* @overload
|
|
1111
|
-
* @param {
|
|
1179
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} method 要注册的方法
|
|
1112
1180
|
* @param {string} path 要注册的路径
|
|
1113
1181
|
* @returns {Binder}
|
|
1114
1182
|
*/
|
|
1115
1183
|
/**
|
|
1116
|
-
* @param {
|
|
1117
|
-
* @param {string|
|
|
1118
|
-
* @param {
|
|
1184
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} methods
|
|
1185
|
+
* @param {string| Handler} [path]
|
|
1186
|
+
* @param {Handler} [handler]
|
|
1119
1187
|
* @returns {Binder | (() => void)}
|
|
1120
1188
|
*/
|
|
1121
1189
|
verb(methods, path, handler) {
|
|
@@ -1126,14 +1194,14 @@
|
|
|
1126
1194
|
/**
|
|
1127
1195
|
* 注册 HTTP GET/POST/PUT/DELETE 处理函数
|
|
1128
1196
|
* @overload
|
|
1129
|
-
* @param {
|
|
1197
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1130
1198
|
* @returns {() => void}
|
|
1131
1199
|
*/
|
|
1132
1200
|
/**
|
|
1133
1201
|
* 注册处理函数
|
|
1134
1202
|
* @overload
|
|
1135
1203
|
* @param {string} path 要注册的路径
|
|
1136
|
-
* @param {
|
|
1204
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1137
1205
|
* @returns {() => void}
|
|
1138
1206
|
*/
|
|
1139
1207
|
/**
|
|
@@ -1159,14 +1227,14 @@
|
|
|
1159
1227
|
/**
|
|
1160
1228
|
* 注册 HTTP GET 处理函数
|
|
1161
1229
|
* @overload
|
|
1162
|
-
* @param {
|
|
1230
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1163
1231
|
* @returns {() => void}
|
|
1164
1232
|
*/
|
|
1165
1233
|
/**
|
|
1166
1234
|
* 注册 HTTP GET 处理函数
|
|
1167
1235
|
* @overload
|
|
1168
1236
|
* @param {string} path 要注册的路径
|
|
1169
|
-
* @param {
|
|
1237
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1170
1238
|
* @returns {() => void}
|
|
1171
1239
|
*/
|
|
1172
1240
|
/**
|
|
@@ -1190,14 +1258,14 @@
|
|
|
1190
1258
|
/**
|
|
1191
1259
|
* 注册 HTTP POST 处理函数
|
|
1192
1260
|
* @overload
|
|
1193
|
-
* @param {
|
|
1261
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1194
1262
|
* @returns {() => void}
|
|
1195
1263
|
*/
|
|
1196
1264
|
/**
|
|
1197
1265
|
* 注册 HTTP POST 处理函数
|
|
1198
1266
|
* @overload
|
|
1199
1267
|
* @param {string} path 要注册的路径
|
|
1200
|
-
* @param {
|
|
1268
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1201
1269
|
* @returns {() => void}
|
|
1202
1270
|
*/
|
|
1203
1271
|
/**
|
|
@@ -1221,14 +1289,14 @@
|
|
|
1221
1289
|
/**
|
|
1222
1290
|
* 注册 HTTP PUT 处理函数
|
|
1223
1291
|
* @overload
|
|
1224
|
-
* @param {
|
|
1292
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1225
1293
|
* @returns {() => void}
|
|
1226
1294
|
*/
|
|
1227
1295
|
/**
|
|
1228
1296
|
* 注册 HTTP PUT 处理函数
|
|
1229
1297
|
* @overload
|
|
1230
1298
|
* @param {string} path 要注册的路径
|
|
1231
|
-
* @param {
|
|
1299
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1232
1300
|
* @returns {() => void}
|
|
1233
1301
|
*/
|
|
1234
1302
|
/**
|
|
@@ -1252,14 +1320,14 @@
|
|
|
1252
1320
|
/**
|
|
1253
1321
|
* 注册 HTTP DELETE 处理函数
|
|
1254
1322
|
* @overload
|
|
1255
|
-
* @param {
|
|
1323
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1256
1324
|
* @returns {() => void}
|
|
1257
1325
|
*/
|
|
1258
1326
|
/**
|
|
1259
1327
|
* 注册 HTTP DELETE 处理函数
|
|
1260
1328
|
* @overload
|
|
1261
1329
|
* @param {string} path 要注册的路径
|
|
1262
|
-
* @param {
|
|
1330
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1263
1331
|
* @returns {() => void}
|
|
1264
1332
|
*/
|
|
1265
1333
|
/**
|
|
@@ -1283,14 +1351,14 @@
|
|
|
1283
1351
|
/**
|
|
1284
1352
|
* 注册 HTTP HEAD 处理函数
|
|
1285
1353
|
* @overload
|
|
1286
|
-
* @param {
|
|
1354
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1287
1355
|
* @returns {() => void}
|
|
1288
1356
|
*/
|
|
1289
1357
|
/**
|
|
1290
1358
|
* 注册 HTTP HEAD 处理函数
|
|
1291
1359
|
* @overload
|
|
1292
1360
|
* @param {string} path 要注册的路径
|
|
1293
|
-
* @param {
|
|
1361
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1294
1362
|
* @returns {() => void}
|
|
1295
1363
|
*/
|
|
1296
1364
|
/**
|
|
@@ -1314,14 +1382,14 @@
|
|
|
1314
1382
|
/**
|
|
1315
1383
|
* 注册 HTTP OPTIONS 处理函数
|
|
1316
1384
|
* @overload
|
|
1317
|
-
* @param {
|
|
1385
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1318
1386
|
* @returns {() => void}
|
|
1319
1387
|
*/
|
|
1320
1388
|
/**
|
|
1321
1389
|
* 注册 HTTP OPTIONS 处理函数
|
|
1322
1390
|
* @overload
|
|
1323
1391
|
* @param {string} path 要注册的路径
|
|
1324
|
-
* @param {
|
|
1392
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1325
1393
|
* @returns {() => void}
|
|
1326
1394
|
*/
|
|
1327
1395
|
/**
|
|
@@ -1367,21 +1435,22 @@
|
|
|
1367
1435
|
};
|
|
1368
1436
|
}
|
|
1369
1437
|
|
|
1438
|
+
/** @import { Context, Handler, HandlerResult } from './main/types' */
|
|
1370
1439
|
/**
|
|
1371
1440
|
* @callback Onionskin
|
|
1372
|
-
* @param {
|
|
1373
|
-
* @param {() => Promise<
|
|
1374
|
-
* @returns {PromiseLike<
|
|
1441
|
+
* @param {Context} ctx
|
|
1442
|
+
* @param {() => Promise<HandlerResult>} next
|
|
1443
|
+
* @returns {PromiseLike<HandlerResult> | HandlerResult}
|
|
1375
1444
|
*/
|
|
1376
1445
|
|
|
1377
1446
|
const noop = () => {};
|
|
1378
1447
|
/**
|
|
1379
1448
|
*
|
|
1380
1449
|
* @param {...(Onionskin | Onionskin[])} handlers
|
|
1381
|
-
* @returns {
|
|
1450
|
+
* @returns {Handler}
|
|
1382
1451
|
*/
|
|
1383
1452
|
function onionskin(...handlers) {
|
|
1384
|
-
/** @type {
|
|
1453
|
+
/** @type {Handler} */
|
|
1385
1454
|
let handler = noop;
|
|
1386
1455
|
for (const os of handlers.flat()) {
|
|
1387
1456
|
const currentHandler = handler;
|
|
@@ -1390,7 +1459,44 @@
|
|
|
1390
1459
|
return handler;
|
|
1391
1460
|
}
|
|
1392
1461
|
|
|
1462
|
+
/** @import { Context } from './main/types.js' */
|
|
1463
|
+
class Param {
|
|
1464
|
+
#symbol = Symbol();
|
|
1465
|
+
get name() { return this.#symbol}
|
|
1466
|
+
#pattern
|
|
1467
|
+
get pattern() { return this.#pattern; }
|
|
1468
|
+
/**
|
|
1469
|
+
*
|
|
1470
|
+
* @param {RegExp} pattern
|
|
1471
|
+
*/
|
|
1472
|
+
constructor(pattern) {
|
|
1473
|
+
this.#pattern = pattern;
|
|
1474
|
+
}
|
|
1475
|
+
/**
|
|
1476
|
+
*
|
|
1477
|
+
* @param {Context} ctx
|
|
1478
|
+
* @returns {string?}
|
|
1479
|
+
*/
|
|
1480
|
+
param(ctx) {
|
|
1481
|
+
const param = ctx.params[this.#symbol];
|
|
1482
|
+
if (Array.isArray(param)) { return param[0] ?? null; }
|
|
1483
|
+
return param ?? null;
|
|
1484
|
+
}
|
|
1485
|
+
/**
|
|
1486
|
+
*
|
|
1487
|
+
* @param {Context} ctx
|
|
1488
|
+
* @returns {string[]?}
|
|
1489
|
+
*/
|
|
1490
|
+
params(ctx) {
|
|
1491
|
+
const param = ctx.params[this.#symbol];
|
|
1492
|
+
if (typeof param === 'string') { return [param]; }
|
|
1493
|
+
if (Array.isArray(param)) { return param; }
|
|
1494
|
+
return null;
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1393
1498
|
exports.ApiRouter = ApiRouter;
|
|
1499
|
+
exports.Param = Param;
|
|
1394
1500
|
exports.Router = Router;
|
|
1395
1501
|
exports.createFetch = createFetch;
|
|
1396
1502
|
exports.main = main;
|