k99 0.6.1 → 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 +301 -181
- package/index.d.ts +76 -76
- package/index.js +301 -181
- package/index.min.js +2 -2
- package/index.min.mjs +2 -2
- package/index.mjs +301 -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.0
|
|
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,101 @@
|
|
|
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
|
+
}
|
|
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
|
+
|
|
884
963
|
}
|
|
885
964
|
if (!list.length) { return; }
|
|
886
965
|
return path => exec(list, path, end);
|
|
887
966
|
}
|
|
888
967
|
|
|
968
|
+
/** @import { Handler, Method } from '../main/types' */
|
|
969
|
+
/** @import { Binder, Match, Route, RouterRoute } from './index.mjs' */
|
|
970
|
+
|
|
889
971
|
/**
|
|
890
972
|
*
|
|
891
|
-
* @param {(
|
|
892
|
-
* @param {
|
|
893
|
-
* @param {
|
|
894
|
-
* @param {
|
|
973
|
+
* @param {(Route | RouterRoute)[]} routes
|
|
974
|
+
* @param {Set<Method>} methods
|
|
975
|
+
* @param {Match | undefined} match
|
|
976
|
+
* @param {Handler[]} handlers
|
|
895
977
|
* @returns {() => void}
|
|
896
978
|
*/
|
|
897
|
-
function bind(routes, methods,
|
|
898
|
-
/** @type {
|
|
899
|
-
const route = {
|
|
900
|
-
match: toMatch(path || '', true),
|
|
901
|
-
methods: new Set(methods),
|
|
902
|
-
handler,
|
|
903
|
-
};
|
|
979
|
+
function bind(routes, methods, match, handlers) {
|
|
980
|
+
/** @type {Route} */
|
|
981
|
+
const route = { match, methods, handler: ctx => runHandles(ctx, handlers) };
|
|
904
982
|
routes.push(route);
|
|
905
983
|
let removed = false;
|
|
906
984
|
return () => {
|
|
@@ -911,43 +989,49 @@
|
|
|
911
989
|
routes.splice(index, 1);
|
|
912
990
|
};
|
|
913
991
|
}
|
|
914
|
-
/** @type {(v: any) => v is
|
|
992
|
+
/** @type {(v: any) => v is Handler} */
|
|
915
993
|
const findHandler = v => typeof v === 'function';
|
|
916
994
|
/**
|
|
917
995
|
*
|
|
918
|
-
* @param {(
|
|
919
|
-
* @param {
|
|
996
|
+
* @param {(Route | RouterRoute)[]} routes
|
|
997
|
+
* @param {Iterable<Method>} methods
|
|
920
998
|
* @param {any[]} p
|
|
921
|
-
* @returns {
|
|
999
|
+
* @returns {Binder | (() => void)}
|
|
922
1000
|
*/
|
|
923
1001
|
function verb(routes, methods, p) {
|
|
1002
|
+
const methodSet = new Set(methods);
|
|
924
1003
|
if (!p.length) {
|
|
925
|
-
|
|
1004
|
+
const match = undefined;
|
|
1005
|
+
/** @type {Binder} */
|
|
1006
|
+
return (...handlers) => bind(routes, methodSet, match, handlers);
|
|
926
1007
|
}
|
|
927
|
-
const [
|
|
928
|
-
if (
|
|
929
|
-
const
|
|
930
|
-
|
|
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);
|
|
931
1013
|
}
|
|
932
|
-
const
|
|
933
|
-
const
|
|
934
|
-
if (!
|
|
935
|
-
|
|
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);
|
|
936
1019
|
}
|
|
937
|
-
return bind(routes,
|
|
1020
|
+
return bind(routes, methodSet, match, handlers);
|
|
938
1021
|
}
|
|
939
1022
|
|
|
1023
|
+
/** @import { Method } from '../main/types' */
|
|
940
1024
|
const methods = new Set(['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS']);
|
|
941
1025
|
/**
|
|
942
1026
|
*
|
|
943
1027
|
* @param {any} v
|
|
944
|
-
* @returns {v is
|
|
1028
|
+
* @returns {v is Method}
|
|
945
1029
|
*/
|
|
946
1030
|
function isMethod(v) { return methods.has(v); }
|
|
947
1031
|
/**
|
|
948
1032
|
*
|
|
949
|
-
* @param {
|
|
950
|
-
* @returns {
|
|
1033
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} [methods]
|
|
1034
|
+
* @returns {Method[]}
|
|
951
1035
|
*/
|
|
952
1036
|
function getMethods(methods) {
|
|
953
1037
|
if (!methods) {
|
|
@@ -961,25 +1045,24 @@
|
|
|
961
1045
|
.filter(isMethod);
|
|
962
1046
|
}
|
|
963
1047
|
|
|
1048
|
+
/** @import { Context, Handler, Method, Params } from '../main/types' */
|
|
1049
|
+
/** @import { Finder, FindItem } from '../Router.mjs' */
|
|
1050
|
+
|
|
964
1051
|
/**
|
|
965
1052
|
* @callback Match
|
|
966
1053
|
* @param {string[]} paths
|
|
967
|
-
* @returns {[
|
|
1054
|
+
* @returns {[Params, string[]] | undefined}
|
|
968
1055
|
*/
|
|
969
1056
|
|
|
970
|
-
/**
|
|
971
|
-
* @callback Binder
|
|
972
|
-
* @param {import('../main/types').Handler} handler
|
|
973
|
-
* @returns {() => void}
|
|
974
|
-
*/
|
|
1057
|
+
/** @typedef {(handler: Handler, ...handlers: Handler[]) => () => void} Binder */
|
|
975
1058
|
|
|
976
1059
|
/**
|
|
977
1060
|
* @typedef {object} Route
|
|
978
1061
|
* @property {Match} [match] 路径匹配
|
|
979
1062
|
* @property {null} [router]
|
|
980
1063
|
* @property {string} [plugin] 所属插件
|
|
981
|
-
* @property {
|
|
982
|
-
* @property {Set<
|
|
1064
|
+
* @property {Handler} handler 处理函数
|
|
1065
|
+
* @property {Set<Method>} methods 方法列表
|
|
983
1066
|
*/
|
|
984
1067
|
|
|
985
1068
|
/**
|
|
@@ -990,16 +1073,16 @@
|
|
|
990
1073
|
|
|
991
1074
|
|
|
992
1075
|
/**
|
|
993
|
-
* @template {Router |
|
|
1076
|
+
* @template {Router | Finder} [T=ApiRouter]
|
|
994
1077
|
* @callback RouteBinder
|
|
995
1078
|
* @param {T} [router] 要注册的子路由或子路由的 Finder
|
|
996
|
-
* @returns {T extends
|
|
1079
|
+
* @returns {T extends Finder ? Router : T}
|
|
997
1080
|
*/
|
|
998
1081
|
/**
|
|
999
1082
|
*
|
|
1000
1083
|
* @param {(Route | RouterRoute)[]} routes
|
|
1001
|
-
* @param {string} path
|
|
1002
|
-
* @param {Router |
|
|
1084
|
+
* @param {string | [string[], any[]]} path
|
|
1085
|
+
* @param {Router | Finder} [r]
|
|
1003
1086
|
* @returns {Router}
|
|
1004
1087
|
*/
|
|
1005
1088
|
function bindRouter(routes, path, r) {
|
|
@@ -1014,18 +1097,18 @@
|
|
|
1014
1097
|
#routes = [];
|
|
1015
1098
|
/**
|
|
1016
1099
|
* 添加子路由
|
|
1017
|
-
* @template {Router |
|
|
1100
|
+
* @template {Router | Finder} [T=ApiRouter]
|
|
1018
1101
|
* @overload
|
|
1019
1102
|
* @param {T} [router] 要注册的子路由或子路由的 Finder
|
|
1020
|
-
* @returns {T extends
|
|
1103
|
+
* @returns {T extends Finder ? Router : T}
|
|
1021
1104
|
*/
|
|
1022
1105
|
/**
|
|
1023
1106
|
* 添加子路由
|
|
1024
|
-
* @template {Router |
|
|
1107
|
+
* @template {Router | Finder} [T=ApiRouter]
|
|
1025
1108
|
* @overload
|
|
1026
1109
|
* @param {string} path 要注册的路径
|
|
1027
1110
|
* @param {T} [router] 要注册的子路由或子路由的 Finder
|
|
1028
|
-
* @returns {T extends
|
|
1111
|
+
* @returns {T extends Finder ? Router : T}
|
|
1029
1112
|
*/
|
|
1030
1113
|
/**
|
|
1031
1114
|
* 添加子路由
|
|
@@ -1042,12 +1125,11 @@
|
|
|
1042
1125
|
route(...p) {
|
|
1043
1126
|
const [a] = p;
|
|
1044
1127
|
if (a && typeof a === 'object' && !(a instanceof Router)) {
|
|
1045
|
-
const path = String.raw(a, ...p.slice(1));
|
|
1046
1128
|
/**
|
|
1047
|
-
* @param {
|
|
1129
|
+
* @param { Finder | Router} [r];
|
|
1048
1130
|
* @returns {any}
|
|
1049
1131
|
*/
|
|
1050
|
-
return r => bindRouter(this.#routes,
|
|
1132
|
+
return r => bindRouter(this.#routes, [a, p.slice(1)], r);
|
|
1051
1133
|
}
|
|
1052
1134
|
const path = typeof a === 'string' ? a : '';
|
|
1053
1135
|
const r = typeof a === 'string' ? p[1] : a;
|
|
@@ -1055,10 +1137,10 @@
|
|
|
1055
1137
|
}
|
|
1056
1138
|
/**
|
|
1057
1139
|
*
|
|
1058
|
-
* @param {
|
|
1140
|
+
* @param {Method} method
|
|
1059
1141
|
* @param {string[]} path
|
|
1060
|
-
* @param {
|
|
1061
|
-
* @returns {Iterable<
|
|
1142
|
+
* @param {Context} ctx
|
|
1143
|
+
* @returns {Iterable<FindItem>}
|
|
1062
1144
|
*/
|
|
1063
1145
|
*find(method, path, ctx) {
|
|
1064
1146
|
for (const route of Array.from(this.#routes)) {
|
|
@@ -1079,29 +1161,29 @@
|
|
|
1079
1161
|
/**
|
|
1080
1162
|
* 注册处理函数
|
|
1081
1163
|
* @overload
|
|
1082
|
-
* @param {
|
|
1083
|
-
* @param {
|
|
1164
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} method 要注册的方法
|
|
1165
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1084
1166
|
* @returns {() => void}
|
|
1085
1167
|
*/
|
|
1086
1168
|
/**
|
|
1087
1169
|
* 注册处理函数
|
|
1088
1170
|
* @overload
|
|
1089
|
-
* @param {
|
|
1171
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} method 要注册的方法
|
|
1090
1172
|
* @param {string} path 要注册的路径
|
|
1091
|
-
* @param {
|
|
1173
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1092
1174
|
* @returns {() => void}
|
|
1093
1175
|
*/
|
|
1094
1176
|
/**
|
|
1095
1177
|
* 注册处理函数
|
|
1096
1178
|
* @overload
|
|
1097
|
-
* @param {
|
|
1179
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} method 要注册的方法
|
|
1098
1180
|
* @param {string} path 要注册的路径
|
|
1099
1181
|
* @returns {Binder}
|
|
1100
1182
|
*/
|
|
1101
1183
|
/**
|
|
1102
|
-
* @param {
|
|
1103
|
-
* @param {string|
|
|
1104
|
-
* @param {
|
|
1184
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} methods
|
|
1185
|
+
* @param {string| Handler} [path]
|
|
1186
|
+
* @param {Handler} [handler]
|
|
1105
1187
|
* @returns {Binder | (() => void)}
|
|
1106
1188
|
*/
|
|
1107
1189
|
verb(methods, path, handler) {
|
|
@@ -1112,14 +1194,14 @@
|
|
|
1112
1194
|
/**
|
|
1113
1195
|
* 注册 HTTP GET/POST/PUT/DELETE 处理函数
|
|
1114
1196
|
* @overload
|
|
1115
|
-
* @param {
|
|
1197
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1116
1198
|
* @returns {() => void}
|
|
1117
1199
|
*/
|
|
1118
1200
|
/**
|
|
1119
1201
|
* 注册处理函数
|
|
1120
1202
|
* @overload
|
|
1121
1203
|
* @param {string} path 要注册的路径
|
|
1122
|
-
* @param {
|
|
1204
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1123
1205
|
* @returns {() => void}
|
|
1124
1206
|
*/
|
|
1125
1207
|
/**
|
|
@@ -1145,14 +1227,14 @@
|
|
|
1145
1227
|
/**
|
|
1146
1228
|
* 注册 HTTP GET 处理函数
|
|
1147
1229
|
* @overload
|
|
1148
|
-
* @param {
|
|
1230
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1149
1231
|
* @returns {() => void}
|
|
1150
1232
|
*/
|
|
1151
1233
|
/**
|
|
1152
1234
|
* 注册 HTTP GET 处理函数
|
|
1153
1235
|
* @overload
|
|
1154
1236
|
* @param {string} path 要注册的路径
|
|
1155
|
-
* @param {
|
|
1237
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1156
1238
|
* @returns {() => void}
|
|
1157
1239
|
*/
|
|
1158
1240
|
/**
|
|
@@ -1176,14 +1258,14 @@
|
|
|
1176
1258
|
/**
|
|
1177
1259
|
* 注册 HTTP POST 处理函数
|
|
1178
1260
|
* @overload
|
|
1179
|
-
* @param {
|
|
1261
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1180
1262
|
* @returns {() => void}
|
|
1181
1263
|
*/
|
|
1182
1264
|
/**
|
|
1183
1265
|
* 注册 HTTP POST 处理函数
|
|
1184
1266
|
* @overload
|
|
1185
1267
|
* @param {string} path 要注册的路径
|
|
1186
|
-
* @param {
|
|
1268
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1187
1269
|
* @returns {() => void}
|
|
1188
1270
|
*/
|
|
1189
1271
|
/**
|
|
@@ -1207,14 +1289,14 @@
|
|
|
1207
1289
|
/**
|
|
1208
1290
|
* 注册 HTTP PUT 处理函数
|
|
1209
1291
|
* @overload
|
|
1210
|
-
* @param {
|
|
1292
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1211
1293
|
* @returns {() => void}
|
|
1212
1294
|
*/
|
|
1213
1295
|
/**
|
|
1214
1296
|
* 注册 HTTP PUT 处理函数
|
|
1215
1297
|
* @overload
|
|
1216
1298
|
* @param {string} path 要注册的路径
|
|
1217
|
-
* @param {
|
|
1299
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1218
1300
|
* @returns {() => void}
|
|
1219
1301
|
*/
|
|
1220
1302
|
/**
|
|
@@ -1238,14 +1320,14 @@
|
|
|
1238
1320
|
/**
|
|
1239
1321
|
* 注册 HTTP DELETE 处理函数
|
|
1240
1322
|
* @overload
|
|
1241
|
-
* @param {
|
|
1323
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1242
1324
|
* @returns {() => void}
|
|
1243
1325
|
*/
|
|
1244
1326
|
/**
|
|
1245
1327
|
* 注册 HTTP DELETE 处理函数
|
|
1246
1328
|
* @overload
|
|
1247
1329
|
* @param {string} path 要注册的路径
|
|
1248
|
-
* @param {
|
|
1330
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1249
1331
|
* @returns {() => void}
|
|
1250
1332
|
*/
|
|
1251
1333
|
/**
|
|
@@ -1269,14 +1351,14 @@
|
|
|
1269
1351
|
/**
|
|
1270
1352
|
* 注册 HTTP HEAD 处理函数
|
|
1271
1353
|
* @overload
|
|
1272
|
-
* @param {
|
|
1354
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1273
1355
|
* @returns {() => void}
|
|
1274
1356
|
*/
|
|
1275
1357
|
/**
|
|
1276
1358
|
* 注册 HTTP HEAD 处理函数
|
|
1277
1359
|
* @overload
|
|
1278
1360
|
* @param {string} path 要注册的路径
|
|
1279
|
-
* @param {
|
|
1361
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1280
1362
|
* @returns {() => void}
|
|
1281
1363
|
*/
|
|
1282
1364
|
/**
|
|
@@ -1300,14 +1382,14 @@
|
|
|
1300
1382
|
/**
|
|
1301
1383
|
* 注册 HTTP OPTIONS 处理函数
|
|
1302
1384
|
* @overload
|
|
1303
|
-
* @param {
|
|
1385
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1304
1386
|
* @returns {() => void}
|
|
1305
1387
|
*/
|
|
1306
1388
|
/**
|
|
1307
1389
|
* 注册 HTTP OPTIONS 处理函数
|
|
1308
1390
|
* @overload
|
|
1309
1391
|
* @param {string} path 要注册的路径
|
|
1310
|
-
* @param {
|
|
1392
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1311
1393
|
* @returns {() => void}
|
|
1312
1394
|
*/
|
|
1313
1395
|
/**
|
|
@@ -1353,21 +1435,22 @@
|
|
|
1353
1435
|
};
|
|
1354
1436
|
}
|
|
1355
1437
|
|
|
1438
|
+
/** @import { Context, Handler, HandlerResult } from './main/types' */
|
|
1356
1439
|
/**
|
|
1357
1440
|
* @callback Onionskin
|
|
1358
|
-
* @param {
|
|
1359
|
-
* @param {() => Promise<
|
|
1360
|
-
* @returns {PromiseLike<
|
|
1441
|
+
* @param {Context} ctx
|
|
1442
|
+
* @param {() => Promise<HandlerResult>} next
|
|
1443
|
+
* @returns {PromiseLike<HandlerResult> | HandlerResult}
|
|
1361
1444
|
*/
|
|
1362
1445
|
|
|
1363
1446
|
const noop = () => {};
|
|
1364
1447
|
/**
|
|
1365
1448
|
*
|
|
1366
1449
|
* @param {...(Onionskin | Onionskin[])} handlers
|
|
1367
|
-
* @returns {
|
|
1450
|
+
* @returns {Handler}
|
|
1368
1451
|
*/
|
|
1369
1452
|
function onionskin(...handlers) {
|
|
1370
|
-
/** @type {
|
|
1453
|
+
/** @type {Handler} */
|
|
1371
1454
|
let handler = noop;
|
|
1372
1455
|
for (const os of handlers.flat()) {
|
|
1373
1456
|
const currentHandler = handler;
|
|
@@ -1376,7 +1459,44 @@
|
|
|
1376
1459
|
return handler;
|
|
1377
1460
|
}
|
|
1378
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
|
+
|
|
1379
1498
|
exports.ApiRouter = ApiRouter;
|
|
1499
|
+
exports.Param = Param;
|
|
1380
1500
|
exports.Router = Router;
|
|
1381
1501
|
exports.createFetch = createFetch;
|
|
1382
1502
|
exports.main = main;
|