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.mjs
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
|
*/
|
|
@@ -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,102 @@ 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
|
+
continue;
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
const last = paths.pop() || '';
|
|
950
|
+
const strings = paths.map((v, i) => [v, values[i]]).flat();
|
|
951
|
+
strings.push(last);
|
|
952
|
+
const p = strings.join('');
|
|
953
|
+
if (!p || /^\.+$/.test(p)) { continue; }
|
|
954
|
+
list.push(parse(p));
|
|
955
|
+
continue;
|
|
956
|
+
}
|
|
957
|
+
|
|
878
958
|
}
|
|
879
959
|
if (!list.length) { return; }
|
|
880
960
|
return path => exec(list, path, end);
|
|
881
961
|
}
|
|
882
962
|
|
|
963
|
+
/** @import { Handler, Method } from '../main/types' */
|
|
964
|
+
/** @import { Binder, Match, Route, RouterRoute } from './index.mjs' */
|
|
965
|
+
|
|
883
966
|
/**
|
|
884
967
|
*
|
|
885
|
-
* @param {(
|
|
886
|
-
* @param {
|
|
887
|
-
* @param {
|
|
888
|
-
* @param {
|
|
968
|
+
* @param {(Route | RouterRoute)[]} routes
|
|
969
|
+
* @param {Set<Method>} methods
|
|
970
|
+
* @param {Match | undefined} match
|
|
971
|
+
* @param {Handler[]} handlers
|
|
889
972
|
* @returns {() => void}
|
|
890
973
|
*/
|
|
891
|
-
function bind(routes, methods,
|
|
892
|
-
/** @type {
|
|
893
|
-
const route = {
|
|
894
|
-
match: toMatch(path || '', true),
|
|
895
|
-
methods: new Set(methods),
|
|
896
|
-
handler,
|
|
897
|
-
};
|
|
974
|
+
function bind(routes, methods, match, handlers) {
|
|
975
|
+
/** @type {Route} */
|
|
976
|
+
const route = { match, methods, handler: ctx => runHandles(ctx, handlers) };
|
|
898
977
|
routes.push(route);
|
|
899
978
|
let removed = false;
|
|
900
979
|
return () => {
|
|
@@ -905,43 +984,49 @@ function bind(routes, methods, path, handler) {
|
|
|
905
984
|
routes.splice(index, 1);
|
|
906
985
|
};
|
|
907
986
|
}
|
|
908
|
-
/** @type {(v: any) => v is
|
|
987
|
+
/** @type {(v: any) => v is Handler} */
|
|
909
988
|
const findHandler = v => typeof v === 'function';
|
|
910
989
|
/**
|
|
911
990
|
*
|
|
912
|
-
* @param {(
|
|
913
|
-
* @param {
|
|
991
|
+
* @param {(Route | RouterRoute)[]} routes
|
|
992
|
+
* @param {Iterable<Method>} methods
|
|
914
993
|
* @param {any[]} p
|
|
915
|
-
* @returns {
|
|
994
|
+
* @returns {Binder | (() => void)}
|
|
916
995
|
*/
|
|
917
996
|
function verb(routes, methods, p) {
|
|
997
|
+
const methodSet = new Set(methods);
|
|
918
998
|
if (!p.length) {
|
|
919
|
-
|
|
999
|
+
const match = undefined;
|
|
1000
|
+
/** @type {Binder} */
|
|
1001
|
+
return (...handlers) => bind(routes, methodSet, match, handlers);
|
|
920
1002
|
}
|
|
921
|
-
const [
|
|
922
|
-
if (
|
|
923
|
-
const
|
|
924
|
-
|
|
1003
|
+
const [path] = p;
|
|
1004
|
+
if (path && typeof path === 'object') {
|
|
1005
|
+
const match = toMatch([path, p.slice(1)], true);
|
|
1006
|
+
/** @type {Binder} */
|
|
1007
|
+
return (...handlers) => bind(routes, methodSet, match, handlers);
|
|
925
1008
|
}
|
|
926
|
-
const
|
|
927
|
-
const
|
|
928
|
-
if (!
|
|
929
|
-
|
|
1009
|
+
const match = toMatch(typeof path === 'string' ? path : '', true);
|
|
1010
|
+
const handlers = p.filter(findHandler);
|
|
1011
|
+
if (!handlers.length) {
|
|
1012
|
+
/** @type {Binder} */
|
|
1013
|
+
return (...handlers) => bind(routes, methodSet, match, handlers);
|
|
930
1014
|
}
|
|
931
|
-
return bind(routes,
|
|
1015
|
+
return bind(routes, methodSet, match, handlers);
|
|
932
1016
|
}
|
|
933
1017
|
|
|
1018
|
+
/** @import { Method } from '../main/types' */
|
|
934
1019
|
const methods = new Set(['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS']);
|
|
935
1020
|
/**
|
|
936
1021
|
*
|
|
937
1022
|
* @param {any} v
|
|
938
|
-
* @returns {v is
|
|
1023
|
+
* @returns {v is Method}
|
|
939
1024
|
*/
|
|
940
1025
|
function isMethod(v) { return methods.has(v); }
|
|
941
1026
|
/**
|
|
942
1027
|
*
|
|
943
|
-
* @param {
|
|
944
|
-
* @returns {
|
|
1028
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} [methods]
|
|
1029
|
+
* @returns {Method[]}
|
|
945
1030
|
*/
|
|
946
1031
|
function getMethods(methods) {
|
|
947
1032
|
if (!methods) {
|
|
@@ -955,25 +1040,24 @@ function getMethods(methods) {
|
|
|
955
1040
|
.filter(isMethod);
|
|
956
1041
|
}
|
|
957
1042
|
|
|
1043
|
+
/** @import { Context, Handler, Method, Params } from '../main/types' */
|
|
1044
|
+
/** @import { Finder, FindItem } from '../Router.mjs' */
|
|
1045
|
+
|
|
958
1046
|
/**
|
|
959
1047
|
* @callback Match
|
|
960
1048
|
* @param {string[]} paths
|
|
961
|
-
* @returns {[
|
|
1049
|
+
* @returns {[Params, string[]] | undefined}
|
|
962
1050
|
*/
|
|
963
1051
|
|
|
964
|
-
/**
|
|
965
|
-
* @callback Binder
|
|
966
|
-
* @param {import('../main/types').Handler} handler
|
|
967
|
-
* @returns {() => void}
|
|
968
|
-
*/
|
|
1052
|
+
/** @typedef {(handler: Handler, ...handlers: Handler[]) => () => void} Binder */
|
|
969
1053
|
|
|
970
1054
|
/**
|
|
971
1055
|
* @typedef {object} Route
|
|
972
1056
|
* @property {Match} [match] 路径匹配
|
|
973
1057
|
* @property {null} [router]
|
|
974
1058
|
* @property {string} [plugin] 所属插件
|
|
975
|
-
* @property {
|
|
976
|
-
* @property {Set<
|
|
1059
|
+
* @property {Handler} handler 处理函数
|
|
1060
|
+
* @property {Set<Method>} methods 方法列表
|
|
977
1061
|
*/
|
|
978
1062
|
|
|
979
1063
|
/**
|
|
@@ -984,16 +1068,16 @@ function getMethods(methods) {
|
|
|
984
1068
|
|
|
985
1069
|
|
|
986
1070
|
/**
|
|
987
|
-
* @template {Router |
|
|
1071
|
+
* @template {Router | Finder} [T=ApiRouter]
|
|
988
1072
|
* @callback RouteBinder
|
|
989
1073
|
* @param {T} [router] 要注册的子路由或子路由的 Finder
|
|
990
|
-
* @returns {T extends
|
|
1074
|
+
* @returns {T extends Finder ? Router : T}
|
|
991
1075
|
*/
|
|
992
1076
|
/**
|
|
993
1077
|
*
|
|
994
1078
|
* @param {(Route | RouterRoute)[]} routes
|
|
995
|
-
* @param {string} path
|
|
996
|
-
* @param {Router |
|
|
1079
|
+
* @param {string | [string[], any[]]} path
|
|
1080
|
+
* @param {Router | Finder} [r]
|
|
997
1081
|
* @returns {Router}
|
|
998
1082
|
*/
|
|
999
1083
|
function bindRouter(routes, path, r) {
|
|
@@ -1008,18 +1092,18 @@ class ApiRouter extends Router {
|
|
|
1008
1092
|
#routes = [];
|
|
1009
1093
|
/**
|
|
1010
1094
|
* 添加子路由
|
|
1011
|
-
* @template {Router |
|
|
1095
|
+
* @template {Router | Finder} [T=ApiRouter]
|
|
1012
1096
|
* @overload
|
|
1013
1097
|
* @param {T} [router] 要注册的子路由或子路由的 Finder
|
|
1014
|
-
* @returns {T extends
|
|
1098
|
+
* @returns {T extends Finder ? Router : T}
|
|
1015
1099
|
*/
|
|
1016
1100
|
/**
|
|
1017
1101
|
* 添加子路由
|
|
1018
|
-
* @template {Router |
|
|
1102
|
+
* @template {Router | Finder} [T=ApiRouter]
|
|
1019
1103
|
* @overload
|
|
1020
1104
|
* @param {string} path 要注册的路径
|
|
1021
1105
|
* @param {T} [router] 要注册的子路由或子路由的 Finder
|
|
1022
|
-
* @returns {T extends
|
|
1106
|
+
* @returns {T extends Finder ? Router : T}
|
|
1023
1107
|
*/
|
|
1024
1108
|
/**
|
|
1025
1109
|
* 添加子路由
|
|
@@ -1036,12 +1120,11 @@ class ApiRouter extends Router {
|
|
|
1036
1120
|
route(...p) {
|
|
1037
1121
|
const [a] = p;
|
|
1038
1122
|
if (a && typeof a === 'object' && !(a instanceof Router)) {
|
|
1039
|
-
const path = String.raw(a, ...p.slice(1));
|
|
1040
1123
|
/**
|
|
1041
|
-
* @param {
|
|
1124
|
+
* @param { Finder | Router} [r];
|
|
1042
1125
|
* @returns {any}
|
|
1043
1126
|
*/
|
|
1044
|
-
return r => bindRouter(this.#routes,
|
|
1127
|
+
return r => bindRouter(this.#routes, [a, p.slice(1)], r);
|
|
1045
1128
|
}
|
|
1046
1129
|
const path = typeof a === 'string' ? a : '';
|
|
1047
1130
|
const r = typeof a === 'string' ? p[1] : a;
|
|
@@ -1049,10 +1132,10 @@ class ApiRouter extends Router {
|
|
|
1049
1132
|
}
|
|
1050
1133
|
/**
|
|
1051
1134
|
*
|
|
1052
|
-
* @param {
|
|
1135
|
+
* @param {Method} method
|
|
1053
1136
|
* @param {string[]} path
|
|
1054
|
-
* @param {
|
|
1055
|
-
* @returns {Iterable<
|
|
1137
|
+
* @param {Context} ctx
|
|
1138
|
+
* @returns {Iterable<FindItem>}
|
|
1056
1139
|
*/
|
|
1057
1140
|
*find(method, path, ctx) {
|
|
1058
1141
|
for (const route of Array.from(this.#routes)) {
|
|
@@ -1073,29 +1156,29 @@ class ApiRouter extends Router {
|
|
|
1073
1156
|
/**
|
|
1074
1157
|
* 注册处理函数
|
|
1075
1158
|
* @overload
|
|
1076
|
-
* @param {
|
|
1077
|
-
* @param {
|
|
1159
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} method 要注册的方法
|
|
1160
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1078
1161
|
* @returns {() => void}
|
|
1079
1162
|
*/
|
|
1080
1163
|
/**
|
|
1081
1164
|
* 注册处理函数
|
|
1082
1165
|
* @overload
|
|
1083
|
-
* @param {
|
|
1166
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} method 要注册的方法
|
|
1084
1167
|
* @param {string} path 要注册的路径
|
|
1085
|
-
* @param {
|
|
1168
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1086
1169
|
* @returns {() => void}
|
|
1087
1170
|
*/
|
|
1088
1171
|
/**
|
|
1089
1172
|
* 注册处理函数
|
|
1090
1173
|
* @overload
|
|
1091
|
-
* @param {
|
|
1174
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} method 要注册的方法
|
|
1092
1175
|
* @param {string} path 要注册的路径
|
|
1093
1176
|
* @returns {Binder}
|
|
1094
1177
|
*/
|
|
1095
1178
|
/**
|
|
1096
|
-
* @param {
|
|
1097
|
-
* @param {string|
|
|
1098
|
-
* @param {
|
|
1179
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} methods
|
|
1180
|
+
* @param {string| Handler} [path]
|
|
1181
|
+
* @param {Handler} [handler]
|
|
1099
1182
|
* @returns {Binder | (() => void)}
|
|
1100
1183
|
*/
|
|
1101
1184
|
verb(methods, path, handler) {
|
|
@@ -1106,14 +1189,14 @@ class ApiRouter extends Router {
|
|
|
1106
1189
|
/**
|
|
1107
1190
|
* 注册 HTTP GET/POST/PUT/DELETE 处理函数
|
|
1108
1191
|
* @overload
|
|
1109
|
-
* @param {
|
|
1192
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1110
1193
|
* @returns {() => void}
|
|
1111
1194
|
*/
|
|
1112
1195
|
/**
|
|
1113
1196
|
* 注册处理函数
|
|
1114
1197
|
* @overload
|
|
1115
1198
|
* @param {string} path 要注册的路径
|
|
1116
|
-
* @param {
|
|
1199
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1117
1200
|
* @returns {() => void}
|
|
1118
1201
|
*/
|
|
1119
1202
|
/**
|
|
@@ -1139,14 +1222,14 @@ class ApiRouter extends Router {
|
|
|
1139
1222
|
/**
|
|
1140
1223
|
* 注册 HTTP GET 处理函数
|
|
1141
1224
|
* @overload
|
|
1142
|
-
* @param {
|
|
1225
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1143
1226
|
* @returns {() => void}
|
|
1144
1227
|
*/
|
|
1145
1228
|
/**
|
|
1146
1229
|
* 注册 HTTP GET 处理函数
|
|
1147
1230
|
* @overload
|
|
1148
1231
|
* @param {string} path 要注册的路径
|
|
1149
|
-
* @param {
|
|
1232
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1150
1233
|
* @returns {() => void}
|
|
1151
1234
|
*/
|
|
1152
1235
|
/**
|
|
@@ -1170,14 +1253,14 @@ class ApiRouter extends Router {
|
|
|
1170
1253
|
/**
|
|
1171
1254
|
* 注册 HTTP POST 处理函数
|
|
1172
1255
|
* @overload
|
|
1173
|
-
* @param {
|
|
1256
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1174
1257
|
* @returns {() => void}
|
|
1175
1258
|
*/
|
|
1176
1259
|
/**
|
|
1177
1260
|
* 注册 HTTP POST 处理函数
|
|
1178
1261
|
* @overload
|
|
1179
1262
|
* @param {string} path 要注册的路径
|
|
1180
|
-
* @param {
|
|
1263
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1181
1264
|
* @returns {() => void}
|
|
1182
1265
|
*/
|
|
1183
1266
|
/**
|
|
@@ -1201,14 +1284,14 @@ class ApiRouter extends Router {
|
|
|
1201
1284
|
/**
|
|
1202
1285
|
* 注册 HTTP PUT 处理函数
|
|
1203
1286
|
* @overload
|
|
1204
|
-
* @param {
|
|
1287
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1205
1288
|
* @returns {() => void}
|
|
1206
1289
|
*/
|
|
1207
1290
|
/**
|
|
1208
1291
|
* 注册 HTTP PUT 处理函数
|
|
1209
1292
|
* @overload
|
|
1210
1293
|
* @param {string} path 要注册的路径
|
|
1211
|
-
* @param {
|
|
1294
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1212
1295
|
* @returns {() => void}
|
|
1213
1296
|
*/
|
|
1214
1297
|
/**
|
|
@@ -1232,14 +1315,14 @@ class ApiRouter extends Router {
|
|
|
1232
1315
|
/**
|
|
1233
1316
|
* 注册 HTTP DELETE 处理函数
|
|
1234
1317
|
* @overload
|
|
1235
|
-
* @param {
|
|
1318
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1236
1319
|
* @returns {() => void}
|
|
1237
1320
|
*/
|
|
1238
1321
|
/**
|
|
1239
1322
|
* 注册 HTTP DELETE 处理函数
|
|
1240
1323
|
* @overload
|
|
1241
1324
|
* @param {string} path 要注册的路径
|
|
1242
|
-
* @param {
|
|
1325
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1243
1326
|
* @returns {() => void}
|
|
1244
1327
|
*/
|
|
1245
1328
|
/**
|
|
@@ -1263,14 +1346,14 @@ class ApiRouter extends Router {
|
|
|
1263
1346
|
/**
|
|
1264
1347
|
* 注册 HTTP HEAD 处理函数
|
|
1265
1348
|
* @overload
|
|
1266
|
-
* @param {
|
|
1349
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1267
1350
|
* @returns {() => void}
|
|
1268
1351
|
*/
|
|
1269
1352
|
/**
|
|
1270
1353
|
* 注册 HTTP HEAD 处理函数
|
|
1271
1354
|
* @overload
|
|
1272
1355
|
* @param {string} path 要注册的路径
|
|
1273
|
-
* @param {
|
|
1356
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1274
1357
|
* @returns {() => void}
|
|
1275
1358
|
*/
|
|
1276
1359
|
/**
|
|
@@ -1294,14 +1377,14 @@ class ApiRouter extends Router {
|
|
|
1294
1377
|
/**
|
|
1295
1378
|
* 注册 HTTP OPTIONS 处理函数
|
|
1296
1379
|
* @overload
|
|
1297
|
-
* @param {
|
|
1380
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1298
1381
|
* @returns {() => void}
|
|
1299
1382
|
*/
|
|
1300
1383
|
/**
|
|
1301
1384
|
* 注册 HTTP OPTIONS 处理函数
|
|
1302
1385
|
* @overload
|
|
1303
1386
|
* @param {string} path 要注册的路径
|
|
1304
|
-
* @param {
|
|
1387
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1305
1388
|
* @returns {() => void}
|
|
1306
1389
|
*/
|
|
1307
1390
|
/**
|
|
@@ -1347,21 +1430,22 @@ function createFetch(run, notFound) {
|
|
|
1347
1430
|
};
|
|
1348
1431
|
}
|
|
1349
1432
|
|
|
1433
|
+
/** @import { Context, Handler, HandlerResult } from './main/types' */
|
|
1350
1434
|
/**
|
|
1351
1435
|
* @callback Onionskin
|
|
1352
|
-
* @param {
|
|
1353
|
-
* @param {() => Promise<
|
|
1354
|
-
* @returns {PromiseLike<
|
|
1436
|
+
* @param {Context} ctx
|
|
1437
|
+
* @param {() => Promise<HandlerResult>} next
|
|
1438
|
+
* @returns {PromiseLike<HandlerResult> | HandlerResult}
|
|
1355
1439
|
*/
|
|
1356
1440
|
|
|
1357
1441
|
const noop = () => {};
|
|
1358
1442
|
/**
|
|
1359
1443
|
*
|
|
1360
1444
|
* @param {...(Onionskin | Onionskin[])} handlers
|
|
1361
|
-
* @returns {
|
|
1445
|
+
* @returns {Handler}
|
|
1362
1446
|
*/
|
|
1363
1447
|
function onionskin(...handlers) {
|
|
1364
|
-
/** @type {
|
|
1448
|
+
/** @type {Handler} */
|
|
1365
1449
|
let handler = noop;
|
|
1366
1450
|
for (const os of handlers.flat()) {
|
|
1367
1451
|
const currentHandler = handler;
|
|
@@ -1370,4 +1454,40 @@ function onionskin(...handlers) {
|
|
|
1370
1454
|
return handler;
|
|
1371
1455
|
}
|
|
1372
1456
|
|
|
1373
|
-
|
|
1457
|
+
/** @import { Context } from './main/types.js' */
|
|
1458
|
+
class Param {
|
|
1459
|
+
#symbol = Symbol();
|
|
1460
|
+
get name() { return this.#symbol}
|
|
1461
|
+
#pattern
|
|
1462
|
+
get pattern() { return this.#pattern; }
|
|
1463
|
+
/**
|
|
1464
|
+
*
|
|
1465
|
+
* @param {RegExp?} [pattern]
|
|
1466
|
+
*/
|
|
1467
|
+
constructor(pattern) {
|
|
1468
|
+
this.#pattern = pattern;
|
|
1469
|
+
}
|
|
1470
|
+
/**
|
|
1471
|
+
*
|
|
1472
|
+
* @param {Context} ctx
|
|
1473
|
+
* @returns {string?}
|
|
1474
|
+
*/
|
|
1475
|
+
param(ctx) {
|
|
1476
|
+
const param = ctx.params[this.#symbol];
|
|
1477
|
+
if (Array.isArray(param)) { return param[0] ?? null; }
|
|
1478
|
+
return param ?? null;
|
|
1479
|
+
}
|
|
1480
|
+
/**
|
|
1481
|
+
*
|
|
1482
|
+
* @param {Context} ctx
|
|
1483
|
+
* @returns {string[]?}
|
|
1484
|
+
*/
|
|
1485
|
+
params(ctx) {
|
|
1486
|
+
const param = ctx.params[this.#symbol];
|
|
1487
|
+
if (typeof param === 'string') { return [param]; }
|
|
1488
|
+
if (Array.isArray(param)) { return param; }
|
|
1489
|
+
return null;
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
export { ApiRouter, Param, Router, createFetch, main, make, merge, onionskin, packer, service, stateService, storeService };
|