k99 0.6.1 → 0.7.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/index.cjs +302 -181
- package/index.d.ts +101 -77
- package/index.js +302 -181
- package/index.min.js +2 -2
- package/index.min.mjs +2 -2
- package/index.mjs +302 -182
- package/package.json +2 -3
- package/services.cjs +5 -3
- package/services.d.ts +7 -6
- package/services.js +5 -3
- package/services.min.js +1 -1
- package/services.min.mjs +1 -1
- package/services.mjs +5 -3
- package/node/index.cjs +0 -149
- package/node/index.d.cts +0 -49
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* k99 v0.
|
|
2
|
+
* k99 v0.7.1
|
|
3
3
|
* (c) 2019-2025 猛火Fierflame
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
@@ -110,8 +110,7 @@
|
|
|
110
110
|
if (!data) { continue; }
|
|
111
111
|
await write(writer, data);
|
|
112
112
|
}
|
|
113
|
-
|
|
114
|
-
})().catch(() => {});
|
|
113
|
+
})().then(() => writable.close(), r => writable.abort(r)).catch(() => {});
|
|
115
114
|
return [readable, 0, ''];
|
|
116
115
|
}
|
|
117
116
|
/**
|
|
@@ -134,11 +133,12 @@
|
|
|
134
133
|
return body;
|
|
135
134
|
}
|
|
136
135
|
|
|
136
|
+
/** @import { Cookie, CookieOption } from './types' */
|
|
137
137
|
/**
|
|
138
138
|
*
|
|
139
|
-
* @param {
|
|
139
|
+
* @param {Cookie[]} sentCookies
|
|
140
140
|
* @param {string} [name]
|
|
141
|
-
* @returns {Iterable<
|
|
141
|
+
* @returns {Iterable<Cookie>}
|
|
142
142
|
*/
|
|
143
143
|
function *getCookie(sentCookies, name) {
|
|
144
144
|
const list = sentCookies;
|
|
@@ -151,7 +151,7 @@
|
|
|
151
151
|
/**
|
|
152
152
|
*
|
|
153
153
|
* @param {Headers} headers
|
|
154
|
-
* @param {
|
|
154
|
+
* @param {Cookie[]} cookies
|
|
155
155
|
* @returns {void}
|
|
156
156
|
*/
|
|
157
157
|
function setCookiesHeader(headers, cookies) {
|
|
@@ -185,10 +185,10 @@
|
|
|
185
185
|
}
|
|
186
186
|
/**
|
|
187
187
|
*
|
|
188
|
-
* @param {
|
|
188
|
+
* @param {Cookie[]} sentCookies
|
|
189
189
|
* @param {Record<string, string>} cookies
|
|
190
|
-
* @param {string |
|
|
191
|
-
* @param {
|
|
190
|
+
* @param {string | CookieOption} [name]
|
|
191
|
+
* @param {CookieOption | boolean} [opt]
|
|
192
192
|
* @returns {void}
|
|
193
193
|
*/
|
|
194
194
|
function clearCookie(
|
|
@@ -200,11 +200,11 @@
|
|
|
200
200
|
let expire = 'Fri, 31 Dec 1999 16:00:00 GMT';
|
|
201
201
|
if (typeof name === 'string') {
|
|
202
202
|
if (!name) { return; }
|
|
203
|
-
/** @type {
|
|
203
|
+
/** @type {CookieOption} */
|
|
204
204
|
const { domain, path, secure, httpOnly } = opt !== true && opt || {};
|
|
205
205
|
sentCookies.push({ name, value: 'delete', expire, domain, path, secure, httpOnly });
|
|
206
206
|
} else {
|
|
207
|
-
/** @type {
|
|
207
|
+
/** @type {CookieOption} */
|
|
208
208
|
const { domain, path, secure, httpOnly } = name || {};
|
|
209
209
|
sentCookies.length = 0;
|
|
210
210
|
if (opt) {
|
|
@@ -215,6 +215,9 @@
|
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
+
/** @import { Context, Cookie, CookieOption, FindHandler, Method, Options, Params, Service } from './types' */
|
|
219
|
+
|
|
220
|
+
|
|
218
221
|
const noBodyMethods = new Set(['GET', 'OPTIONS']);
|
|
219
222
|
/**
|
|
220
223
|
*
|
|
@@ -251,7 +254,7 @@
|
|
|
251
254
|
*
|
|
252
255
|
* @param {Request} request
|
|
253
256
|
* @param {string | ((request: Request) => string)} [toMethod]
|
|
254
|
-
* @returns {
|
|
257
|
+
* @returns {Method}
|
|
255
258
|
*/
|
|
256
259
|
function getMethod(request, toMethod) {
|
|
257
260
|
let methodStr = '';
|
|
@@ -263,13 +266,13 @@
|
|
|
263
266
|
if (!methodStr || typeof methodStr !== 'string') {
|
|
264
267
|
methodStr = request.method || 'GET';
|
|
265
268
|
}
|
|
266
|
-
return /** @type {
|
|
269
|
+
return /** @type {Method} */(methodStr.toUpperCase());
|
|
267
270
|
}
|
|
268
271
|
/**
|
|
269
272
|
*
|
|
270
273
|
* @param {Request} request
|
|
271
|
-
* @param {
|
|
272
|
-
* @param {
|
|
274
|
+
* @param {FindHandler} getHandler
|
|
275
|
+
* @param {Options} [options]
|
|
273
276
|
* @returns {Promise<Response | null>}
|
|
274
277
|
*/
|
|
275
278
|
function main(
|
|
@@ -279,7 +282,7 @@
|
|
|
279
282
|
/**
|
|
280
283
|
*
|
|
281
284
|
* @param {Request} request
|
|
282
|
-
* @param {
|
|
285
|
+
* @param {Context} [parent]
|
|
283
286
|
* @returns {Promise<Response | null>}
|
|
284
287
|
*/
|
|
285
288
|
function exec(request, parent) {
|
|
@@ -287,10 +290,10 @@
|
|
|
287
290
|
const url = new URL(request.url);
|
|
288
291
|
const { signal, headers } = request;
|
|
289
292
|
const aborted = signal2promise(signal);
|
|
290
|
-
/** @type {Map<
|
|
293
|
+
/** @type {Map<Service<any, any>, Function>} */
|
|
291
294
|
const services = new Map();
|
|
292
295
|
const cookies = getRequestCookies(headers.get('cookie') || '');
|
|
293
|
-
/** @type {
|
|
296
|
+
/** @type {Cookie[]} */
|
|
294
297
|
const sentCookies = [];
|
|
295
298
|
const responseHeaders = new Headers();
|
|
296
299
|
const root = parent?.root;
|
|
@@ -306,9 +309,9 @@
|
|
|
306
309
|
const donePromise = new Promise((a, b) => { resolve = a; reject = b; });
|
|
307
310
|
donePromise.catch(() => {});
|
|
308
311
|
|
|
309
|
-
/** @type {
|
|
312
|
+
/** @type {Params} */
|
|
310
313
|
let params = {};
|
|
311
|
-
/** @type {
|
|
314
|
+
/** @type {Context} */
|
|
312
315
|
const context = {
|
|
313
316
|
environment,
|
|
314
317
|
parent,
|
|
@@ -372,8 +375,8 @@
|
|
|
372
375
|
},
|
|
373
376
|
/**
|
|
374
377
|
*
|
|
375
|
-
* @param {string |
|
|
376
|
-
* @param {
|
|
378
|
+
* @param {string | CookieOption} [name]
|
|
379
|
+
* @param {CookieOption | boolean} [opt]
|
|
377
380
|
* @returns {void}
|
|
378
381
|
*/
|
|
379
382
|
clearCookie(name, opt) {
|
|
@@ -410,69 +413,72 @@
|
|
|
410
413
|
return exec(request);
|
|
411
414
|
}
|
|
412
415
|
|
|
416
|
+
/** @import { FindHandler, Options } from './main/types' */
|
|
417
|
+
|
|
413
418
|
/**
|
|
414
419
|
*
|
|
415
|
-
* @param {
|
|
416
|
-
* @param {
|
|
420
|
+
* @param {FindHandler} getHandler
|
|
421
|
+
* @param {Options} options
|
|
417
422
|
* @returns {(request: Request) => Promise<Response | null>}
|
|
418
423
|
*/
|
|
419
424
|
function make(getHandler, options) {
|
|
420
425
|
return r => main(r, getHandler, options);
|
|
421
426
|
}
|
|
422
427
|
|
|
428
|
+
/** @import { Context, Handler } from './main/types' */
|
|
423
429
|
/**
|
|
424
430
|
*
|
|
425
|
-
* @param {
|
|
426
|
-
* @param {
|
|
431
|
+
* @param {Context} context
|
|
432
|
+
* @param {Handler[]} handlers
|
|
427
433
|
* @returns {Promise<string | boolean | object | undefined>}
|
|
428
434
|
*/
|
|
429
435
|
async function runHandles(context, handlers) {
|
|
430
436
|
for (const handle of handlers) {
|
|
431
437
|
const result = await handle(context);
|
|
432
|
-
if (
|
|
433
|
-
if (!result) { continue; }
|
|
438
|
+
if (result === undefined) { continue; }
|
|
434
439
|
return result;
|
|
435
440
|
}
|
|
436
441
|
}
|
|
437
442
|
|
|
438
443
|
/**
|
|
439
444
|
*
|
|
440
|
-
* @param {...(
|
|
441
|
-
* @returns {
|
|
445
|
+
* @param {...(Handler | Handler[])} handlers
|
|
446
|
+
* @returns {Handler}
|
|
442
447
|
*/
|
|
443
448
|
function merge(...handlers) {
|
|
444
449
|
return ctx => runHandles(ctx, handlers.flat());
|
|
445
450
|
}
|
|
446
451
|
|
|
452
|
+
/** @import { Context, Service } from './main/types' */
|
|
447
453
|
/**
|
|
448
454
|
*
|
|
449
455
|
* @template T
|
|
450
456
|
* @template {any[]} P
|
|
451
457
|
* @overload
|
|
452
|
-
* @param {(ctx:
|
|
453
|
-
* @param {((ctx:
|
|
454
|
-
* @param {
|
|
455
|
-
* @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>}
|
|
456
462
|
*/
|
|
457
463
|
/**
|
|
458
464
|
*
|
|
459
465
|
* @template T
|
|
460
466
|
* @template {any[]} P
|
|
461
467
|
* @overload
|
|
462
|
-
* @param {(ctx:
|
|
463
|
-
* @param {
|
|
464
|
-
* @returns {
|
|
468
|
+
* @param {(ctx: Context, ...p: P) => T} exec
|
|
469
|
+
* @param {Service.Options?} [options]
|
|
470
|
+
* @returns {Service<T, P>}
|
|
465
471
|
*/
|
|
466
472
|
/**
|
|
467
473
|
* @template T
|
|
468
474
|
* @template {any[]} P
|
|
469
|
-
* @param {(ctx:
|
|
470
|
-
* @param {((ctx:
|
|
471
|
-
* @param {
|
|
472
|
-
* @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>}
|
|
473
479
|
*/
|
|
474
480
|
function service(exec, destroy, options) {
|
|
475
|
-
/** @type {
|
|
481
|
+
/** @type {Service<T, P>} */
|
|
476
482
|
const service = function (ctx) {
|
|
477
483
|
if (typeof destroy === 'function') {
|
|
478
484
|
ctx.done(() => destroy(ctx), error => destroy(ctx, error));
|
|
@@ -491,43 +497,44 @@
|
|
|
491
497
|
return service;
|
|
492
498
|
}
|
|
493
499
|
|
|
500
|
+
/** @import { Context, Service, StateService } from './main/types' */
|
|
494
501
|
/**
|
|
495
502
|
*
|
|
496
503
|
* @template T
|
|
497
504
|
* @overload
|
|
498
|
-
* @param {(ctx:
|
|
499
|
-
* @param {
|
|
500
|
-
* @returns {
|
|
505
|
+
* @param {(ctx: Context) => T} init
|
|
506
|
+
* @param {Service.Options} [options]
|
|
507
|
+
* @returns {StateService<T>}
|
|
501
508
|
*/
|
|
502
509
|
/**
|
|
503
510
|
*
|
|
504
511
|
* @template T
|
|
505
512
|
* @overload
|
|
506
|
-
* @param {(ctx:
|
|
507
|
-
* @param {((state: T | undefined, ctx:
|
|
508
|
-
* @param {
|
|
509
|
-
* @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>}
|
|
510
517
|
*/
|
|
511
518
|
/**
|
|
512
519
|
*
|
|
513
520
|
* @template T
|
|
514
521
|
* @overload
|
|
515
|
-
* @param {(ctx:
|
|
516
|
-
* @param {((state: T | undefined, ctx:
|
|
517
|
-
* @param {((state: T, ctx:
|
|
518
|
-
* @param {
|
|
519
|
-
* @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>}
|
|
520
527
|
*/
|
|
521
528
|
/**
|
|
522
529
|
* @template T
|
|
523
|
-
* @param {(ctx:
|
|
524
|
-
* @param {((state: T | undefined, ctx:
|
|
525
|
-
* @param {((state: T, ctx:
|
|
526
|
-
* @param {
|
|
527
|
-
* @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>}
|
|
528
535
|
*/
|
|
529
536
|
function stateService(init, destroy, exec, options) {
|
|
530
|
-
/** @type {
|
|
537
|
+
/** @type {StateService<T>} */
|
|
531
538
|
const service = function (ctx) {
|
|
532
539
|
const state = init(ctx) || /** @type {T} */({});
|
|
533
540
|
if (typeof destroy === 'function') {
|
|
@@ -551,39 +558,40 @@
|
|
|
551
558
|
return service;
|
|
552
559
|
}
|
|
553
560
|
|
|
561
|
+
/** @import { Context, Service, StoreService } from './main/types' */
|
|
554
562
|
/**
|
|
555
563
|
*
|
|
556
564
|
* @template T
|
|
557
565
|
* @overload
|
|
558
|
-
* @param {
|
|
559
|
-
* @returns {
|
|
566
|
+
* @param {Service.Options?} [options]
|
|
567
|
+
* @returns {StoreService<T>}
|
|
560
568
|
*/
|
|
561
569
|
/**
|
|
562
570
|
*
|
|
563
571
|
* @template T
|
|
564
572
|
* @overload
|
|
565
|
-
* @param {((state: T | undefined, ctx:
|
|
566
|
-
* @param {
|
|
567
|
-
* @returns {
|
|
573
|
+
* @param {((state: T | undefined, ctx: Context, error?: unknown) => PromiseLike<void> | void)?} [destroy]
|
|
574
|
+
* @param {Service.Options?} [options]
|
|
575
|
+
* @returns {StoreService<T>}
|
|
568
576
|
*/
|
|
569
577
|
/**
|
|
570
578
|
*
|
|
571
579
|
* @template T
|
|
572
580
|
* @overload
|
|
573
|
-
* @param {((state: T | undefined, ctx:
|
|
574
|
-
* @param {((state: T | undefined, ctx:
|
|
575
|
-
* @param {
|
|
576
|
-
* @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>}
|
|
577
585
|
*/
|
|
578
586
|
/**
|
|
579
587
|
* @template T
|
|
580
|
-
* @param {((state: T | undefined, ctx:
|
|
581
|
-
* @param {((state: T | undefined, ctx:
|
|
582
|
-
* @param {
|
|
583
|
-
* @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>}
|
|
584
592
|
*/
|
|
585
593
|
function storeService(destroy, exec, options) {
|
|
586
|
-
/** @type {
|
|
594
|
+
/** @type {StoreService<T>} */
|
|
587
595
|
const service = function (ctx) {
|
|
588
596
|
/** @type {T | undefined} */
|
|
589
597
|
let state;
|
|
@@ -620,16 +628,18 @@
|
|
|
620
628
|
return service;
|
|
621
629
|
}
|
|
622
630
|
|
|
631
|
+
/** @import { Handler } from './main/types' */
|
|
632
|
+
/** @import { Onionskin } from './onionskin.mjs' */
|
|
623
633
|
/**
|
|
624
634
|
* @callback Packer
|
|
625
|
-
* @param {
|
|
626
|
-
* @returns {
|
|
635
|
+
* @param {Handler} handler
|
|
636
|
+
* @returns {Handler}
|
|
627
637
|
*/
|
|
628
638
|
/** @type {Packer} */
|
|
629
639
|
const noop$1 = h => h;
|
|
630
640
|
/**
|
|
631
641
|
*
|
|
632
|
-
* @param {
|
|
642
|
+
* @param {Onionskin} onionskin
|
|
633
643
|
* @param {Packer} [packer]
|
|
634
644
|
* @returns {Packer}
|
|
635
645
|
*/
|
|
@@ -640,30 +650,33 @@
|
|
|
640
650
|
};
|
|
641
651
|
}
|
|
642
652
|
|
|
653
|
+
/** @import { Context, FindHandler, Handler, Method, Params } from './main/types' */
|
|
654
|
+
/** @import { Onionskin } from './onionskin.mjs' */
|
|
655
|
+
|
|
643
656
|
/**
|
|
644
657
|
* @callback Guard
|
|
645
|
-
* @param {
|
|
646
|
-
* @returns {PromiseLike<boolean |
|
|
658
|
+
* @param {Context} ctx
|
|
659
|
+
* @returns {PromiseLike<boolean | Handler | void> | boolean | Handler | void}
|
|
647
660
|
*/
|
|
648
661
|
/**
|
|
649
|
-
* @typedef {[
|
|
662
|
+
* @typedef {[Handler | Router, Record<string | symbol, any>, string[]]} FindItem
|
|
650
663
|
*/
|
|
651
664
|
/**
|
|
652
665
|
* @callback Finder
|
|
653
666
|
* @this {Router}
|
|
654
|
-
* @param {
|
|
667
|
+
* @param {Method} method
|
|
655
668
|
* @param {string[]} path
|
|
656
|
-
* @param {
|
|
669
|
+
* @param {Context} ctx
|
|
657
670
|
* @returns {AsyncIterable<FindItem> | Iterable<FindItem>}
|
|
658
671
|
*/
|
|
659
672
|
|
|
660
673
|
/**
|
|
661
674
|
*
|
|
662
675
|
* @param {Set<Guard>} guards
|
|
663
|
-
* @param {
|
|
676
|
+
* @param {Context} ctx
|
|
664
677
|
* @param {(v: any) => void} setParams
|
|
665
678
|
* @param {object} params
|
|
666
|
-
* @returns {Promise<boolean |
|
|
679
|
+
* @returns {Promise<boolean | Handler>}
|
|
667
680
|
*/
|
|
668
681
|
async function execGuard(guards, ctx, setParams, params) {
|
|
669
682
|
if (!guards.size) { return true; }
|
|
@@ -682,12 +695,12 @@
|
|
|
682
695
|
|
|
683
696
|
/**
|
|
684
697
|
*
|
|
685
|
-
* @param {Router |
|
|
698
|
+
* @param {Router | Handler} route
|
|
686
699
|
* @param {string[]} path
|
|
687
|
-
* @param {
|
|
688
|
-
* @param {(v:
|
|
689
|
-
* @param {
|
|
690
|
-
* @returns {Promise<
|
|
700
|
+
* @param {Context} ctx
|
|
701
|
+
* @param {(v: Params) => void} setParams
|
|
702
|
+
* @param {Params} params
|
|
703
|
+
* @returns {Promise<Handler | null>}
|
|
691
704
|
*/
|
|
692
705
|
async function find(route, path, ctx, setParams, params) {
|
|
693
706
|
if (!(route instanceof Router)) {
|
|
@@ -726,16 +739,16 @@
|
|
|
726
739
|
disabled = false;
|
|
727
740
|
/**
|
|
728
741
|
* @abstract
|
|
729
|
-
* @param {
|
|
742
|
+
* @param {Method} method
|
|
730
743
|
* @param {string[]} path
|
|
731
|
-
* @param {
|
|
744
|
+
* @param {Context} ctx
|
|
732
745
|
* @returns {AsyncIterable<FindItem> | Iterable<FindItem>}
|
|
733
746
|
*/
|
|
734
747
|
find(method, path, ctx) { return []; }
|
|
735
748
|
/**
|
|
736
749
|
*
|
|
737
750
|
* @param {Router[]} routers
|
|
738
|
-
* @returns {
|
|
751
|
+
* @returns {FindHandler}
|
|
739
752
|
*/
|
|
740
753
|
static make(routers) {
|
|
741
754
|
return async (ctx, setParams) => {
|
|
@@ -763,19 +776,21 @@
|
|
|
763
776
|
guards = new Set();
|
|
764
777
|
/**
|
|
765
778
|
*
|
|
766
|
-
* @param {
|
|
767
|
-
* @returns {
|
|
779
|
+
* @param {Handler} h
|
|
780
|
+
* @returns {Handler}
|
|
768
781
|
*/
|
|
769
782
|
__onionskin = (h) => h;
|
|
770
|
-
/** @param {
|
|
783
|
+
/** @param {Onionskin} os */
|
|
771
784
|
onionskin(os) { this.__onionskin = packer(os, this.__onionskin); }
|
|
772
785
|
}
|
|
773
786
|
|
|
787
|
+
/** @import { Match } from './index.mjs' */
|
|
788
|
+
/** @import { Params } from '../main/types.js' */
|
|
774
789
|
/**
|
|
775
790
|
* @typedef {object} Pattern
|
|
776
|
-
* @property {string} name
|
|
777
|
-
* @property {boolean} optional
|
|
778
|
-
* @property {boolean} many
|
|
791
|
+
* @property {string | symbol} name
|
|
792
|
+
* @property {boolean} [optional]
|
|
793
|
+
* @property {boolean} [many]
|
|
779
794
|
* @property {RegExp} pattern
|
|
780
795
|
*/
|
|
781
796
|
|
|
@@ -846,7 +861,7 @@
|
|
|
846
861
|
* @returns {[Record<string, string | string[]>, string[]] | undefined}
|
|
847
862
|
*/
|
|
848
863
|
function exec(match, path, end) {
|
|
849
|
-
/** @type {
|
|
864
|
+
/** @type {Params} */
|
|
850
865
|
const params = {};
|
|
851
866
|
for (let i = 0; i < match.length; i++) {
|
|
852
867
|
const m = match[i];
|
|
@@ -869,38 +884,102 @@
|
|
|
869
884
|
return [params, []];
|
|
870
885
|
|
|
871
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
|
+
}
|
|
872
915
|
/**
|
|
873
916
|
*
|
|
874
|
-
* @param {string} path
|
|
917
|
+
* @param {string | [string[], any[]]} path
|
|
875
918
|
* @param {boolean} end
|
|
876
|
-
* @returns {
|
|
919
|
+
* @returns {Match | undefined}
|
|
877
920
|
*/
|
|
878
921
|
function toMatch(path, end) {
|
|
879
922
|
/** @type {(Pattern | string)[]} */
|
|
880
923
|
const list = [];
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
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
|
+
continue;
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
const last = paths.pop() || '';
|
|
956
|
+
const strings = paths.map((v, i) => [v, values[i]]).flat();
|
|
957
|
+
strings.push(last);
|
|
958
|
+
const p = strings.join('');
|
|
959
|
+
if (!p || /^\.+$/.test(p)) { continue; }
|
|
960
|
+
list.push(parse(p));
|
|
961
|
+
continue;
|
|
962
|
+
}
|
|
963
|
+
|
|
884
964
|
}
|
|
885
965
|
if (!list.length) { return; }
|
|
886
966
|
return path => exec(list, path, end);
|
|
887
967
|
}
|
|
888
968
|
|
|
969
|
+
/** @import { Handler, Method } from '../main/types' */
|
|
970
|
+
/** @import { Binder, Match, Route, RouterRoute } from './index.mjs' */
|
|
971
|
+
|
|
889
972
|
/**
|
|
890
973
|
*
|
|
891
|
-
* @param {(
|
|
892
|
-
* @param {
|
|
893
|
-
* @param {
|
|
894
|
-
* @param {
|
|
974
|
+
* @param {(Route | RouterRoute)[]} routes
|
|
975
|
+
* @param {Set<Method>} methods
|
|
976
|
+
* @param {Match | undefined} match
|
|
977
|
+
* @param {Handler[]} handlers
|
|
895
978
|
* @returns {() => void}
|
|
896
979
|
*/
|
|
897
|
-
function bind(routes, methods,
|
|
898
|
-
/** @type {
|
|
899
|
-
const route = {
|
|
900
|
-
match: toMatch(path || '', true),
|
|
901
|
-
methods: new Set(methods),
|
|
902
|
-
handler,
|
|
903
|
-
};
|
|
980
|
+
function bind(routes, methods, match, handlers) {
|
|
981
|
+
/** @type {Route} */
|
|
982
|
+
const route = { match, methods, handler: ctx => runHandles(ctx, handlers) };
|
|
904
983
|
routes.push(route);
|
|
905
984
|
let removed = false;
|
|
906
985
|
return () => {
|
|
@@ -911,43 +990,49 @@
|
|
|
911
990
|
routes.splice(index, 1);
|
|
912
991
|
};
|
|
913
992
|
}
|
|
914
|
-
/** @type {(v: any) => v is
|
|
993
|
+
/** @type {(v: any) => v is Handler} */
|
|
915
994
|
const findHandler = v => typeof v === 'function';
|
|
916
995
|
/**
|
|
917
996
|
*
|
|
918
|
-
* @param {(
|
|
919
|
-
* @param {
|
|
997
|
+
* @param {(Route | RouterRoute)[]} routes
|
|
998
|
+
* @param {Iterable<Method>} methods
|
|
920
999
|
* @param {any[]} p
|
|
921
|
-
* @returns {
|
|
1000
|
+
* @returns {Binder | (() => void)}
|
|
922
1001
|
*/
|
|
923
1002
|
function verb(routes, methods, p) {
|
|
1003
|
+
const methodSet = new Set(methods);
|
|
924
1004
|
if (!p.length) {
|
|
925
|
-
|
|
1005
|
+
const match = undefined;
|
|
1006
|
+
/** @type {Binder} */
|
|
1007
|
+
return (...handlers) => bind(routes, methodSet, match, handlers);
|
|
926
1008
|
}
|
|
927
|
-
const [
|
|
928
|
-
if (
|
|
929
|
-
const
|
|
930
|
-
|
|
1009
|
+
const [path] = p;
|
|
1010
|
+
if (path && typeof path === 'object') {
|
|
1011
|
+
const match = toMatch([path, p.slice(1)], true);
|
|
1012
|
+
/** @type {Binder} */
|
|
1013
|
+
return (...handlers) => bind(routes, methodSet, match, handlers);
|
|
931
1014
|
}
|
|
932
|
-
const
|
|
933
|
-
const
|
|
934
|
-
if (!
|
|
935
|
-
|
|
1015
|
+
const match = toMatch(typeof path === 'string' ? path : '', true);
|
|
1016
|
+
const handlers = p.filter(findHandler);
|
|
1017
|
+
if (!handlers.length) {
|
|
1018
|
+
/** @type {Binder} */
|
|
1019
|
+
return (...handlers) => bind(routes, methodSet, match, handlers);
|
|
936
1020
|
}
|
|
937
|
-
return bind(routes,
|
|
1021
|
+
return bind(routes, methodSet, match, handlers);
|
|
938
1022
|
}
|
|
939
1023
|
|
|
1024
|
+
/** @import { Method } from '../main/types' */
|
|
940
1025
|
const methods = new Set(['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS']);
|
|
941
1026
|
/**
|
|
942
1027
|
*
|
|
943
1028
|
* @param {any} v
|
|
944
|
-
* @returns {v is
|
|
1029
|
+
* @returns {v is Method}
|
|
945
1030
|
*/
|
|
946
1031
|
function isMethod(v) { return methods.has(v); }
|
|
947
1032
|
/**
|
|
948
1033
|
*
|
|
949
|
-
* @param {
|
|
950
|
-
* @returns {
|
|
1034
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} [methods]
|
|
1035
|
+
* @returns {Method[]}
|
|
951
1036
|
*/
|
|
952
1037
|
function getMethods(methods) {
|
|
953
1038
|
if (!methods) {
|
|
@@ -961,25 +1046,24 @@
|
|
|
961
1046
|
.filter(isMethod);
|
|
962
1047
|
}
|
|
963
1048
|
|
|
1049
|
+
/** @import { Context, Handler, Method, Params } from '../main/types' */
|
|
1050
|
+
/** @import { Finder, FindItem } from '../Router.mjs' */
|
|
1051
|
+
|
|
964
1052
|
/**
|
|
965
1053
|
* @callback Match
|
|
966
1054
|
* @param {string[]} paths
|
|
967
|
-
* @returns {[
|
|
1055
|
+
* @returns {[Params, string[]] | undefined}
|
|
968
1056
|
*/
|
|
969
1057
|
|
|
970
|
-
/**
|
|
971
|
-
* @callback Binder
|
|
972
|
-
* @param {import('../main/types').Handler} handler
|
|
973
|
-
* @returns {() => void}
|
|
974
|
-
*/
|
|
1058
|
+
/** @typedef {(handler: Handler, ...handlers: Handler[]) => () => void} Binder */
|
|
975
1059
|
|
|
976
1060
|
/**
|
|
977
1061
|
* @typedef {object} Route
|
|
978
1062
|
* @property {Match} [match] 路径匹配
|
|
979
1063
|
* @property {null} [router]
|
|
980
1064
|
* @property {string} [plugin] 所属插件
|
|
981
|
-
* @property {
|
|
982
|
-
* @property {Set<
|
|
1065
|
+
* @property {Handler} handler 处理函数
|
|
1066
|
+
* @property {Set<Method>} methods 方法列表
|
|
983
1067
|
*/
|
|
984
1068
|
|
|
985
1069
|
/**
|
|
@@ -990,16 +1074,16 @@
|
|
|
990
1074
|
|
|
991
1075
|
|
|
992
1076
|
/**
|
|
993
|
-
* @template {Router |
|
|
1077
|
+
* @template {Router | Finder} [T=ApiRouter]
|
|
994
1078
|
* @callback RouteBinder
|
|
995
1079
|
* @param {T} [router] 要注册的子路由或子路由的 Finder
|
|
996
|
-
* @returns {T extends
|
|
1080
|
+
* @returns {T extends Finder ? Router : T}
|
|
997
1081
|
*/
|
|
998
1082
|
/**
|
|
999
1083
|
*
|
|
1000
1084
|
* @param {(Route | RouterRoute)[]} routes
|
|
1001
|
-
* @param {string} path
|
|
1002
|
-
* @param {Router |
|
|
1085
|
+
* @param {string | [string[], any[]]} path
|
|
1086
|
+
* @param {Router | Finder} [r]
|
|
1003
1087
|
* @returns {Router}
|
|
1004
1088
|
*/
|
|
1005
1089
|
function bindRouter(routes, path, r) {
|
|
@@ -1014,18 +1098,18 @@
|
|
|
1014
1098
|
#routes = [];
|
|
1015
1099
|
/**
|
|
1016
1100
|
* 添加子路由
|
|
1017
|
-
* @template {Router |
|
|
1101
|
+
* @template {Router | Finder} [T=ApiRouter]
|
|
1018
1102
|
* @overload
|
|
1019
1103
|
* @param {T} [router] 要注册的子路由或子路由的 Finder
|
|
1020
|
-
* @returns {T extends
|
|
1104
|
+
* @returns {T extends Finder ? Router : T}
|
|
1021
1105
|
*/
|
|
1022
1106
|
/**
|
|
1023
1107
|
* 添加子路由
|
|
1024
|
-
* @template {Router |
|
|
1108
|
+
* @template {Router | Finder} [T=ApiRouter]
|
|
1025
1109
|
* @overload
|
|
1026
1110
|
* @param {string} path 要注册的路径
|
|
1027
1111
|
* @param {T} [router] 要注册的子路由或子路由的 Finder
|
|
1028
|
-
* @returns {T extends
|
|
1112
|
+
* @returns {T extends Finder ? Router : T}
|
|
1029
1113
|
*/
|
|
1030
1114
|
/**
|
|
1031
1115
|
* 添加子路由
|
|
@@ -1042,12 +1126,11 @@
|
|
|
1042
1126
|
route(...p) {
|
|
1043
1127
|
const [a] = p;
|
|
1044
1128
|
if (a && typeof a === 'object' && !(a instanceof Router)) {
|
|
1045
|
-
const path = String.raw(a, ...p.slice(1));
|
|
1046
1129
|
/**
|
|
1047
|
-
* @param {
|
|
1130
|
+
* @param { Finder | Router} [r];
|
|
1048
1131
|
* @returns {any}
|
|
1049
1132
|
*/
|
|
1050
|
-
return r => bindRouter(this.#routes,
|
|
1133
|
+
return r => bindRouter(this.#routes, [a, p.slice(1)], r);
|
|
1051
1134
|
}
|
|
1052
1135
|
const path = typeof a === 'string' ? a : '';
|
|
1053
1136
|
const r = typeof a === 'string' ? p[1] : a;
|
|
@@ -1055,10 +1138,10 @@
|
|
|
1055
1138
|
}
|
|
1056
1139
|
/**
|
|
1057
1140
|
*
|
|
1058
|
-
* @param {
|
|
1141
|
+
* @param {Method} method
|
|
1059
1142
|
* @param {string[]} path
|
|
1060
|
-
* @param {
|
|
1061
|
-
* @returns {Iterable<
|
|
1143
|
+
* @param {Context} ctx
|
|
1144
|
+
* @returns {Iterable<FindItem>}
|
|
1062
1145
|
*/
|
|
1063
1146
|
*find(method, path, ctx) {
|
|
1064
1147
|
for (const route of Array.from(this.#routes)) {
|
|
@@ -1079,29 +1162,29 @@
|
|
|
1079
1162
|
/**
|
|
1080
1163
|
* 注册处理函数
|
|
1081
1164
|
* @overload
|
|
1082
|
-
* @param {
|
|
1083
|
-
* @param {
|
|
1165
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} method 要注册的方法
|
|
1166
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1084
1167
|
* @returns {() => void}
|
|
1085
1168
|
*/
|
|
1086
1169
|
/**
|
|
1087
1170
|
* 注册处理函数
|
|
1088
1171
|
* @overload
|
|
1089
|
-
* @param {
|
|
1172
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} method 要注册的方法
|
|
1090
1173
|
* @param {string} path 要注册的路径
|
|
1091
|
-
* @param {
|
|
1174
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1092
1175
|
* @returns {() => void}
|
|
1093
1176
|
*/
|
|
1094
1177
|
/**
|
|
1095
1178
|
* 注册处理函数
|
|
1096
1179
|
* @overload
|
|
1097
|
-
* @param {
|
|
1180
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} method 要注册的方法
|
|
1098
1181
|
* @param {string} path 要注册的路径
|
|
1099
1182
|
* @returns {Binder}
|
|
1100
1183
|
*/
|
|
1101
1184
|
/**
|
|
1102
|
-
* @param {
|
|
1103
|
-
* @param {string|
|
|
1104
|
-
* @param {
|
|
1185
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} methods
|
|
1186
|
+
* @param {string| Handler} [path]
|
|
1187
|
+
* @param {Handler} [handler]
|
|
1105
1188
|
* @returns {Binder | (() => void)}
|
|
1106
1189
|
*/
|
|
1107
1190
|
verb(methods, path, handler) {
|
|
@@ -1112,14 +1195,14 @@
|
|
|
1112
1195
|
/**
|
|
1113
1196
|
* 注册 HTTP GET/POST/PUT/DELETE 处理函数
|
|
1114
1197
|
* @overload
|
|
1115
|
-
* @param {
|
|
1198
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1116
1199
|
* @returns {() => void}
|
|
1117
1200
|
*/
|
|
1118
1201
|
/**
|
|
1119
1202
|
* 注册处理函数
|
|
1120
1203
|
* @overload
|
|
1121
1204
|
* @param {string} path 要注册的路径
|
|
1122
|
-
* @param {
|
|
1205
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1123
1206
|
* @returns {() => void}
|
|
1124
1207
|
*/
|
|
1125
1208
|
/**
|
|
@@ -1145,14 +1228,14 @@
|
|
|
1145
1228
|
/**
|
|
1146
1229
|
* 注册 HTTP GET 处理函数
|
|
1147
1230
|
* @overload
|
|
1148
|
-
* @param {
|
|
1231
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1149
1232
|
* @returns {() => void}
|
|
1150
1233
|
*/
|
|
1151
1234
|
/**
|
|
1152
1235
|
* 注册 HTTP GET 处理函数
|
|
1153
1236
|
* @overload
|
|
1154
1237
|
* @param {string} path 要注册的路径
|
|
1155
|
-
* @param {
|
|
1238
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1156
1239
|
* @returns {() => void}
|
|
1157
1240
|
*/
|
|
1158
1241
|
/**
|
|
@@ -1176,14 +1259,14 @@
|
|
|
1176
1259
|
/**
|
|
1177
1260
|
* 注册 HTTP POST 处理函数
|
|
1178
1261
|
* @overload
|
|
1179
|
-
* @param {
|
|
1262
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1180
1263
|
* @returns {() => void}
|
|
1181
1264
|
*/
|
|
1182
1265
|
/**
|
|
1183
1266
|
* 注册 HTTP POST 处理函数
|
|
1184
1267
|
* @overload
|
|
1185
1268
|
* @param {string} path 要注册的路径
|
|
1186
|
-
* @param {
|
|
1269
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1187
1270
|
* @returns {() => void}
|
|
1188
1271
|
*/
|
|
1189
1272
|
/**
|
|
@@ -1207,14 +1290,14 @@
|
|
|
1207
1290
|
/**
|
|
1208
1291
|
* 注册 HTTP PUT 处理函数
|
|
1209
1292
|
* @overload
|
|
1210
|
-
* @param {
|
|
1293
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1211
1294
|
* @returns {() => void}
|
|
1212
1295
|
*/
|
|
1213
1296
|
/**
|
|
1214
1297
|
* 注册 HTTP PUT 处理函数
|
|
1215
1298
|
* @overload
|
|
1216
1299
|
* @param {string} path 要注册的路径
|
|
1217
|
-
* @param {
|
|
1300
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1218
1301
|
* @returns {() => void}
|
|
1219
1302
|
*/
|
|
1220
1303
|
/**
|
|
@@ -1238,14 +1321,14 @@
|
|
|
1238
1321
|
/**
|
|
1239
1322
|
* 注册 HTTP DELETE 处理函数
|
|
1240
1323
|
* @overload
|
|
1241
|
-
* @param {
|
|
1324
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1242
1325
|
* @returns {() => void}
|
|
1243
1326
|
*/
|
|
1244
1327
|
/**
|
|
1245
1328
|
* 注册 HTTP DELETE 处理函数
|
|
1246
1329
|
* @overload
|
|
1247
1330
|
* @param {string} path 要注册的路径
|
|
1248
|
-
* @param {
|
|
1331
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1249
1332
|
* @returns {() => void}
|
|
1250
1333
|
*/
|
|
1251
1334
|
/**
|
|
@@ -1269,14 +1352,14 @@
|
|
|
1269
1352
|
/**
|
|
1270
1353
|
* 注册 HTTP HEAD 处理函数
|
|
1271
1354
|
* @overload
|
|
1272
|
-
* @param {
|
|
1355
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1273
1356
|
* @returns {() => void}
|
|
1274
1357
|
*/
|
|
1275
1358
|
/**
|
|
1276
1359
|
* 注册 HTTP HEAD 处理函数
|
|
1277
1360
|
* @overload
|
|
1278
1361
|
* @param {string} path 要注册的路径
|
|
1279
|
-
* @param {
|
|
1362
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1280
1363
|
* @returns {() => void}
|
|
1281
1364
|
*/
|
|
1282
1365
|
/**
|
|
@@ -1300,14 +1383,14 @@
|
|
|
1300
1383
|
/**
|
|
1301
1384
|
* 注册 HTTP OPTIONS 处理函数
|
|
1302
1385
|
* @overload
|
|
1303
|
-
* @param {
|
|
1386
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1304
1387
|
* @returns {() => void}
|
|
1305
1388
|
*/
|
|
1306
1389
|
/**
|
|
1307
1390
|
* 注册 HTTP OPTIONS 处理函数
|
|
1308
1391
|
* @overload
|
|
1309
1392
|
* @param {string} path 要注册的路径
|
|
1310
|
-
* @param {
|
|
1393
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1311
1394
|
* @returns {() => void}
|
|
1312
1395
|
*/
|
|
1313
1396
|
/**
|
|
@@ -1353,21 +1436,22 @@
|
|
|
1353
1436
|
};
|
|
1354
1437
|
}
|
|
1355
1438
|
|
|
1439
|
+
/** @import { Context, Handler, HandlerResult } from './main/types' */
|
|
1356
1440
|
/**
|
|
1357
1441
|
* @callback Onionskin
|
|
1358
|
-
* @param {
|
|
1359
|
-
* @param {() => Promise<
|
|
1360
|
-
* @returns {PromiseLike<
|
|
1442
|
+
* @param {Context} ctx
|
|
1443
|
+
* @param {() => Promise<HandlerResult>} next
|
|
1444
|
+
* @returns {PromiseLike<HandlerResult> | HandlerResult}
|
|
1361
1445
|
*/
|
|
1362
1446
|
|
|
1363
1447
|
const noop = () => {};
|
|
1364
1448
|
/**
|
|
1365
1449
|
*
|
|
1366
1450
|
* @param {...(Onionskin | Onionskin[])} handlers
|
|
1367
|
-
* @returns {
|
|
1451
|
+
* @returns {Handler}
|
|
1368
1452
|
*/
|
|
1369
1453
|
function onionskin(...handlers) {
|
|
1370
|
-
/** @type {
|
|
1454
|
+
/** @type {Handler} */
|
|
1371
1455
|
let handler = noop;
|
|
1372
1456
|
for (const os of handlers.flat()) {
|
|
1373
1457
|
const currentHandler = handler;
|
|
@@ -1376,7 +1460,44 @@
|
|
|
1376
1460
|
return handler;
|
|
1377
1461
|
}
|
|
1378
1462
|
|
|
1463
|
+
/** @import { Context } from './main/types.js' */
|
|
1464
|
+
class Param {
|
|
1465
|
+
#symbol = Symbol();
|
|
1466
|
+
get name() { return this.#symbol}
|
|
1467
|
+
#pattern
|
|
1468
|
+
get pattern() { return this.#pattern; }
|
|
1469
|
+
/**
|
|
1470
|
+
*
|
|
1471
|
+
* @param {RegExp?} [pattern]
|
|
1472
|
+
*/
|
|
1473
|
+
constructor(pattern) {
|
|
1474
|
+
this.#pattern = pattern;
|
|
1475
|
+
}
|
|
1476
|
+
/**
|
|
1477
|
+
*
|
|
1478
|
+
* @param {Context} ctx
|
|
1479
|
+
* @returns {string?}
|
|
1480
|
+
*/
|
|
1481
|
+
param(ctx) {
|
|
1482
|
+
const param = ctx.params[this.#symbol];
|
|
1483
|
+
if (Array.isArray(param)) { return param[0] ?? null; }
|
|
1484
|
+
return param ?? null;
|
|
1485
|
+
}
|
|
1486
|
+
/**
|
|
1487
|
+
*
|
|
1488
|
+
* @param {Context} ctx
|
|
1489
|
+
* @returns {string[]?}
|
|
1490
|
+
*/
|
|
1491
|
+
params(ctx) {
|
|
1492
|
+
const param = ctx.params[this.#symbol];
|
|
1493
|
+
if (typeof param === 'string') { return [param]; }
|
|
1494
|
+
if (Array.isArray(param)) { return param; }
|
|
1495
|
+
return null;
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1379
1499
|
exports.ApiRouter = ApiRouter;
|
|
1500
|
+
exports.Param = Param;
|
|
1380
1501
|
exports.Router = Router;
|
|
1381
1502
|
exports.createFetch = createFetch;
|
|
1382
1503
|
exports.main = main;
|