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.mjs
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
|
*/
|
|
@@ -104,8 +104,7 @@ function toBodyData(result, aborted) {
|
|
|
104
104
|
if (!data) { continue; }
|
|
105
105
|
await write(writer, data);
|
|
106
106
|
}
|
|
107
|
-
|
|
108
|
-
})().catch(() => {});
|
|
107
|
+
})().then(() => writable.close(), r => writable.abort(r)).catch(() => {});
|
|
109
108
|
return [readable, 0, ''];
|
|
110
109
|
}
|
|
111
110
|
/**
|
|
@@ -128,11 +127,12 @@ function toBody(result, headers, aborted) {
|
|
|
128
127
|
return body;
|
|
129
128
|
}
|
|
130
129
|
|
|
130
|
+
/** @import { Cookie, CookieOption } from './types' */
|
|
131
131
|
/**
|
|
132
132
|
*
|
|
133
|
-
* @param {
|
|
133
|
+
* @param {Cookie[]} sentCookies
|
|
134
134
|
* @param {string} [name]
|
|
135
|
-
* @returns {Iterable<
|
|
135
|
+
* @returns {Iterable<Cookie>}
|
|
136
136
|
*/
|
|
137
137
|
function *getCookie(sentCookies, name) {
|
|
138
138
|
const list = sentCookies;
|
|
@@ -145,7 +145,7 @@ function *getCookie(sentCookies, name) {
|
|
|
145
145
|
/**
|
|
146
146
|
*
|
|
147
147
|
* @param {Headers} headers
|
|
148
|
-
* @param {
|
|
148
|
+
* @param {Cookie[]} cookies
|
|
149
149
|
* @returns {void}
|
|
150
150
|
*/
|
|
151
151
|
function setCookiesHeader(headers, cookies) {
|
|
@@ -179,10 +179,10 @@ function getRequestCookies(cookie) {
|
|
|
179
179
|
}
|
|
180
180
|
/**
|
|
181
181
|
*
|
|
182
|
-
* @param {
|
|
182
|
+
* @param {Cookie[]} sentCookies
|
|
183
183
|
* @param {Record<string, string>} cookies
|
|
184
|
-
* @param {string |
|
|
185
|
-
* @param {
|
|
184
|
+
* @param {string | CookieOption} [name]
|
|
185
|
+
* @param {CookieOption | boolean} [opt]
|
|
186
186
|
* @returns {void}
|
|
187
187
|
*/
|
|
188
188
|
function clearCookie(
|
|
@@ -194,11 +194,11 @@ function clearCookie(
|
|
|
194
194
|
let expire = 'Fri, 31 Dec 1999 16:00:00 GMT';
|
|
195
195
|
if (typeof name === 'string') {
|
|
196
196
|
if (!name) { return; }
|
|
197
|
-
/** @type {
|
|
197
|
+
/** @type {CookieOption} */
|
|
198
198
|
const { domain, path, secure, httpOnly } = opt !== true && opt || {};
|
|
199
199
|
sentCookies.push({ name, value: 'delete', expire, domain, path, secure, httpOnly });
|
|
200
200
|
} else {
|
|
201
|
-
/** @type {
|
|
201
|
+
/** @type {CookieOption} */
|
|
202
202
|
const { domain, path, secure, httpOnly } = name || {};
|
|
203
203
|
sentCookies.length = 0;
|
|
204
204
|
if (opt) {
|
|
@@ -209,6 +209,9 @@ function clearCookie(
|
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
+
/** @import { Context, Cookie, CookieOption, FindHandler, Method, Options, Params, Service } from './types' */
|
|
213
|
+
|
|
214
|
+
|
|
212
215
|
const noBodyMethods = new Set(['GET', 'OPTIONS']);
|
|
213
216
|
/**
|
|
214
217
|
*
|
|
@@ -245,7 +248,7 @@ function setHeader(headers, name, value) {
|
|
|
245
248
|
*
|
|
246
249
|
* @param {Request} request
|
|
247
250
|
* @param {string | ((request: Request) => string)} [toMethod]
|
|
248
|
-
* @returns {
|
|
251
|
+
* @returns {Method}
|
|
249
252
|
*/
|
|
250
253
|
function getMethod(request, toMethod) {
|
|
251
254
|
let methodStr = '';
|
|
@@ -257,13 +260,13 @@ function getMethod(request, toMethod) {
|
|
|
257
260
|
if (!methodStr || typeof methodStr !== 'string') {
|
|
258
261
|
methodStr = request.method || 'GET';
|
|
259
262
|
}
|
|
260
|
-
return /** @type {
|
|
263
|
+
return /** @type {Method} */(methodStr.toUpperCase());
|
|
261
264
|
}
|
|
262
265
|
/**
|
|
263
266
|
*
|
|
264
267
|
* @param {Request} request
|
|
265
|
-
* @param {
|
|
266
|
-
* @param {
|
|
268
|
+
* @param {FindHandler} getHandler
|
|
269
|
+
* @param {Options} [options]
|
|
267
270
|
* @returns {Promise<Response | null>}
|
|
268
271
|
*/
|
|
269
272
|
function main(
|
|
@@ -273,7 +276,7 @@ function main(
|
|
|
273
276
|
/**
|
|
274
277
|
*
|
|
275
278
|
* @param {Request} request
|
|
276
|
-
* @param {
|
|
279
|
+
* @param {Context} [parent]
|
|
277
280
|
* @returns {Promise<Response | null>}
|
|
278
281
|
*/
|
|
279
282
|
function exec(request, parent) {
|
|
@@ -281,10 +284,10 @@ function main(
|
|
|
281
284
|
const url = new URL(request.url);
|
|
282
285
|
const { signal, headers } = request;
|
|
283
286
|
const aborted = signal2promise(signal);
|
|
284
|
-
/** @type {Map<
|
|
287
|
+
/** @type {Map<Service<any, any>, Function>} */
|
|
285
288
|
const services = new Map();
|
|
286
289
|
const cookies = getRequestCookies(headers.get('cookie') || '');
|
|
287
|
-
/** @type {
|
|
290
|
+
/** @type {Cookie[]} */
|
|
288
291
|
const sentCookies = [];
|
|
289
292
|
const responseHeaders = new Headers();
|
|
290
293
|
const root = parent?.root;
|
|
@@ -300,9 +303,9 @@ function main(
|
|
|
300
303
|
const donePromise = new Promise((a, b) => { resolve = a; reject = b; });
|
|
301
304
|
donePromise.catch(() => {});
|
|
302
305
|
|
|
303
|
-
/** @type {
|
|
306
|
+
/** @type {Params} */
|
|
304
307
|
let params = {};
|
|
305
|
-
/** @type {
|
|
308
|
+
/** @type {Context} */
|
|
306
309
|
const context = {
|
|
307
310
|
environment,
|
|
308
311
|
parent,
|
|
@@ -366,8 +369,8 @@ function main(
|
|
|
366
369
|
},
|
|
367
370
|
/**
|
|
368
371
|
*
|
|
369
|
-
* @param {string |
|
|
370
|
-
* @param {
|
|
372
|
+
* @param {string | CookieOption} [name]
|
|
373
|
+
* @param {CookieOption | boolean} [opt]
|
|
371
374
|
* @returns {void}
|
|
372
375
|
*/
|
|
373
376
|
clearCookie(name, opt) {
|
|
@@ -404,69 +407,72 @@ function main(
|
|
|
404
407
|
return exec(request);
|
|
405
408
|
}
|
|
406
409
|
|
|
410
|
+
/** @import { FindHandler, Options } from './main/types' */
|
|
411
|
+
|
|
407
412
|
/**
|
|
408
413
|
*
|
|
409
|
-
* @param {
|
|
410
|
-
* @param {
|
|
414
|
+
* @param {FindHandler} getHandler
|
|
415
|
+
* @param {Options} options
|
|
411
416
|
* @returns {(request: Request) => Promise<Response | null>}
|
|
412
417
|
*/
|
|
413
418
|
function make(getHandler, options) {
|
|
414
419
|
return r => main(r, getHandler, options);
|
|
415
420
|
}
|
|
416
421
|
|
|
422
|
+
/** @import { Context, Handler } from './main/types' */
|
|
417
423
|
/**
|
|
418
424
|
*
|
|
419
|
-
* @param {
|
|
420
|
-
* @param {
|
|
425
|
+
* @param {Context} context
|
|
426
|
+
* @param {Handler[]} handlers
|
|
421
427
|
* @returns {Promise<string | boolean | object | undefined>}
|
|
422
428
|
*/
|
|
423
429
|
async function runHandles(context, handlers) {
|
|
424
430
|
for (const handle of handlers) {
|
|
425
431
|
const result = await handle(context);
|
|
426
|
-
if (
|
|
427
|
-
if (!result) { continue; }
|
|
432
|
+
if (result === undefined) { continue; }
|
|
428
433
|
return result;
|
|
429
434
|
}
|
|
430
435
|
}
|
|
431
436
|
|
|
432
437
|
/**
|
|
433
438
|
*
|
|
434
|
-
* @param {...(
|
|
435
|
-
* @returns {
|
|
439
|
+
* @param {...(Handler | Handler[])} handlers
|
|
440
|
+
* @returns {Handler}
|
|
436
441
|
*/
|
|
437
442
|
function merge(...handlers) {
|
|
438
443
|
return ctx => runHandles(ctx, handlers.flat());
|
|
439
444
|
}
|
|
440
445
|
|
|
446
|
+
/** @import { Context, Service } from './main/types' */
|
|
441
447
|
/**
|
|
442
448
|
*
|
|
443
449
|
* @template T
|
|
444
450
|
* @template {any[]} P
|
|
445
451
|
* @overload
|
|
446
|
-
* @param {(ctx:
|
|
447
|
-
* @param {((ctx:
|
|
448
|
-
* @param {
|
|
449
|
-
* @returns {
|
|
452
|
+
* @param {(ctx: Context, ...p: P) => T} exec
|
|
453
|
+
* @param {((ctx: Context, error?: unknown) => PromiseLike<void> | void)?} [destroy]
|
|
454
|
+
* @param {Service.Options?} [options]
|
|
455
|
+
* @returns {Service<T, P>}
|
|
450
456
|
*/
|
|
451
457
|
/**
|
|
452
458
|
*
|
|
453
459
|
* @template T
|
|
454
460
|
* @template {any[]} P
|
|
455
461
|
* @overload
|
|
456
|
-
* @param {(ctx:
|
|
457
|
-
* @param {
|
|
458
|
-
* @returns {
|
|
462
|
+
* @param {(ctx: Context, ...p: P) => T} exec
|
|
463
|
+
* @param {Service.Options?} [options]
|
|
464
|
+
* @returns {Service<T, P>}
|
|
459
465
|
*/
|
|
460
466
|
/**
|
|
461
467
|
* @template T
|
|
462
468
|
* @template {any[]} P
|
|
463
|
-
* @param {(ctx:
|
|
464
|
-
* @param {((ctx:
|
|
465
|
-
* @param {
|
|
466
|
-
* @returns {
|
|
469
|
+
* @param {(ctx: Context, ...p: P) => T} exec
|
|
470
|
+
* @param {((ctx: Context, error?: unknown) => PromiseLike<void> | void) | Service.Options | null} [destroy]
|
|
471
|
+
* @param {Service.Options?} [options]
|
|
472
|
+
* @returns {Service<T, P>}
|
|
467
473
|
*/
|
|
468
474
|
function service(exec, destroy, options) {
|
|
469
|
-
/** @type {
|
|
475
|
+
/** @type {Service<T, P>} */
|
|
470
476
|
const service = function (ctx) {
|
|
471
477
|
if (typeof destroy === 'function') {
|
|
472
478
|
ctx.done(() => destroy(ctx), error => destroy(ctx, error));
|
|
@@ -485,43 +491,44 @@ function service(exec, destroy, options) {
|
|
|
485
491
|
return service;
|
|
486
492
|
}
|
|
487
493
|
|
|
494
|
+
/** @import { Context, Service, StateService } from './main/types' */
|
|
488
495
|
/**
|
|
489
496
|
*
|
|
490
497
|
* @template T
|
|
491
498
|
* @overload
|
|
492
|
-
* @param {(ctx:
|
|
493
|
-
* @param {
|
|
494
|
-
* @returns {
|
|
499
|
+
* @param {(ctx: Context) => T} init
|
|
500
|
+
* @param {Service.Options} [options]
|
|
501
|
+
* @returns {StateService<T>}
|
|
495
502
|
*/
|
|
496
503
|
/**
|
|
497
504
|
*
|
|
498
505
|
* @template T
|
|
499
506
|
* @overload
|
|
500
|
-
* @param {(ctx:
|
|
501
|
-
* @param {((state: T | undefined, ctx:
|
|
502
|
-
* @param {
|
|
503
|
-
* @returns {
|
|
507
|
+
* @param {(ctx: Context) => T} init
|
|
508
|
+
* @param {((state: T | undefined, ctx: Context, error?: unknown) => PromiseLike<void> | void)?} [destroy]
|
|
509
|
+
* @param {Service.Options?} [options]
|
|
510
|
+
* @returns {StateService<T>}
|
|
504
511
|
*/
|
|
505
512
|
/**
|
|
506
513
|
*
|
|
507
514
|
* @template T
|
|
508
515
|
* @overload
|
|
509
|
-
* @param {(ctx:
|
|
510
|
-
* @param {((state: T | undefined, ctx:
|
|
511
|
-
* @param {((state: T, ctx:
|
|
512
|
-
* @param {
|
|
513
|
-
* @returns {
|
|
516
|
+
* @param {(ctx: Context) => T} init
|
|
517
|
+
* @param {((state: T | undefined, ctx: Context, error?: unknown) => PromiseLike<void> | void)?} [destroy]
|
|
518
|
+
* @param {((state: T, ctx: Context) => any)?} [exec]
|
|
519
|
+
* @param {Service.Options?} [options]
|
|
520
|
+
* @returns {StateService<T>}
|
|
514
521
|
*/
|
|
515
522
|
/**
|
|
516
523
|
* @template T
|
|
517
|
-
* @param {(ctx:
|
|
518
|
-
* @param {((state: T | undefined, ctx:
|
|
519
|
-
* @param {((state: T, ctx:
|
|
520
|
-
* @param {
|
|
521
|
-
* @returns {
|
|
524
|
+
* @param {(ctx: Context) => T} init
|
|
525
|
+
* @param {((state: T | undefined, ctx: Context, error?: unknown) => PromiseLike<void> | void) | Service.Options | null} [destroy]
|
|
526
|
+
* @param {((state: T, ctx: Context) => any) | Service.Options | null} [exec]
|
|
527
|
+
* @param {Service.Options?} [options]
|
|
528
|
+
* @returns {StateService<T>}
|
|
522
529
|
*/
|
|
523
530
|
function stateService(init, destroy, exec, options) {
|
|
524
|
-
/** @type {
|
|
531
|
+
/** @type {StateService<T>} */
|
|
525
532
|
const service = function (ctx) {
|
|
526
533
|
const state = init(ctx) || /** @type {T} */({});
|
|
527
534
|
if (typeof destroy === 'function') {
|
|
@@ -545,39 +552,40 @@ function stateService(init, destroy, exec, options) {
|
|
|
545
552
|
return service;
|
|
546
553
|
}
|
|
547
554
|
|
|
555
|
+
/** @import { Context, Service, StoreService } from './main/types' */
|
|
548
556
|
/**
|
|
549
557
|
*
|
|
550
558
|
* @template T
|
|
551
559
|
* @overload
|
|
552
|
-
* @param {
|
|
553
|
-
* @returns {
|
|
560
|
+
* @param {Service.Options?} [options]
|
|
561
|
+
* @returns {StoreService<T>}
|
|
554
562
|
*/
|
|
555
563
|
/**
|
|
556
564
|
*
|
|
557
565
|
* @template T
|
|
558
566
|
* @overload
|
|
559
|
-
* @param {((state: T | undefined, ctx:
|
|
560
|
-
* @param {
|
|
561
|
-
* @returns {
|
|
567
|
+
* @param {((state: T | undefined, ctx: Context, error?: unknown) => PromiseLike<void> | void)?} [destroy]
|
|
568
|
+
* @param {Service.Options?} [options]
|
|
569
|
+
* @returns {StoreService<T>}
|
|
562
570
|
*/
|
|
563
571
|
/**
|
|
564
572
|
*
|
|
565
573
|
* @template T
|
|
566
574
|
* @overload
|
|
567
|
-
* @param {((state: T | undefined, ctx:
|
|
568
|
-
* @param {((state: T | undefined, ctx:
|
|
569
|
-
* @param {
|
|
570
|
-
* @returns {
|
|
575
|
+
* @param {((state: T | undefined, ctx: Context, error?: unknown) => PromiseLike<void> | void)?} [destroy]
|
|
576
|
+
* @param {((state: T | undefined, ctx: Context) => any)?} [exec]
|
|
577
|
+
* @param {Service.Options?} [options]
|
|
578
|
+
* @returns {StoreService<T>}
|
|
571
579
|
*/
|
|
572
580
|
/**
|
|
573
581
|
* @template T
|
|
574
|
-
* @param {((state: T | undefined, ctx:
|
|
575
|
-
* @param {((state: T | undefined, ctx:
|
|
576
|
-
* @param {
|
|
577
|
-
* @returns {
|
|
582
|
+
* @param {((state: T | undefined, ctx: Context, error?: unknown) => PromiseLike<void> | void) | Service.Options | null} [destroy]
|
|
583
|
+
* @param {((state: T | undefined, ctx: Context) => any) | Service.Options | null} [exec]
|
|
584
|
+
* @param {Service.Options?} [options]
|
|
585
|
+
* @returns {StoreService<T>}
|
|
578
586
|
*/
|
|
579
587
|
function storeService(destroy, exec, options) {
|
|
580
|
-
/** @type {
|
|
588
|
+
/** @type {StoreService<T>} */
|
|
581
589
|
const service = function (ctx) {
|
|
582
590
|
/** @type {T | undefined} */
|
|
583
591
|
let state;
|
|
@@ -614,16 +622,18 @@ function storeService(destroy, exec, options) {
|
|
|
614
622
|
return service;
|
|
615
623
|
}
|
|
616
624
|
|
|
625
|
+
/** @import { Handler } from './main/types' */
|
|
626
|
+
/** @import { Onionskin } from './onionskin.mjs' */
|
|
617
627
|
/**
|
|
618
628
|
* @callback Packer
|
|
619
|
-
* @param {
|
|
620
|
-
* @returns {
|
|
629
|
+
* @param {Handler} handler
|
|
630
|
+
* @returns {Handler}
|
|
621
631
|
*/
|
|
622
632
|
/** @type {Packer} */
|
|
623
633
|
const noop$1 = h => h;
|
|
624
634
|
/**
|
|
625
635
|
*
|
|
626
|
-
* @param {
|
|
636
|
+
* @param {Onionskin} onionskin
|
|
627
637
|
* @param {Packer} [packer]
|
|
628
638
|
* @returns {Packer}
|
|
629
639
|
*/
|
|
@@ -634,30 +644,33 @@ function packer(onionskin, packer = noop$1) {
|
|
|
634
644
|
};
|
|
635
645
|
}
|
|
636
646
|
|
|
647
|
+
/** @import { Context, FindHandler, Handler, Method, Params } from './main/types' */
|
|
648
|
+
/** @import { Onionskin } from './onionskin.mjs' */
|
|
649
|
+
|
|
637
650
|
/**
|
|
638
651
|
* @callback Guard
|
|
639
|
-
* @param {
|
|
640
|
-
* @returns {PromiseLike<boolean |
|
|
652
|
+
* @param {Context} ctx
|
|
653
|
+
* @returns {PromiseLike<boolean | Handler | void> | boolean | Handler | void}
|
|
641
654
|
*/
|
|
642
655
|
/**
|
|
643
|
-
* @typedef {[
|
|
656
|
+
* @typedef {[Handler | Router, Record<string | symbol, any>, string[]]} FindItem
|
|
644
657
|
*/
|
|
645
658
|
/**
|
|
646
659
|
* @callback Finder
|
|
647
660
|
* @this {Router}
|
|
648
|
-
* @param {
|
|
661
|
+
* @param {Method} method
|
|
649
662
|
* @param {string[]} path
|
|
650
|
-
* @param {
|
|
663
|
+
* @param {Context} ctx
|
|
651
664
|
* @returns {AsyncIterable<FindItem> | Iterable<FindItem>}
|
|
652
665
|
*/
|
|
653
666
|
|
|
654
667
|
/**
|
|
655
668
|
*
|
|
656
669
|
* @param {Set<Guard>} guards
|
|
657
|
-
* @param {
|
|
670
|
+
* @param {Context} ctx
|
|
658
671
|
* @param {(v: any) => void} setParams
|
|
659
672
|
* @param {object} params
|
|
660
|
-
* @returns {Promise<boolean |
|
|
673
|
+
* @returns {Promise<boolean | Handler>}
|
|
661
674
|
*/
|
|
662
675
|
async function execGuard(guards, ctx, setParams, params) {
|
|
663
676
|
if (!guards.size) { return true; }
|
|
@@ -676,12 +689,12 @@ async function execGuard(guards, ctx, setParams, params) {
|
|
|
676
689
|
|
|
677
690
|
/**
|
|
678
691
|
*
|
|
679
|
-
* @param {Router |
|
|
692
|
+
* @param {Router | Handler} route
|
|
680
693
|
* @param {string[]} path
|
|
681
|
-
* @param {
|
|
682
|
-
* @param {(v:
|
|
683
|
-
* @param {
|
|
684
|
-
* @returns {Promise<
|
|
694
|
+
* @param {Context} ctx
|
|
695
|
+
* @param {(v: Params) => void} setParams
|
|
696
|
+
* @param {Params} params
|
|
697
|
+
* @returns {Promise<Handler | null>}
|
|
685
698
|
*/
|
|
686
699
|
async function find(route, path, ctx, setParams, params) {
|
|
687
700
|
if (!(route instanceof Router)) {
|
|
@@ -720,16 +733,16 @@ class Router {
|
|
|
720
733
|
disabled = false;
|
|
721
734
|
/**
|
|
722
735
|
* @abstract
|
|
723
|
-
* @param {
|
|
736
|
+
* @param {Method} method
|
|
724
737
|
* @param {string[]} path
|
|
725
|
-
* @param {
|
|
738
|
+
* @param {Context} ctx
|
|
726
739
|
* @returns {AsyncIterable<FindItem> | Iterable<FindItem>}
|
|
727
740
|
*/
|
|
728
741
|
find(method, path, ctx) { return []; }
|
|
729
742
|
/**
|
|
730
743
|
*
|
|
731
744
|
* @param {Router[]} routers
|
|
732
|
-
* @returns {
|
|
745
|
+
* @returns {FindHandler}
|
|
733
746
|
*/
|
|
734
747
|
static make(routers) {
|
|
735
748
|
return async (ctx, setParams) => {
|
|
@@ -757,19 +770,21 @@ class Router {
|
|
|
757
770
|
guards = new Set();
|
|
758
771
|
/**
|
|
759
772
|
*
|
|
760
|
-
* @param {
|
|
761
|
-
* @returns {
|
|
773
|
+
* @param {Handler} h
|
|
774
|
+
* @returns {Handler}
|
|
762
775
|
*/
|
|
763
776
|
__onionskin = (h) => h;
|
|
764
|
-
/** @param {
|
|
777
|
+
/** @param {Onionskin} os */
|
|
765
778
|
onionskin(os) { this.__onionskin = packer(os, this.__onionskin); }
|
|
766
779
|
}
|
|
767
780
|
|
|
781
|
+
/** @import { Match } from './index.mjs' */
|
|
782
|
+
/** @import { Params } from '../main/types.js' */
|
|
768
783
|
/**
|
|
769
784
|
* @typedef {object} Pattern
|
|
770
|
-
* @property {string} name
|
|
771
|
-
* @property {boolean} optional
|
|
772
|
-
* @property {boolean} many
|
|
785
|
+
* @property {string | symbol} name
|
|
786
|
+
* @property {boolean} [optional]
|
|
787
|
+
* @property {boolean} [many]
|
|
773
788
|
* @property {RegExp} pattern
|
|
774
789
|
*/
|
|
775
790
|
|
|
@@ -840,7 +855,7 @@ function parse(p) {
|
|
|
840
855
|
* @returns {[Record<string, string | string[]>, string[]] | undefined}
|
|
841
856
|
*/
|
|
842
857
|
function exec(match, path, end) {
|
|
843
|
-
/** @type {
|
|
858
|
+
/** @type {Params} */
|
|
844
859
|
const params = {};
|
|
845
860
|
for (let i = 0; i < match.length; i++) {
|
|
846
861
|
const m = match[i];
|
|
@@ -863,38 +878,101 @@ function exec(match, path, end) {
|
|
|
863
878
|
return [params, []];
|
|
864
879
|
|
|
865
880
|
}
|
|
881
|
+
/**
|
|
882
|
+
*
|
|
883
|
+
* @param {string[]} paths
|
|
884
|
+
* @param {*} values
|
|
885
|
+
* @returns {Iterable<[string[], any[]]>}
|
|
886
|
+
*/
|
|
887
|
+
function* split([...paths], [...values]) {
|
|
888
|
+
let els = (paths.shift() || '').split('/');
|
|
889
|
+
let list = [els.pop() || ''];
|
|
890
|
+
for (const f of els) {
|
|
891
|
+
yield [[f], []];
|
|
892
|
+
}
|
|
893
|
+
for (const path of paths) {
|
|
894
|
+
const els = path.split('/');
|
|
895
|
+
if (els.length <= 1) {
|
|
896
|
+
list.push(path);
|
|
897
|
+
continue;
|
|
898
|
+
}
|
|
899
|
+
const pathValue = values.splice(0, list.length);
|
|
900
|
+
list.push(els.shift() || '');
|
|
901
|
+
yield [list, pathValue];
|
|
902
|
+
list = [els.pop() || ''];
|
|
903
|
+
for (const f of els) {
|
|
904
|
+
yield [[f], []];
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
yield [list, values];
|
|
908
|
+
}
|
|
866
909
|
/**
|
|
867
910
|
*
|
|
868
|
-
* @param {string} path
|
|
911
|
+
* @param {string | [string[], any[]]} path
|
|
869
912
|
* @param {boolean} end
|
|
870
|
-
* @returns {
|
|
913
|
+
* @returns {Match | undefined}
|
|
871
914
|
*/
|
|
872
915
|
function toMatch(path, end) {
|
|
873
916
|
/** @type {(Pattern | string)[]} */
|
|
874
917
|
const list = [];
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
918
|
+
if (typeof path === 'string') {
|
|
919
|
+
for (const p of path.split('/')) {
|
|
920
|
+
if (!p || /^\.+$/.test(p)) { continue; }
|
|
921
|
+
list.push(parse(p));
|
|
922
|
+
}
|
|
923
|
+
} else {
|
|
924
|
+
for (const [paths, values] of split(...path)) {
|
|
925
|
+
if (paths.length === 2 && !paths[0]) {
|
|
926
|
+
const modifier = paths[1];
|
|
927
|
+
if (['', '?', '+', '*'].includes(modifier)) {
|
|
928
|
+
const value = values[0];
|
|
929
|
+
if (typeof value === 'symbol') {
|
|
930
|
+
list.push({
|
|
931
|
+
name: value, pattern: /^.*$/,
|
|
932
|
+
optional: modifier === '?' || modifier === '*',
|
|
933
|
+
many: modifier === '+' || modifier === '*',
|
|
934
|
+
});
|
|
935
|
+
continue;
|
|
936
|
+
} else if (value && typeof value === 'object') {
|
|
937
|
+
const {name, pattern} = value;
|
|
938
|
+
if (typeof name === 'symbol') {
|
|
939
|
+
list.push({
|
|
940
|
+
name, pattern: pattern instanceof RegExp ? pattern : /^.*$/,
|
|
941
|
+
optional: modifier === '?' || modifier === '*',
|
|
942
|
+
many: modifier === '+' || modifier === '*',
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
const last = paths.pop() || '';
|
|
949
|
+
const strings = paths.map((v, i) => [v, values[i]]).flat();
|
|
950
|
+
strings.push(last);
|
|
951
|
+
const p = strings.join('');
|
|
952
|
+
if (!p || /^\.+$/.test(p)) { continue; }
|
|
953
|
+
list.push(parse(p));
|
|
954
|
+
continue;
|
|
955
|
+
}
|
|
956
|
+
|
|
878
957
|
}
|
|
879
958
|
if (!list.length) { return; }
|
|
880
959
|
return path => exec(list, path, end);
|
|
881
960
|
}
|
|
882
961
|
|
|
962
|
+
/** @import { Handler, Method } from '../main/types' */
|
|
963
|
+
/** @import { Binder, Match, Route, RouterRoute } from './index.mjs' */
|
|
964
|
+
|
|
883
965
|
/**
|
|
884
966
|
*
|
|
885
|
-
* @param {(
|
|
886
|
-
* @param {
|
|
887
|
-
* @param {
|
|
888
|
-
* @param {
|
|
967
|
+
* @param {(Route | RouterRoute)[]} routes
|
|
968
|
+
* @param {Set<Method>} methods
|
|
969
|
+
* @param {Match | undefined} match
|
|
970
|
+
* @param {Handler[]} handlers
|
|
889
971
|
* @returns {() => void}
|
|
890
972
|
*/
|
|
891
|
-
function bind(routes, methods,
|
|
892
|
-
/** @type {
|
|
893
|
-
const route = {
|
|
894
|
-
match: toMatch(path || '', true),
|
|
895
|
-
methods: new Set(methods),
|
|
896
|
-
handler,
|
|
897
|
-
};
|
|
973
|
+
function bind(routes, methods, match, handlers) {
|
|
974
|
+
/** @type {Route} */
|
|
975
|
+
const route = { match, methods, handler: ctx => runHandles(ctx, handlers) };
|
|
898
976
|
routes.push(route);
|
|
899
977
|
let removed = false;
|
|
900
978
|
return () => {
|
|
@@ -905,43 +983,49 @@ function bind(routes, methods, path, handler) {
|
|
|
905
983
|
routes.splice(index, 1);
|
|
906
984
|
};
|
|
907
985
|
}
|
|
908
|
-
/** @type {(v: any) => v is
|
|
986
|
+
/** @type {(v: any) => v is Handler} */
|
|
909
987
|
const findHandler = v => typeof v === 'function';
|
|
910
988
|
/**
|
|
911
989
|
*
|
|
912
|
-
* @param {(
|
|
913
|
-
* @param {
|
|
990
|
+
* @param {(Route | RouterRoute)[]} routes
|
|
991
|
+
* @param {Iterable<Method>} methods
|
|
914
992
|
* @param {any[]} p
|
|
915
|
-
* @returns {
|
|
993
|
+
* @returns {Binder | (() => void)}
|
|
916
994
|
*/
|
|
917
995
|
function verb(routes, methods, p) {
|
|
996
|
+
const methodSet = new Set(methods);
|
|
918
997
|
if (!p.length) {
|
|
919
|
-
|
|
998
|
+
const match = undefined;
|
|
999
|
+
/** @type {Binder} */
|
|
1000
|
+
return (...handlers) => bind(routes, methodSet, match, handlers);
|
|
920
1001
|
}
|
|
921
|
-
const [
|
|
922
|
-
if (
|
|
923
|
-
const
|
|
924
|
-
|
|
1002
|
+
const [path] = p;
|
|
1003
|
+
if (path && typeof path === 'object') {
|
|
1004
|
+
const match = toMatch([path, p.slice(1)], true);
|
|
1005
|
+
/** @type {Binder} */
|
|
1006
|
+
return (...handlers) => bind(routes, methodSet, match, handlers);
|
|
925
1007
|
}
|
|
926
|
-
const
|
|
927
|
-
const
|
|
928
|
-
if (!
|
|
929
|
-
|
|
1008
|
+
const match = toMatch(typeof path === 'string' ? path : '', true);
|
|
1009
|
+
const handlers = p.filter(findHandler);
|
|
1010
|
+
if (!handlers.length) {
|
|
1011
|
+
/** @type {Binder} */
|
|
1012
|
+
return (...handlers) => bind(routes, methodSet, match, handlers);
|
|
930
1013
|
}
|
|
931
|
-
return bind(routes,
|
|
1014
|
+
return bind(routes, methodSet, match, handlers);
|
|
932
1015
|
}
|
|
933
1016
|
|
|
1017
|
+
/** @import { Method } from '../main/types' */
|
|
934
1018
|
const methods = new Set(['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS']);
|
|
935
1019
|
/**
|
|
936
1020
|
*
|
|
937
1021
|
* @param {any} v
|
|
938
|
-
* @returns {v is
|
|
1022
|
+
* @returns {v is Method}
|
|
939
1023
|
*/
|
|
940
1024
|
function isMethod(v) { return methods.has(v); }
|
|
941
1025
|
/**
|
|
942
1026
|
*
|
|
943
|
-
* @param {
|
|
944
|
-
* @returns {
|
|
1027
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} [methods]
|
|
1028
|
+
* @returns {Method[]}
|
|
945
1029
|
*/
|
|
946
1030
|
function getMethods(methods) {
|
|
947
1031
|
if (!methods) {
|
|
@@ -955,25 +1039,24 @@ function getMethods(methods) {
|
|
|
955
1039
|
.filter(isMethod);
|
|
956
1040
|
}
|
|
957
1041
|
|
|
1042
|
+
/** @import { Context, Handler, Method, Params } from '../main/types' */
|
|
1043
|
+
/** @import { Finder, FindItem } from '../Router.mjs' */
|
|
1044
|
+
|
|
958
1045
|
/**
|
|
959
1046
|
* @callback Match
|
|
960
1047
|
* @param {string[]} paths
|
|
961
|
-
* @returns {[
|
|
1048
|
+
* @returns {[Params, string[]] | undefined}
|
|
962
1049
|
*/
|
|
963
1050
|
|
|
964
|
-
/**
|
|
965
|
-
* @callback Binder
|
|
966
|
-
* @param {import('../main/types').Handler} handler
|
|
967
|
-
* @returns {() => void}
|
|
968
|
-
*/
|
|
1051
|
+
/** @typedef {(handler: Handler, ...handlers: Handler[]) => () => void} Binder */
|
|
969
1052
|
|
|
970
1053
|
/**
|
|
971
1054
|
* @typedef {object} Route
|
|
972
1055
|
* @property {Match} [match] 路径匹配
|
|
973
1056
|
* @property {null} [router]
|
|
974
1057
|
* @property {string} [plugin] 所属插件
|
|
975
|
-
* @property {
|
|
976
|
-
* @property {Set<
|
|
1058
|
+
* @property {Handler} handler 处理函数
|
|
1059
|
+
* @property {Set<Method>} methods 方法列表
|
|
977
1060
|
*/
|
|
978
1061
|
|
|
979
1062
|
/**
|
|
@@ -984,16 +1067,16 @@ function getMethods(methods) {
|
|
|
984
1067
|
|
|
985
1068
|
|
|
986
1069
|
/**
|
|
987
|
-
* @template {Router |
|
|
1070
|
+
* @template {Router | Finder} [T=ApiRouter]
|
|
988
1071
|
* @callback RouteBinder
|
|
989
1072
|
* @param {T} [router] 要注册的子路由或子路由的 Finder
|
|
990
|
-
* @returns {T extends
|
|
1073
|
+
* @returns {T extends Finder ? Router : T}
|
|
991
1074
|
*/
|
|
992
1075
|
/**
|
|
993
1076
|
*
|
|
994
1077
|
* @param {(Route | RouterRoute)[]} routes
|
|
995
|
-
* @param {string} path
|
|
996
|
-
* @param {Router |
|
|
1078
|
+
* @param {string | [string[], any[]]} path
|
|
1079
|
+
* @param {Router | Finder} [r]
|
|
997
1080
|
* @returns {Router}
|
|
998
1081
|
*/
|
|
999
1082
|
function bindRouter(routes, path, r) {
|
|
@@ -1008,18 +1091,18 @@ class ApiRouter extends Router {
|
|
|
1008
1091
|
#routes = [];
|
|
1009
1092
|
/**
|
|
1010
1093
|
* 添加子路由
|
|
1011
|
-
* @template {Router |
|
|
1094
|
+
* @template {Router | Finder} [T=ApiRouter]
|
|
1012
1095
|
* @overload
|
|
1013
1096
|
* @param {T} [router] 要注册的子路由或子路由的 Finder
|
|
1014
|
-
* @returns {T extends
|
|
1097
|
+
* @returns {T extends Finder ? Router : T}
|
|
1015
1098
|
*/
|
|
1016
1099
|
/**
|
|
1017
1100
|
* 添加子路由
|
|
1018
|
-
* @template {Router |
|
|
1101
|
+
* @template {Router | Finder} [T=ApiRouter]
|
|
1019
1102
|
* @overload
|
|
1020
1103
|
* @param {string} path 要注册的路径
|
|
1021
1104
|
* @param {T} [router] 要注册的子路由或子路由的 Finder
|
|
1022
|
-
* @returns {T extends
|
|
1105
|
+
* @returns {T extends Finder ? Router : T}
|
|
1023
1106
|
*/
|
|
1024
1107
|
/**
|
|
1025
1108
|
* 添加子路由
|
|
@@ -1036,12 +1119,11 @@ class ApiRouter extends Router {
|
|
|
1036
1119
|
route(...p) {
|
|
1037
1120
|
const [a] = p;
|
|
1038
1121
|
if (a && typeof a === 'object' && !(a instanceof Router)) {
|
|
1039
|
-
const path = String.raw(a, ...p.slice(1));
|
|
1040
1122
|
/**
|
|
1041
|
-
* @param {
|
|
1123
|
+
* @param { Finder | Router} [r];
|
|
1042
1124
|
* @returns {any}
|
|
1043
1125
|
*/
|
|
1044
|
-
return r => bindRouter(this.#routes,
|
|
1126
|
+
return r => bindRouter(this.#routes, [a, p.slice(1)], r);
|
|
1045
1127
|
}
|
|
1046
1128
|
const path = typeof a === 'string' ? a : '';
|
|
1047
1129
|
const r = typeof a === 'string' ? p[1] : a;
|
|
@@ -1049,10 +1131,10 @@ class ApiRouter extends Router {
|
|
|
1049
1131
|
}
|
|
1050
1132
|
/**
|
|
1051
1133
|
*
|
|
1052
|
-
* @param {
|
|
1134
|
+
* @param {Method} method
|
|
1053
1135
|
* @param {string[]} path
|
|
1054
|
-
* @param {
|
|
1055
|
-
* @returns {Iterable<
|
|
1136
|
+
* @param {Context} ctx
|
|
1137
|
+
* @returns {Iterable<FindItem>}
|
|
1056
1138
|
*/
|
|
1057
1139
|
*find(method, path, ctx) {
|
|
1058
1140
|
for (const route of Array.from(this.#routes)) {
|
|
@@ -1073,29 +1155,29 @@ class ApiRouter extends Router {
|
|
|
1073
1155
|
/**
|
|
1074
1156
|
* 注册处理函数
|
|
1075
1157
|
* @overload
|
|
1076
|
-
* @param {
|
|
1077
|
-
* @param {
|
|
1158
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} method 要注册的方法
|
|
1159
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1078
1160
|
* @returns {() => void}
|
|
1079
1161
|
*/
|
|
1080
1162
|
/**
|
|
1081
1163
|
* 注册处理函数
|
|
1082
1164
|
* @overload
|
|
1083
|
-
* @param {
|
|
1165
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} method 要注册的方法
|
|
1084
1166
|
* @param {string} path 要注册的路径
|
|
1085
|
-
* @param {
|
|
1167
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1086
1168
|
* @returns {() => void}
|
|
1087
1169
|
*/
|
|
1088
1170
|
/**
|
|
1089
1171
|
* 注册处理函数
|
|
1090
1172
|
* @overload
|
|
1091
|
-
* @param {
|
|
1173
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} method 要注册的方法
|
|
1092
1174
|
* @param {string} path 要注册的路径
|
|
1093
1175
|
* @returns {Binder}
|
|
1094
1176
|
*/
|
|
1095
1177
|
/**
|
|
1096
|
-
* @param {
|
|
1097
|
-
* @param {string|
|
|
1098
|
-
* @param {
|
|
1178
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} methods
|
|
1179
|
+
* @param {string| Handler} [path]
|
|
1180
|
+
* @param {Handler} [handler]
|
|
1099
1181
|
* @returns {Binder | (() => void)}
|
|
1100
1182
|
*/
|
|
1101
1183
|
verb(methods, path, handler) {
|
|
@@ -1106,14 +1188,14 @@ class ApiRouter extends Router {
|
|
|
1106
1188
|
/**
|
|
1107
1189
|
* 注册 HTTP GET/POST/PUT/DELETE 处理函数
|
|
1108
1190
|
* @overload
|
|
1109
|
-
* @param {
|
|
1191
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1110
1192
|
* @returns {() => void}
|
|
1111
1193
|
*/
|
|
1112
1194
|
/**
|
|
1113
1195
|
* 注册处理函数
|
|
1114
1196
|
* @overload
|
|
1115
1197
|
* @param {string} path 要注册的路径
|
|
1116
|
-
* @param {
|
|
1198
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1117
1199
|
* @returns {() => void}
|
|
1118
1200
|
*/
|
|
1119
1201
|
/**
|
|
@@ -1139,14 +1221,14 @@ class ApiRouter extends Router {
|
|
|
1139
1221
|
/**
|
|
1140
1222
|
* 注册 HTTP GET 处理函数
|
|
1141
1223
|
* @overload
|
|
1142
|
-
* @param {
|
|
1224
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1143
1225
|
* @returns {() => void}
|
|
1144
1226
|
*/
|
|
1145
1227
|
/**
|
|
1146
1228
|
* 注册 HTTP GET 处理函数
|
|
1147
1229
|
* @overload
|
|
1148
1230
|
* @param {string} path 要注册的路径
|
|
1149
|
-
* @param {
|
|
1231
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1150
1232
|
* @returns {() => void}
|
|
1151
1233
|
*/
|
|
1152
1234
|
/**
|
|
@@ -1170,14 +1252,14 @@ class ApiRouter extends Router {
|
|
|
1170
1252
|
/**
|
|
1171
1253
|
* 注册 HTTP POST 处理函数
|
|
1172
1254
|
* @overload
|
|
1173
|
-
* @param {
|
|
1255
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1174
1256
|
* @returns {() => void}
|
|
1175
1257
|
*/
|
|
1176
1258
|
/**
|
|
1177
1259
|
* 注册 HTTP POST 处理函数
|
|
1178
1260
|
* @overload
|
|
1179
1261
|
* @param {string} path 要注册的路径
|
|
1180
|
-
* @param {
|
|
1262
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1181
1263
|
* @returns {() => void}
|
|
1182
1264
|
*/
|
|
1183
1265
|
/**
|
|
@@ -1201,14 +1283,14 @@ class ApiRouter extends Router {
|
|
|
1201
1283
|
/**
|
|
1202
1284
|
* 注册 HTTP PUT 处理函数
|
|
1203
1285
|
* @overload
|
|
1204
|
-
* @param {
|
|
1286
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1205
1287
|
* @returns {() => void}
|
|
1206
1288
|
*/
|
|
1207
1289
|
/**
|
|
1208
1290
|
* 注册 HTTP PUT 处理函数
|
|
1209
1291
|
* @overload
|
|
1210
1292
|
* @param {string} path 要注册的路径
|
|
1211
|
-
* @param {
|
|
1293
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1212
1294
|
* @returns {() => void}
|
|
1213
1295
|
*/
|
|
1214
1296
|
/**
|
|
@@ -1232,14 +1314,14 @@ class ApiRouter extends Router {
|
|
|
1232
1314
|
/**
|
|
1233
1315
|
* 注册 HTTP DELETE 处理函数
|
|
1234
1316
|
* @overload
|
|
1235
|
-
* @param {
|
|
1317
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1236
1318
|
* @returns {() => void}
|
|
1237
1319
|
*/
|
|
1238
1320
|
/**
|
|
1239
1321
|
* 注册 HTTP DELETE 处理函数
|
|
1240
1322
|
* @overload
|
|
1241
1323
|
* @param {string} path 要注册的路径
|
|
1242
|
-
* @param {
|
|
1324
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1243
1325
|
* @returns {() => void}
|
|
1244
1326
|
*/
|
|
1245
1327
|
/**
|
|
@@ -1263,14 +1345,14 @@ class ApiRouter extends Router {
|
|
|
1263
1345
|
/**
|
|
1264
1346
|
* 注册 HTTP HEAD 处理函数
|
|
1265
1347
|
* @overload
|
|
1266
|
-
* @param {
|
|
1348
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1267
1349
|
* @returns {() => void}
|
|
1268
1350
|
*/
|
|
1269
1351
|
/**
|
|
1270
1352
|
* 注册 HTTP HEAD 处理函数
|
|
1271
1353
|
* @overload
|
|
1272
1354
|
* @param {string} path 要注册的路径
|
|
1273
|
-
* @param {
|
|
1355
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1274
1356
|
* @returns {() => void}
|
|
1275
1357
|
*/
|
|
1276
1358
|
/**
|
|
@@ -1294,14 +1376,14 @@ class ApiRouter extends Router {
|
|
|
1294
1376
|
/**
|
|
1295
1377
|
* 注册 HTTP OPTIONS 处理函数
|
|
1296
1378
|
* @overload
|
|
1297
|
-
* @param {
|
|
1379
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1298
1380
|
* @returns {() => void}
|
|
1299
1381
|
*/
|
|
1300
1382
|
/**
|
|
1301
1383
|
* 注册 HTTP OPTIONS 处理函数
|
|
1302
1384
|
* @overload
|
|
1303
1385
|
* @param {string} path 要注册的路径
|
|
1304
|
-
* @param {
|
|
1386
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1305
1387
|
* @returns {() => void}
|
|
1306
1388
|
*/
|
|
1307
1389
|
/**
|
|
@@ -1347,21 +1429,22 @@ function createFetch(run, notFound) {
|
|
|
1347
1429
|
};
|
|
1348
1430
|
}
|
|
1349
1431
|
|
|
1432
|
+
/** @import { Context, Handler, HandlerResult } from './main/types' */
|
|
1350
1433
|
/**
|
|
1351
1434
|
* @callback Onionskin
|
|
1352
|
-
* @param {
|
|
1353
|
-
* @param {() => Promise<
|
|
1354
|
-
* @returns {PromiseLike<
|
|
1435
|
+
* @param {Context} ctx
|
|
1436
|
+
* @param {() => Promise<HandlerResult>} next
|
|
1437
|
+
* @returns {PromiseLike<HandlerResult> | HandlerResult}
|
|
1355
1438
|
*/
|
|
1356
1439
|
|
|
1357
1440
|
const noop = () => {};
|
|
1358
1441
|
/**
|
|
1359
1442
|
*
|
|
1360
1443
|
* @param {...(Onionskin | Onionskin[])} handlers
|
|
1361
|
-
* @returns {
|
|
1444
|
+
* @returns {Handler}
|
|
1362
1445
|
*/
|
|
1363
1446
|
function onionskin(...handlers) {
|
|
1364
|
-
/** @type {
|
|
1447
|
+
/** @type {Handler} */
|
|
1365
1448
|
let handler = noop;
|
|
1366
1449
|
for (const os of handlers.flat()) {
|
|
1367
1450
|
const currentHandler = handler;
|
|
@@ -1370,4 +1453,40 @@ function onionskin(...handlers) {
|
|
|
1370
1453
|
return handler;
|
|
1371
1454
|
}
|
|
1372
1455
|
|
|
1373
|
-
|
|
1456
|
+
/** @import { Context } from './main/types.js' */
|
|
1457
|
+
class Param {
|
|
1458
|
+
#symbol = Symbol();
|
|
1459
|
+
get name() { return this.#symbol}
|
|
1460
|
+
#pattern
|
|
1461
|
+
get pattern() { return this.#pattern; }
|
|
1462
|
+
/**
|
|
1463
|
+
*
|
|
1464
|
+
* @param {RegExp} pattern
|
|
1465
|
+
*/
|
|
1466
|
+
constructor(pattern) {
|
|
1467
|
+
this.#pattern = pattern;
|
|
1468
|
+
}
|
|
1469
|
+
/**
|
|
1470
|
+
*
|
|
1471
|
+
* @param {Context} ctx
|
|
1472
|
+
* @returns {string?}
|
|
1473
|
+
*/
|
|
1474
|
+
param(ctx) {
|
|
1475
|
+
const param = ctx.params[this.#symbol];
|
|
1476
|
+
if (Array.isArray(param)) { return param[0] ?? null; }
|
|
1477
|
+
return param ?? null;
|
|
1478
|
+
}
|
|
1479
|
+
/**
|
|
1480
|
+
*
|
|
1481
|
+
* @param {Context} ctx
|
|
1482
|
+
* @returns {string[]?}
|
|
1483
|
+
*/
|
|
1484
|
+
params(ctx) {
|
|
1485
|
+
const param = ctx.params[this.#symbol];
|
|
1486
|
+
if (typeof param === 'string') { return [param]; }
|
|
1487
|
+
if (Array.isArray(param)) { return param; }
|
|
1488
|
+
return null;
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
export { ApiRouter, Param, Router, createFetch, main, make, merge, onionskin, packer, service, stateService, storeService };
|