k99 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs +304 -198
- package/index.d.ts +82 -81
- package/index.js +304 -198
- package/index.min.js +3 -3
- package/index.min.mjs +3 -3
- package/index.mjs +304 -199
- package/package.json +2 -3
- package/services.cjs +6 -4
- package/services.d.ts +8 -7
- package/services.js +6 -4
- package/services.min.js +2 -2
- package/services.min.mjs +2 -2
- package/services.mjs +6 -4
- package/node/index.cjs +0 -140
- package/node/index.d.cts +0 -52
package/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* k99 v0.
|
|
3
|
-
* (c) 2019-
|
|
2
|
+
* k99 v0.7.0
|
|
3
|
+
* (c) 2019-2025 猛火Fierflame
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
6
6
|
/**
|
|
@@ -11,20 +11,6 @@
|
|
|
11
11
|
function str2utf8bin(str) {
|
|
12
12
|
return new TextEncoder().encode(str);
|
|
13
13
|
}
|
|
14
|
-
/**
|
|
15
|
-
*
|
|
16
|
-
* @param {unknown} chunk
|
|
17
|
-
* @returns {chunk is ArrayBuffer | SharedArrayBuffer}
|
|
18
|
-
*/
|
|
19
|
-
function isBufferSource(chunk) {
|
|
20
|
-
if (chunk instanceof ArrayBuffer) { return true; }
|
|
21
|
-
try {
|
|
22
|
-
if (chunk instanceof SharedArrayBuffer) { return true; }
|
|
23
|
-
} catch {
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
28
14
|
/**
|
|
29
15
|
*
|
|
30
16
|
* @template T
|
|
@@ -49,7 +35,7 @@ async function write(writer, chunk) {
|
|
|
49
35
|
if (ArrayBuffer.isView(chunk)) {
|
|
50
36
|
return writer.write(new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength));
|
|
51
37
|
}
|
|
52
|
-
if (
|
|
38
|
+
if (chunk instanceof ArrayBuffer) {
|
|
53
39
|
return writer.write(new Uint8Array(chunk));
|
|
54
40
|
}
|
|
55
41
|
if (!isIterable(chunk)) {
|
|
@@ -93,7 +79,7 @@ function toBodyData(result, aborted) {
|
|
|
93
79
|
if (result instanceof FormData) {
|
|
94
80
|
return [result, 0, ''];
|
|
95
81
|
}
|
|
96
|
-
if (ArrayBuffer.isView(result) ||
|
|
82
|
+
if (ArrayBuffer.isView(result) || result instanceof ArrayBuffer) {
|
|
97
83
|
return [result, result.byteLength, ''];
|
|
98
84
|
}
|
|
99
85
|
if (typeof result === 'string') {
|
|
@@ -118,8 +104,7 @@ function toBodyData(result, aborted) {
|
|
|
118
104
|
if (!data) { continue; }
|
|
119
105
|
await write(writer, data);
|
|
120
106
|
}
|
|
121
|
-
|
|
122
|
-
})().catch(() => {});
|
|
107
|
+
})().then(() => writable.close(), r => writable.abort(r)).catch(() => {});
|
|
123
108
|
return [readable, 0, ''];
|
|
124
109
|
}
|
|
125
110
|
/**
|
|
@@ -142,11 +127,12 @@ function toBody(result, headers, aborted) {
|
|
|
142
127
|
return body;
|
|
143
128
|
}
|
|
144
129
|
|
|
130
|
+
/** @import { Cookie, CookieOption } from './types' */
|
|
145
131
|
/**
|
|
146
132
|
*
|
|
147
|
-
* @param {
|
|
133
|
+
* @param {Cookie[]} sentCookies
|
|
148
134
|
* @param {string} [name]
|
|
149
|
-
* @returns {Iterable<
|
|
135
|
+
* @returns {Iterable<Cookie>}
|
|
150
136
|
*/
|
|
151
137
|
function *getCookie(sentCookies, name) {
|
|
152
138
|
const list = sentCookies;
|
|
@@ -159,7 +145,7 @@ function *getCookie(sentCookies, name) {
|
|
|
159
145
|
/**
|
|
160
146
|
*
|
|
161
147
|
* @param {Headers} headers
|
|
162
|
-
* @param {
|
|
148
|
+
* @param {Cookie[]} cookies
|
|
163
149
|
* @returns {void}
|
|
164
150
|
*/
|
|
165
151
|
function setCookiesHeader(headers, cookies) {
|
|
@@ -193,10 +179,10 @@ function getRequestCookies(cookie) {
|
|
|
193
179
|
}
|
|
194
180
|
/**
|
|
195
181
|
*
|
|
196
|
-
* @param {
|
|
182
|
+
* @param {Cookie[]} sentCookies
|
|
197
183
|
* @param {Record<string, string>} cookies
|
|
198
|
-
* @param {string |
|
|
199
|
-
* @param {
|
|
184
|
+
* @param {string | CookieOption} [name]
|
|
185
|
+
* @param {CookieOption | boolean} [opt]
|
|
200
186
|
* @returns {void}
|
|
201
187
|
*/
|
|
202
188
|
function clearCookie(
|
|
@@ -208,11 +194,11 @@ function clearCookie(
|
|
|
208
194
|
let expire = 'Fri, 31 Dec 1999 16:00:00 GMT';
|
|
209
195
|
if (typeof name === 'string') {
|
|
210
196
|
if (!name) { return; }
|
|
211
|
-
/** @type {
|
|
197
|
+
/** @type {CookieOption} */
|
|
212
198
|
const { domain, path, secure, httpOnly } = opt !== true && opt || {};
|
|
213
199
|
sentCookies.push({ name, value: 'delete', expire, domain, path, secure, httpOnly });
|
|
214
200
|
} else {
|
|
215
|
-
/** @type {
|
|
201
|
+
/** @type {CookieOption} */
|
|
216
202
|
const { domain, path, secure, httpOnly } = name || {};
|
|
217
203
|
sentCookies.length = 0;
|
|
218
204
|
if (opt) {
|
|
@@ -223,6 +209,9 @@ function clearCookie(
|
|
|
223
209
|
}
|
|
224
210
|
}
|
|
225
211
|
|
|
212
|
+
/** @import { Context, Cookie, CookieOption, FindHandler, Method, Options, Params, Service } from './types' */
|
|
213
|
+
|
|
214
|
+
|
|
226
215
|
const noBodyMethods = new Set(['GET', 'OPTIONS']);
|
|
227
216
|
/**
|
|
228
217
|
*
|
|
@@ -259,7 +248,7 @@ function setHeader(headers, name, value) {
|
|
|
259
248
|
*
|
|
260
249
|
* @param {Request} request
|
|
261
250
|
* @param {string | ((request: Request) => string)} [toMethod]
|
|
262
|
-
* @returns {
|
|
251
|
+
* @returns {Method}
|
|
263
252
|
*/
|
|
264
253
|
function getMethod(request, toMethod) {
|
|
265
254
|
let methodStr = '';
|
|
@@ -271,13 +260,13 @@ function getMethod(request, toMethod) {
|
|
|
271
260
|
if (!methodStr || typeof methodStr !== 'string') {
|
|
272
261
|
methodStr = request.method || 'GET';
|
|
273
262
|
}
|
|
274
|
-
return /** @type {
|
|
263
|
+
return /** @type {Method} */(methodStr.toUpperCase());
|
|
275
264
|
}
|
|
276
265
|
/**
|
|
277
266
|
*
|
|
278
267
|
* @param {Request} request
|
|
279
|
-
* @param {
|
|
280
|
-
* @param {
|
|
268
|
+
* @param {FindHandler} getHandler
|
|
269
|
+
* @param {Options} [options]
|
|
281
270
|
* @returns {Promise<Response | null>}
|
|
282
271
|
*/
|
|
283
272
|
function main(
|
|
@@ -287,7 +276,7 @@ function main(
|
|
|
287
276
|
/**
|
|
288
277
|
*
|
|
289
278
|
* @param {Request} request
|
|
290
|
-
* @param {
|
|
279
|
+
* @param {Context} [parent]
|
|
291
280
|
* @returns {Promise<Response | null>}
|
|
292
281
|
*/
|
|
293
282
|
function exec(request, parent) {
|
|
@@ -295,10 +284,10 @@ function main(
|
|
|
295
284
|
const url = new URL(request.url);
|
|
296
285
|
const { signal, headers } = request;
|
|
297
286
|
const aborted = signal2promise(signal);
|
|
298
|
-
/** @type {Map<
|
|
287
|
+
/** @type {Map<Service<any, any>, Function>} */
|
|
299
288
|
const services = new Map();
|
|
300
289
|
const cookies = getRequestCookies(headers.get('cookie') || '');
|
|
301
|
-
/** @type {
|
|
290
|
+
/** @type {Cookie[]} */
|
|
302
291
|
const sentCookies = [];
|
|
303
292
|
const responseHeaders = new Headers();
|
|
304
293
|
const root = parent?.root;
|
|
@@ -314,9 +303,9 @@ function main(
|
|
|
314
303
|
const donePromise = new Promise((a, b) => { resolve = a; reject = b; });
|
|
315
304
|
donePromise.catch(() => {});
|
|
316
305
|
|
|
317
|
-
/** @type {
|
|
306
|
+
/** @type {Params} */
|
|
318
307
|
let params = {};
|
|
319
|
-
/** @type {
|
|
308
|
+
/** @type {Context} */
|
|
320
309
|
const context = {
|
|
321
310
|
environment,
|
|
322
311
|
parent,
|
|
@@ -380,8 +369,8 @@ function main(
|
|
|
380
369
|
},
|
|
381
370
|
/**
|
|
382
371
|
*
|
|
383
|
-
* @param {string |
|
|
384
|
-
* @param {
|
|
372
|
+
* @param {string | CookieOption} [name]
|
|
373
|
+
* @param {CookieOption | boolean} [opt]
|
|
385
374
|
* @returns {void}
|
|
386
375
|
*/
|
|
387
376
|
clearCookie(name, opt) {
|
|
@@ -418,69 +407,72 @@ function main(
|
|
|
418
407
|
return exec(request);
|
|
419
408
|
}
|
|
420
409
|
|
|
410
|
+
/** @import { FindHandler, Options } from './main/types' */
|
|
411
|
+
|
|
421
412
|
/**
|
|
422
413
|
*
|
|
423
|
-
* @param {
|
|
424
|
-
* @param {
|
|
414
|
+
* @param {FindHandler} getHandler
|
|
415
|
+
* @param {Options} options
|
|
425
416
|
* @returns {(request: Request) => Promise<Response | null>}
|
|
426
417
|
*/
|
|
427
418
|
function make(getHandler, options) {
|
|
428
419
|
return r => main(r, getHandler, options);
|
|
429
420
|
}
|
|
430
421
|
|
|
422
|
+
/** @import { Context, Handler } from './main/types' */
|
|
431
423
|
/**
|
|
432
424
|
*
|
|
433
|
-
* @param {
|
|
434
|
-
* @param {
|
|
425
|
+
* @param {Context} context
|
|
426
|
+
* @param {Handler[]} handlers
|
|
435
427
|
* @returns {Promise<string | boolean | object | undefined>}
|
|
436
428
|
*/
|
|
437
429
|
async function runHandles(context, handlers) {
|
|
438
430
|
for (const handle of handlers) {
|
|
439
431
|
const result = await handle(context);
|
|
440
|
-
if (
|
|
441
|
-
if (!result) { continue; }
|
|
432
|
+
if (result === undefined) { continue; }
|
|
442
433
|
return result;
|
|
443
434
|
}
|
|
444
435
|
}
|
|
445
436
|
|
|
446
437
|
/**
|
|
447
438
|
*
|
|
448
|
-
* @param {...(
|
|
449
|
-
* @returns {
|
|
439
|
+
* @param {...(Handler | Handler[])} handlers
|
|
440
|
+
* @returns {Handler}
|
|
450
441
|
*/
|
|
451
442
|
function merge(...handlers) {
|
|
452
443
|
return ctx => runHandles(ctx, handlers.flat());
|
|
453
444
|
}
|
|
454
445
|
|
|
446
|
+
/** @import { Context, Service } from './main/types' */
|
|
455
447
|
/**
|
|
456
448
|
*
|
|
457
449
|
* @template T
|
|
458
450
|
* @template {any[]} P
|
|
459
451
|
* @overload
|
|
460
|
-
* @param {(ctx:
|
|
461
|
-
* @param {((ctx:
|
|
462
|
-
* @param {
|
|
463
|
-
* @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>}
|
|
464
456
|
*/
|
|
465
457
|
/**
|
|
466
458
|
*
|
|
467
459
|
* @template T
|
|
468
460
|
* @template {any[]} P
|
|
469
461
|
* @overload
|
|
470
|
-
* @param {(ctx:
|
|
471
|
-
* @param {
|
|
472
|
-
* @returns {
|
|
462
|
+
* @param {(ctx: Context, ...p: P) => T} exec
|
|
463
|
+
* @param {Service.Options?} [options]
|
|
464
|
+
* @returns {Service<T, P>}
|
|
473
465
|
*/
|
|
474
466
|
/**
|
|
475
467
|
* @template T
|
|
476
468
|
* @template {any[]} P
|
|
477
|
-
* @param {(ctx:
|
|
478
|
-
* @param {((ctx:
|
|
479
|
-
* @param {
|
|
480
|
-
* @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>}
|
|
481
473
|
*/
|
|
482
474
|
function service(exec, destroy, options) {
|
|
483
|
-
/** @type {
|
|
475
|
+
/** @type {Service<T, P>} */
|
|
484
476
|
const service = function (ctx) {
|
|
485
477
|
if (typeof destroy === 'function') {
|
|
486
478
|
ctx.done(() => destroy(ctx), error => destroy(ctx, error));
|
|
@@ -499,43 +491,44 @@ function service(exec, destroy, options) {
|
|
|
499
491
|
return service;
|
|
500
492
|
}
|
|
501
493
|
|
|
494
|
+
/** @import { Context, Service, StateService } from './main/types' */
|
|
502
495
|
/**
|
|
503
496
|
*
|
|
504
497
|
* @template T
|
|
505
498
|
* @overload
|
|
506
|
-
* @param {(ctx:
|
|
507
|
-
* @param {
|
|
508
|
-
* @returns {
|
|
499
|
+
* @param {(ctx: Context) => T} init
|
|
500
|
+
* @param {Service.Options} [options]
|
|
501
|
+
* @returns {StateService<T>}
|
|
509
502
|
*/
|
|
510
503
|
/**
|
|
511
504
|
*
|
|
512
505
|
* @template T
|
|
513
506
|
* @overload
|
|
514
|
-
* @param {(ctx:
|
|
515
|
-
* @param {((state: T | undefined, ctx:
|
|
516
|
-
* @param {
|
|
517
|
-
* @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>}
|
|
518
511
|
*/
|
|
519
512
|
/**
|
|
520
513
|
*
|
|
521
514
|
* @template T
|
|
522
515
|
* @overload
|
|
523
|
-
* @param {(ctx:
|
|
524
|
-
* @param {((state: T | undefined, ctx:
|
|
525
|
-
* @param {((state: T, ctx:
|
|
526
|
-
* @param {
|
|
527
|
-
* @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>}
|
|
528
521
|
*/
|
|
529
522
|
/**
|
|
530
523
|
* @template T
|
|
531
|
-
* @param {(ctx:
|
|
532
|
-
* @param {((state: T | undefined, ctx:
|
|
533
|
-
* @param {((state: T, ctx:
|
|
534
|
-
* @param {
|
|
535
|
-
* @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>}
|
|
536
529
|
*/
|
|
537
530
|
function stateService(init, destroy, exec, options) {
|
|
538
|
-
/** @type {
|
|
531
|
+
/** @type {StateService<T>} */
|
|
539
532
|
const service = function (ctx) {
|
|
540
533
|
const state = init(ctx) || /** @type {T} */({});
|
|
541
534
|
if (typeof destroy === 'function') {
|
|
@@ -559,39 +552,40 @@ function stateService(init, destroy, exec, options) {
|
|
|
559
552
|
return service;
|
|
560
553
|
}
|
|
561
554
|
|
|
555
|
+
/** @import { Context, Service, StoreService } from './main/types' */
|
|
562
556
|
/**
|
|
563
557
|
*
|
|
564
558
|
* @template T
|
|
565
559
|
* @overload
|
|
566
|
-
* @param {
|
|
567
|
-
* @returns {
|
|
560
|
+
* @param {Service.Options?} [options]
|
|
561
|
+
* @returns {StoreService<T>}
|
|
568
562
|
*/
|
|
569
563
|
/**
|
|
570
564
|
*
|
|
571
565
|
* @template T
|
|
572
566
|
* @overload
|
|
573
|
-
* @param {((state: T | undefined, ctx:
|
|
574
|
-
* @param {
|
|
575
|
-
* @returns {
|
|
567
|
+
* @param {((state: T | undefined, ctx: Context, error?: unknown) => PromiseLike<void> | void)?} [destroy]
|
|
568
|
+
* @param {Service.Options?} [options]
|
|
569
|
+
* @returns {StoreService<T>}
|
|
576
570
|
*/
|
|
577
571
|
/**
|
|
578
572
|
*
|
|
579
573
|
* @template T
|
|
580
574
|
* @overload
|
|
581
|
-
* @param {((state: T | undefined, ctx:
|
|
582
|
-
* @param {((state: T | undefined, ctx:
|
|
583
|
-
* @param {
|
|
584
|
-
* @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>}
|
|
585
579
|
*/
|
|
586
580
|
/**
|
|
587
581
|
* @template T
|
|
588
|
-
* @param {((state: T | undefined, ctx:
|
|
589
|
-
* @param {((state: T | undefined, ctx:
|
|
590
|
-
* @param {
|
|
591
|
-
* @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>}
|
|
592
586
|
*/
|
|
593
587
|
function storeService(destroy, exec, options) {
|
|
594
|
-
/** @type {
|
|
588
|
+
/** @type {StoreService<T>} */
|
|
595
589
|
const service = function (ctx) {
|
|
596
590
|
/** @type {T | undefined} */
|
|
597
591
|
let state;
|
|
@@ -628,16 +622,18 @@ function storeService(destroy, exec, options) {
|
|
|
628
622
|
return service;
|
|
629
623
|
}
|
|
630
624
|
|
|
625
|
+
/** @import { Handler } from './main/types' */
|
|
626
|
+
/** @import { Onionskin } from './onionskin.mjs' */
|
|
631
627
|
/**
|
|
632
628
|
* @callback Packer
|
|
633
|
-
* @param {
|
|
634
|
-
* @returns {
|
|
629
|
+
* @param {Handler} handler
|
|
630
|
+
* @returns {Handler}
|
|
635
631
|
*/
|
|
636
632
|
/** @type {Packer} */
|
|
637
633
|
const noop$1 = h => h;
|
|
638
634
|
/**
|
|
639
635
|
*
|
|
640
|
-
* @param {
|
|
636
|
+
* @param {Onionskin} onionskin
|
|
641
637
|
* @param {Packer} [packer]
|
|
642
638
|
* @returns {Packer}
|
|
643
639
|
*/
|
|
@@ -648,30 +644,33 @@ function packer(onionskin, packer = noop$1) {
|
|
|
648
644
|
};
|
|
649
645
|
}
|
|
650
646
|
|
|
647
|
+
/** @import { Context, FindHandler, Handler, Method, Params } from './main/types' */
|
|
648
|
+
/** @import { Onionskin } from './onionskin.mjs' */
|
|
649
|
+
|
|
651
650
|
/**
|
|
652
651
|
* @callback Guard
|
|
653
|
-
* @param {
|
|
654
|
-
* @returns {PromiseLike<boolean |
|
|
652
|
+
* @param {Context} ctx
|
|
653
|
+
* @returns {PromiseLike<boolean | Handler | void> | boolean | Handler | void}
|
|
655
654
|
*/
|
|
656
655
|
/**
|
|
657
|
-
* @typedef {[
|
|
656
|
+
* @typedef {[Handler | Router, Record<string | symbol, any>, string[]]} FindItem
|
|
658
657
|
*/
|
|
659
658
|
/**
|
|
660
659
|
* @callback Finder
|
|
661
660
|
* @this {Router}
|
|
662
|
-
* @param {
|
|
661
|
+
* @param {Method} method
|
|
663
662
|
* @param {string[]} path
|
|
664
|
-
* @param {
|
|
663
|
+
* @param {Context} ctx
|
|
665
664
|
* @returns {AsyncIterable<FindItem> | Iterable<FindItem>}
|
|
666
665
|
*/
|
|
667
666
|
|
|
668
667
|
/**
|
|
669
668
|
*
|
|
670
669
|
* @param {Set<Guard>} guards
|
|
671
|
-
* @param {
|
|
670
|
+
* @param {Context} ctx
|
|
672
671
|
* @param {(v: any) => void} setParams
|
|
673
672
|
* @param {object} params
|
|
674
|
-
* @returns {Promise<boolean |
|
|
673
|
+
* @returns {Promise<boolean | Handler>}
|
|
675
674
|
*/
|
|
676
675
|
async function execGuard(guards, ctx, setParams, params) {
|
|
677
676
|
if (!guards.size) { return true; }
|
|
@@ -690,12 +689,12 @@ async function execGuard(guards, ctx, setParams, params) {
|
|
|
690
689
|
|
|
691
690
|
/**
|
|
692
691
|
*
|
|
693
|
-
* @param {Router |
|
|
692
|
+
* @param {Router | Handler} route
|
|
694
693
|
* @param {string[]} path
|
|
695
|
-
* @param {
|
|
696
|
-
* @param {(v:
|
|
697
|
-
* @param {
|
|
698
|
-
* @returns {Promise<
|
|
694
|
+
* @param {Context} ctx
|
|
695
|
+
* @param {(v: Params) => void} setParams
|
|
696
|
+
* @param {Params} params
|
|
697
|
+
* @returns {Promise<Handler | null>}
|
|
699
698
|
*/
|
|
700
699
|
async function find(route, path, ctx, setParams, params) {
|
|
701
700
|
if (!(route instanceof Router)) {
|
|
@@ -734,16 +733,16 @@ class Router {
|
|
|
734
733
|
disabled = false;
|
|
735
734
|
/**
|
|
736
735
|
* @abstract
|
|
737
|
-
* @param {
|
|
736
|
+
* @param {Method} method
|
|
738
737
|
* @param {string[]} path
|
|
739
|
-
* @param {
|
|
738
|
+
* @param {Context} ctx
|
|
740
739
|
* @returns {AsyncIterable<FindItem> | Iterable<FindItem>}
|
|
741
740
|
*/
|
|
742
741
|
find(method, path, ctx) { return []; }
|
|
743
742
|
/**
|
|
744
743
|
*
|
|
745
744
|
* @param {Router[]} routers
|
|
746
|
-
* @returns {
|
|
745
|
+
* @returns {FindHandler}
|
|
747
746
|
*/
|
|
748
747
|
static make(routers) {
|
|
749
748
|
return async (ctx, setParams) => {
|
|
@@ -771,19 +770,21 @@ class Router {
|
|
|
771
770
|
guards = new Set();
|
|
772
771
|
/**
|
|
773
772
|
*
|
|
774
|
-
* @param {
|
|
775
|
-
* @returns {
|
|
773
|
+
* @param {Handler} h
|
|
774
|
+
* @returns {Handler}
|
|
776
775
|
*/
|
|
777
776
|
__onionskin = (h) => h;
|
|
778
|
-
/** @param {
|
|
777
|
+
/** @param {Onionskin} os */
|
|
779
778
|
onionskin(os) { this.__onionskin = packer(os, this.__onionskin); }
|
|
780
779
|
}
|
|
781
780
|
|
|
781
|
+
/** @import { Match } from './index.mjs' */
|
|
782
|
+
/** @import { Params } from '../main/types.js' */
|
|
782
783
|
/**
|
|
783
784
|
* @typedef {object} Pattern
|
|
784
|
-
* @property {string} name
|
|
785
|
-
* @property {boolean} optional
|
|
786
|
-
* @property {boolean} many
|
|
785
|
+
* @property {string | symbol} name
|
|
786
|
+
* @property {boolean} [optional]
|
|
787
|
+
* @property {boolean} [many]
|
|
787
788
|
* @property {RegExp} pattern
|
|
788
789
|
*/
|
|
789
790
|
|
|
@@ -854,7 +855,7 @@ function parse(p) {
|
|
|
854
855
|
* @returns {[Record<string, string | string[]>, string[]] | undefined}
|
|
855
856
|
*/
|
|
856
857
|
function exec(match, path, end) {
|
|
857
|
-
/** @type {
|
|
858
|
+
/** @type {Params} */
|
|
858
859
|
const params = {};
|
|
859
860
|
for (let i = 0; i < match.length; i++) {
|
|
860
861
|
const m = match[i];
|
|
@@ -877,38 +878,101 @@ function exec(match, path, end) {
|
|
|
877
878
|
return [params, []];
|
|
878
879
|
|
|
879
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
|
+
}
|
|
880
909
|
/**
|
|
881
910
|
*
|
|
882
|
-
* @param {string} path
|
|
911
|
+
* @param {string | [string[], any[]]} path
|
|
883
912
|
* @param {boolean} end
|
|
884
|
-
* @returns {
|
|
913
|
+
* @returns {Match | undefined}
|
|
885
914
|
*/
|
|
886
915
|
function toMatch(path, end) {
|
|
887
916
|
/** @type {(Pattern | string)[]} */
|
|
888
917
|
const list = [];
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
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
|
+
|
|
892
957
|
}
|
|
893
958
|
if (!list.length) { return; }
|
|
894
959
|
return path => exec(list, path, end);
|
|
895
960
|
}
|
|
896
961
|
|
|
962
|
+
/** @import { Handler, Method } from '../main/types' */
|
|
963
|
+
/** @import { Binder, Match, Route, RouterRoute } from './index.mjs' */
|
|
964
|
+
|
|
897
965
|
/**
|
|
898
966
|
*
|
|
899
|
-
* @param {(
|
|
900
|
-
* @param {
|
|
901
|
-
* @param {
|
|
902
|
-
* @param {
|
|
967
|
+
* @param {(Route | RouterRoute)[]} routes
|
|
968
|
+
* @param {Set<Method>} methods
|
|
969
|
+
* @param {Match | undefined} match
|
|
970
|
+
* @param {Handler[]} handlers
|
|
903
971
|
* @returns {() => void}
|
|
904
972
|
*/
|
|
905
|
-
function bind(routes, methods,
|
|
906
|
-
/** @type {
|
|
907
|
-
const route = {
|
|
908
|
-
match: toMatch(path || '', true),
|
|
909
|
-
methods: new Set(methods),
|
|
910
|
-
handler,
|
|
911
|
-
};
|
|
973
|
+
function bind(routes, methods, match, handlers) {
|
|
974
|
+
/** @type {Route} */
|
|
975
|
+
const route = { match, methods, handler: ctx => runHandles(ctx, handlers) };
|
|
912
976
|
routes.push(route);
|
|
913
977
|
let removed = false;
|
|
914
978
|
return () => {
|
|
@@ -919,43 +983,49 @@ function bind(routes, methods, path, handler) {
|
|
|
919
983
|
routes.splice(index, 1);
|
|
920
984
|
};
|
|
921
985
|
}
|
|
922
|
-
/** @type {(v: any) => v is
|
|
986
|
+
/** @type {(v: any) => v is Handler} */
|
|
923
987
|
const findHandler = v => typeof v === 'function';
|
|
924
988
|
/**
|
|
925
989
|
*
|
|
926
|
-
* @param {(
|
|
927
|
-
* @param {
|
|
990
|
+
* @param {(Route | RouterRoute)[]} routes
|
|
991
|
+
* @param {Iterable<Method>} methods
|
|
928
992
|
* @param {any[]} p
|
|
929
|
-
* @returns {
|
|
993
|
+
* @returns {Binder | (() => void)}
|
|
930
994
|
*/
|
|
931
995
|
function verb(routes, methods, p) {
|
|
996
|
+
const methodSet = new Set(methods);
|
|
932
997
|
if (!p.length) {
|
|
933
|
-
|
|
998
|
+
const match = undefined;
|
|
999
|
+
/** @type {Binder} */
|
|
1000
|
+
return (...handlers) => bind(routes, methodSet, match, handlers);
|
|
934
1001
|
}
|
|
935
|
-
const [
|
|
936
|
-
if (
|
|
937
|
-
const
|
|
938
|
-
|
|
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);
|
|
939
1007
|
}
|
|
940
|
-
const
|
|
941
|
-
const
|
|
942
|
-
if (!
|
|
943
|
-
|
|
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);
|
|
944
1013
|
}
|
|
945
|
-
return bind(routes,
|
|
1014
|
+
return bind(routes, methodSet, match, handlers);
|
|
946
1015
|
}
|
|
947
1016
|
|
|
1017
|
+
/** @import { Method } from '../main/types' */
|
|
948
1018
|
const methods = new Set(['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS']);
|
|
949
1019
|
/**
|
|
950
1020
|
*
|
|
951
1021
|
* @param {any} v
|
|
952
|
-
* @returns {v is
|
|
1022
|
+
* @returns {v is Method}
|
|
953
1023
|
*/
|
|
954
1024
|
function isMethod(v) { return methods.has(v); }
|
|
955
1025
|
/**
|
|
956
1026
|
*
|
|
957
|
-
* @param {
|
|
958
|
-
* @returns {
|
|
1027
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} [methods]
|
|
1028
|
+
* @returns {Method[]}
|
|
959
1029
|
*/
|
|
960
1030
|
function getMethods(methods) {
|
|
961
1031
|
if (!methods) {
|
|
@@ -969,25 +1039,24 @@ function getMethods(methods) {
|
|
|
969
1039
|
.filter(isMethod);
|
|
970
1040
|
}
|
|
971
1041
|
|
|
1042
|
+
/** @import { Context, Handler, Method, Params } from '../main/types' */
|
|
1043
|
+
/** @import { Finder, FindItem } from '../Router.mjs' */
|
|
1044
|
+
|
|
972
1045
|
/**
|
|
973
1046
|
* @callback Match
|
|
974
1047
|
* @param {string[]} paths
|
|
975
|
-
* @returns {[
|
|
1048
|
+
* @returns {[Params, string[]] | undefined}
|
|
976
1049
|
*/
|
|
977
1050
|
|
|
978
|
-
/**
|
|
979
|
-
* @callback Binder
|
|
980
|
-
* @param {import('../main/types').Handler} handler
|
|
981
|
-
* @returns {() => void}
|
|
982
|
-
*/
|
|
1051
|
+
/** @typedef {(handler: Handler, ...handlers: Handler[]) => () => void} Binder */
|
|
983
1052
|
|
|
984
1053
|
/**
|
|
985
1054
|
* @typedef {object} Route
|
|
986
1055
|
* @property {Match} [match] 路径匹配
|
|
987
1056
|
* @property {null} [router]
|
|
988
1057
|
* @property {string} [plugin] 所属插件
|
|
989
|
-
* @property {
|
|
990
|
-
* @property {Set<
|
|
1058
|
+
* @property {Handler} handler 处理函数
|
|
1059
|
+
* @property {Set<Method>} methods 方法列表
|
|
991
1060
|
*/
|
|
992
1061
|
|
|
993
1062
|
/**
|
|
@@ -998,16 +1067,16 @@ function getMethods(methods) {
|
|
|
998
1067
|
|
|
999
1068
|
|
|
1000
1069
|
/**
|
|
1001
|
-
* @template {Router |
|
|
1070
|
+
* @template {Router | Finder} [T=ApiRouter]
|
|
1002
1071
|
* @callback RouteBinder
|
|
1003
1072
|
* @param {T} [router] 要注册的子路由或子路由的 Finder
|
|
1004
|
-
* @returns {T extends
|
|
1073
|
+
* @returns {T extends Finder ? Router : T}
|
|
1005
1074
|
*/
|
|
1006
1075
|
/**
|
|
1007
1076
|
*
|
|
1008
1077
|
* @param {(Route | RouterRoute)[]} routes
|
|
1009
|
-
* @param {string} path
|
|
1010
|
-
* @param {Router |
|
|
1078
|
+
* @param {string | [string[], any[]]} path
|
|
1079
|
+
* @param {Router | Finder} [r]
|
|
1011
1080
|
* @returns {Router}
|
|
1012
1081
|
*/
|
|
1013
1082
|
function bindRouter(routes, path, r) {
|
|
@@ -1022,18 +1091,18 @@ class ApiRouter extends Router {
|
|
|
1022
1091
|
#routes = [];
|
|
1023
1092
|
/**
|
|
1024
1093
|
* 添加子路由
|
|
1025
|
-
* @template {Router |
|
|
1094
|
+
* @template {Router | Finder} [T=ApiRouter]
|
|
1026
1095
|
* @overload
|
|
1027
1096
|
* @param {T} [router] 要注册的子路由或子路由的 Finder
|
|
1028
|
-
* @returns {T extends
|
|
1097
|
+
* @returns {T extends Finder ? Router : T}
|
|
1029
1098
|
*/
|
|
1030
1099
|
/**
|
|
1031
1100
|
* 添加子路由
|
|
1032
|
-
* @template {Router |
|
|
1101
|
+
* @template {Router | Finder} [T=ApiRouter]
|
|
1033
1102
|
* @overload
|
|
1034
1103
|
* @param {string} path 要注册的路径
|
|
1035
1104
|
* @param {T} [router] 要注册的子路由或子路由的 Finder
|
|
1036
|
-
* @returns {T extends
|
|
1105
|
+
* @returns {T extends Finder ? Router : T}
|
|
1037
1106
|
*/
|
|
1038
1107
|
/**
|
|
1039
1108
|
* 添加子路由
|
|
@@ -1050,12 +1119,11 @@ class ApiRouter extends Router {
|
|
|
1050
1119
|
route(...p) {
|
|
1051
1120
|
const [a] = p;
|
|
1052
1121
|
if (a && typeof a === 'object' && !(a instanceof Router)) {
|
|
1053
|
-
const path = String.raw(a, ...p.slice(1));
|
|
1054
1122
|
/**
|
|
1055
|
-
* @param {
|
|
1123
|
+
* @param { Finder | Router} [r];
|
|
1056
1124
|
* @returns {any}
|
|
1057
1125
|
*/
|
|
1058
|
-
return r => bindRouter(this.#routes,
|
|
1126
|
+
return r => bindRouter(this.#routes, [a, p.slice(1)], r);
|
|
1059
1127
|
}
|
|
1060
1128
|
const path = typeof a === 'string' ? a : '';
|
|
1061
1129
|
const r = typeof a === 'string' ? p[1] : a;
|
|
@@ -1063,10 +1131,10 @@ class ApiRouter extends Router {
|
|
|
1063
1131
|
}
|
|
1064
1132
|
/**
|
|
1065
1133
|
*
|
|
1066
|
-
* @param {
|
|
1134
|
+
* @param {Method} method
|
|
1067
1135
|
* @param {string[]} path
|
|
1068
|
-
* @param {
|
|
1069
|
-
* @returns {Iterable<
|
|
1136
|
+
* @param {Context} ctx
|
|
1137
|
+
* @returns {Iterable<FindItem>}
|
|
1070
1138
|
*/
|
|
1071
1139
|
*find(method, path, ctx) {
|
|
1072
1140
|
for (const route of Array.from(this.#routes)) {
|
|
@@ -1087,29 +1155,29 @@ class ApiRouter extends Router {
|
|
|
1087
1155
|
/**
|
|
1088
1156
|
* 注册处理函数
|
|
1089
1157
|
* @overload
|
|
1090
|
-
* @param {
|
|
1091
|
-
* @param {
|
|
1158
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} method 要注册的方法
|
|
1159
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1092
1160
|
* @returns {() => void}
|
|
1093
1161
|
*/
|
|
1094
1162
|
/**
|
|
1095
1163
|
* 注册处理函数
|
|
1096
1164
|
* @overload
|
|
1097
|
-
* @param {
|
|
1165
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} method 要注册的方法
|
|
1098
1166
|
* @param {string} path 要注册的路径
|
|
1099
|
-
* @param {
|
|
1167
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1100
1168
|
* @returns {() => void}
|
|
1101
1169
|
*/
|
|
1102
1170
|
/**
|
|
1103
1171
|
* 注册处理函数
|
|
1104
1172
|
* @overload
|
|
1105
|
-
* @param {
|
|
1173
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} method 要注册的方法
|
|
1106
1174
|
* @param {string} path 要注册的路径
|
|
1107
1175
|
* @returns {Binder}
|
|
1108
1176
|
*/
|
|
1109
1177
|
/**
|
|
1110
|
-
* @param {
|
|
1111
|
-
* @param {string|
|
|
1112
|
-
* @param {
|
|
1178
|
+
* @param {Method | Iterable<Method> | ArrayLike<Method>} methods
|
|
1179
|
+
* @param {string| Handler} [path]
|
|
1180
|
+
* @param {Handler} [handler]
|
|
1113
1181
|
* @returns {Binder | (() => void)}
|
|
1114
1182
|
*/
|
|
1115
1183
|
verb(methods, path, handler) {
|
|
@@ -1120,14 +1188,14 @@ class ApiRouter extends Router {
|
|
|
1120
1188
|
/**
|
|
1121
1189
|
* 注册 HTTP GET/POST/PUT/DELETE 处理函数
|
|
1122
1190
|
* @overload
|
|
1123
|
-
* @param {
|
|
1191
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1124
1192
|
* @returns {() => void}
|
|
1125
1193
|
*/
|
|
1126
1194
|
/**
|
|
1127
1195
|
* 注册处理函数
|
|
1128
1196
|
* @overload
|
|
1129
1197
|
* @param {string} path 要注册的路径
|
|
1130
|
-
* @param {
|
|
1198
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1131
1199
|
* @returns {() => void}
|
|
1132
1200
|
*/
|
|
1133
1201
|
/**
|
|
@@ -1153,14 +1221,14 @@ class ApiRouter extends Router {
|
|
|
1153
1221
|
/**
|
|
1154
1222
|
* 注册 HTTP GET 处理函数
|
|
1155
1223
|
* @overload
|
|
1156
|
-
* @param {
|
|
1224
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1157
1225
|
* @returns {() => void}
|
|
1158
1226
|
*/
|
|
1159
1227
|
/**
|
|
1160
1228
|
* 注册 HTTP GET 处理函数
|
|
1161
1229
|
* @overload
|
|
1162
1230
|
* @param {string} path 要注册的路径
|
|
1163
|
-
* @param {
|
|
1231
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1164
1232
|
* @returns {() => void}
|
|
1165
1233
|
*/
|
|
1166
1234
|
/**
|
|
@@ -1184,14 +1252,14 @@ class ApiRouter extends Router {
|
|
|
1184
1252
|
/**
|
|
1185
1253
|
* 注册 HTTP POST 处理函数
|
|
1186
1254
|
* @overload
|
|
1187
|
-
* @param {
|
|
1255
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1188
1256
|
* @returns {() => void}
|
|
1189
1257
|
*/
|
|
1190
1258
|
/**
|
|
1191
1259
|
* 注册 HTTP POST 处理函数
|
|
1192
1260
|
* @overload
|
|
1193
1261
|
* @param {string} path 要注册的路径
|
|
1194
|
-
* @param {
|
|
1262
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1195
1263
|
* @returns {() => void}
|
|
1196
1264
|
*/
|
|
1197
1265
|
/**
|
|
@@ -1215,14 +1283,14 @@ class ApiRouter extends Router {
|
|
|
1215
1283
|
/**
|
|
1216
1284
|
* 注册 HTTP PUT 处理函数
|
|
1217
1285
|
* @overload
|
|
1218
|
-
* @param {
|
|
1286
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1219
1287
|
* @returns {() => void}
|
|
1220
1288
|
*/
|
|
1221
1289
|
/**
|
|
1222
1290
|
* 注册 HTTP PUT 处理函数
|
|
1223
1291
|
* @overload
|
|
1224
1292
|
* @param {string} path 要注册的路径
|
|
1225
|
-
* @param {
|
|
1293
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1226
1294
|
* @returns {() => void}
|
|
1227
1295
|
*/
|
|
1228
1296
|
/**
|
|
@@ -1246,14 +1314,14 @@ class ApiRouter extends Router {
|
|
|
1246
1314
|
/**
|
|
1247
1315
|
* 注册 HTTP DELETE 处理函数
|
|
1248
1316
|
* @overload
|
|
1249
|
-
* @param {
|
|
1317
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1250
1318
|
* @returns {() => void}
|
|
1251
1319
|
*/
|
|
1252
1320
|
/**
|
|
1253
1321
|
* 注册 HTTP DELETE 处理函数
|
|
1254
1322
|
* @overload
|
|
1255
1323
|
* @param {string} path 要注册的路径
|
|
1256
|
-
* @param {
|
|
1324
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1257
1325
|
* @returns {() => void}
|
|
1258
1326
|
*/
|
|
1259
1327
|
/**
|
|
@@ -1277,14 +1345,14 @@ class ApiRouter extends Router {
|
|
|
1277
1345
|
/**
|
|
1278
1346
|
* 注册 HTTP HEAD 处理函数
|
|
1279
1347
|
* @overload
|
|
1280
|
-
* @param {
|
|
1348
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1281
1349
|
* @returns {() => void}
|
|
1282
1350
|
*/
|
|
1283
1351
|
/**
|
|
1284
1352
|
* 注册 HTTP HEAD 处理函数
|
|
1285
1353
|
* @overload
|
|
1286
1354
|
* @param {string} path 要注册的路径
|
|
1287
|
-
* @param {
|
|
1355
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1288
1356
|
* @returns {() => void}
|
|
1289
1357
|
*/
|
|
1290
1358
|
/**
|
|
@@ -1308,14 +1376,14 @@ class ApiRouter extends Router {
|
|
|
1308
1376
|
/**
|
|
1309
1377
|
* 注册 HTTP OPTIONS 处理函数
|
|
1310
1378
|
* @overload
|
|
1311
|
-
* @param {
|
|
1379
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1312
1380
|
* @returns {() => void}
|
|
1313
1381
|
*/
|
|
1314
1382
|
/**
|
|
1315
1383
|
* 注册 HTTP OPTIONS 处理函数
|
|
1316
1384
|
* @overload
|
|
1317
1385
|
* @param {string} path 要注册的路径
|
|
1318
|
-
* @param {
|
|
1386
|
+
* @param {Handler} handler 要注册的处理函数
|
|
1319
1387
|
* @returns {() => void}
|
|
1320
1388
|
*/
|
|
1321
1389
|
/**
|
|
@@ -1361,21 +1429,22 @@ function createFetch(run, notFound) {
|
|
|
1361
1429
|
};
|
|
1362
1430
|
}
|
|
1363
1431
|
|
|
1432
|
+
/** @import { Context, Handler, HandlerResult } from './main/types' */
|
|
1364
1433
|
/**
|
|
1365
1434
|
* @callback Onionskin
|
|
1366
|
-
* @param {
|
|
1367
|
-
* @param {() => Promise<
|
|
1368
|
-
* @returns {PromiseLike<
|
|
1435
|
+
* @param {Context} ctx
|
|
1436
|
+
* @param {() => Promise<HandlerResult>} next
|
|
1437
|
+
* @returns {PromiseLike<HandlerResult> | HandlerResult}
|
|
1369
1438
|
*/
|
|
1370
1439
|
|
|
1371
1440
|
const noop = () => {};
|
|
1372
1441
|
/**
|
|
1373
1442
|
*
|
|
1374
1443
|
* @param {...(Onionskin | Onionskin[])} handlers
|
|
1375
|
-
* @returns {
|
|
1444
|
+
* @returns {Handler}
|
|
1376
1445
|
*/
|
|
1377
1446
|
function onionskin(...handlers) {
|
|
1378
|
-
/** @type {
|
|
1447
|
+
/** @type {Handler} */
|
|
1379
1448
|
let handler = noop;
|
|
1380
1449
|
for (const os of handlers.flat()) {
|
|
1381
1450
|
const currentHandler = handler;
|
|
@@ -1384,4 +1453,40 @@ function onionskin(...handlers) {
|
|
|
1384
1453
|
return handler;
|
|
1385
1454
|
}
|
|
1386
1455
|
|
|
1387
|
-
|
|
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 };
|