@orkestrel/router 0.0.1 → 0.0.2
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/dist/src/browser/index.d.ts +283 -4
- package/dist/src/browser/index.js +4 -300
- package/dist/src/browser/index.js.map +1 -1
- package/dist/src/core/index.cjs +893 -0
- package/dist/src/core/index.cjs.map +1 -0
- package/dist/src/core/index.d.cts +1067 -0
- package/dist/src/core/index.d.ts +1067 -8
- package/dist/src/core/index.js +33 -175
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +4 -210
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/{helpers.d.ts → index.d.cts} +166 -127
- package/dist/src/server/index.d.ts +166 -2
- package/dist/src/server/index.js +207 -0
- package/dist/src/server/index.js.map +1 -0
- package/package.json +32 -19
- package/dist/src/browser/Navigator.d.ts +0 -62
- package/dist/src/browser/factories.d.ts +0 -33
- package/dist/src/browser/helpers.d.ts +0 -76
- package/dist/src/browser/types.d.ts +0 -101
- package/dist/src/core/DispatchGroup.d.ts +0 -32
- package/dist/src/core/Dispatcher.d.ts +0 -51
- package/dist/src/core/Group.d.ts +0 -30
- package/dist/src/core/Router.d.ts +0 -42
- package/dist/src/core/constants.d.ts +0 -60
- package/dist/src/core/factories.d.ts +0 -53
- package/dist/src/core/helpers.d.ts +0 -274
- package/dist/src/core/types.d.ts +0 -445
- package/dist/src/server/types.d.ts +0 -31
package/dist/src/core/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Emitter } from "@orkestrel/emitter";
|
|
2
|
+
import { isFunction, isString } from "@orkestrel/contract";
|
|
1
3
|
//#region src/core/constants.ts
|
|
2
4
|
/**
|
|
3
5
|
* The complete set of HTTP methods a {@link import('./types.js').Dispatcher}
|
|
@@ -410,189 +412,45 @@ function joinPaths(prefix, path) {
|
|
|
410
412
|
if (path === "") return prefix;
|
|
411
413
|
return `${prefix.endsWith("/") ? prefix.slice(0, -1) : prefix}${path.startsWith("/") ? path : `/${path}`}`;
|
|
412
414
|
}
|
|
413
|
-
//#endregion
|
|
414
|
-
//#region node_modules/@orkestrel/emitter/dist/src/core/index.js
|
|
415
415
|
/**
|
|
416
|
-
*
|
|
416
|
+
* Identity pass-through for a {@link RouteInput} that pins its `Path` generic
|
|
417
|
+
* to the LITERAL registration-site string, so `context.params` types
|
|
418
|
+
* correctly through {@link PathParams} without an explicit type argument.
|
|
417
419
|
*
|
|
418
420
|
* @remarks
|
|
419
|
-
*
|
|
420
|
-
*
|
|
421
|
-
*
|
|
422
|
-
*
|
|
423
|
-
*
|
|
424
|
-
*
|
|
425
|
-
*
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
* @
|
|
429
|
-
*
|
|
430
|
-
*
|
|
431
|
-
*
|
|
432
|
-
*
|
|
433
|
-
*
|
|
434
|
-
*
|
|
435
|
-
*
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
for (const key in object) collected.push(key);
|
|
440
|
-
return collected;
|
|
441
|
-
}
|
|
442
|
-
Object.freeze([
|
|
443
|
-
"null",
|
|
444
|
-
"boolean",
|
|
445
|
-
"object",
|
|
446
|
-
"array",
|
|
447
|
-
"number",
|
|
448
|
-
"integer",
|
|
449
|
-
"string"
|
|
450
|
-
]);
|
|
451
|
-
/** Determine whether a value is callable. */
|
|
452
|
-
function isFunction$1(value) {
|
|
453
|
-
return typeof value === "function";
|
|
454
|
-
}
|
|
455
|
-
/**
|
|
456
|
-
* A typed synchronous event emitter — the foundational observable primitive of
|
|
457
|
-
* the codebase (AGENTS §13). Stateful entities OWN one as a `#emitter` field and
|
|
458
|
-
* expose it through `readonly emitter`; they never inherit from it.
|
|
459
|
-
*
|
|
460
|
-
* @typeParam TMap - The event map: each event name to the argument tuple its
|
|
461
|
-
* listeners receive.
|
|
462
|
-
*
|
|
463
|
-
* @remarks
|
|
464
|
-
* - **Synchronous.** `emit` invokes listeners in registration order, in the
|
|
465
|
-
* current tick.
|
|
466
|
-
* - **Listener isolation.** A throwing listener never stops its siblings: every
|
|
467
|
-
* listener runs, and a throw is routed to the `error` handler
|
|
468
|
-
* ({@link EmitterOptions.error}) — never rethrown. Every throwing listener
|
|
469
|
-
* surfaces (not just the first), and with no `error` handler a throw is swallowed
|
|
470
|
-
* silently. The `error` handler runs inside its own try/catch, so a throwing
|
|
471
|
-
* error-handler is swallowed too (anti-recursion — it cannot escape or re-enter).
|
|
472
|
-
* - **Per-event storage.** Listeners live in a per-event `Set`, so every public
|
|
473
|
-
* method is precisely typed with no assertions.
|
|
474
|
-
* - **Destroyed → no-op.** After `destroy()`, `on` / `once` / `emit` do nothing
|
|
475
|
-
* and `destroyed` is `true`.
|
|
421
|
+
* A bare object literal handed straight to {@link import('./types.js').DispatcherInterface}'s
|
|
422
|
+
* `add` already infers `Path` as a literal at that call site — but the moment
|
|
423
|
+
* the object is built through an intermediate binding (a local `const route =
|
|
424
|
+
* { method, path, handler }`) TypeScript widens `path` to `string` unless the
|
|
425
|
+
* binding's own type is pinned. Wrapping the literal in `route(...)` supplies
|
|
426
|
+
* that pin: its `const Path extends string` type parameter infers the NARROW
|
|
427
|
+
* literal from the call, and the function returns its input completely
|
|
428
|
+
* unchanged (same reference, no cloning, no validation) — this is a
|
|
429
|
+
* compile-time typing aid only, not a construction step (contrast
|
|
430
|
+
* {@link import('./factories.js')} `create*` entity factories). A
|
|
431
|
+
* heterogeneous `RouteInput[]` built from several `route(...)` calls still
|
|
432
|
+
* widens each element's `Path` to `string` once collected into one array
|
|
433
|
+
* (§14) — the realistic ceiling this helper raises is PER-CALL typing at the
|
|
434
|
+
* registration site, not a stored, still-literal-typed record.
|
|
435
|
+
*
|
|
436
|
+
* @typeParam Path - The route path pattern literal (drives `context.params`
|
|
437
|
+
* via {@link PathParams})
|
|
438
|
+
* @typeParam TState - The consumer's opaque per-request state type
|
|
439
|
+
* @param input - The {@link RouteInput} to pass through unchanged
|
|
440
|
+
* @returns `input`, unchanged (same reference)
|
|
476
441
|
*
|
|
477
442
|
* @example
|
|
478
443
|
* ```ts
|
|
479
|
-
*
|
|
480
|
-
*
|
|
481
|
-
*
|
|
482
|
-
*
|
|
483
|
-
*
|
|
484
|
-
* const emitter = new Emitter<CounterEventMap>({
|
|
485
|
-
* on: { done: () => stop() },
|
|
486
|
-
* error: (error, event) => log(`listener for ${event} threw`, error),
|
|
444
|
+
* const input = route({
|
|
445
|
+
* method: 'GET',
|
|
446
|
+
* path: '/users/:id',
|
|
447
|
+
* handler: (_request, context) => new Response(context.params.id), // typed string
|
|
487
448
|
* })
|
|
488
|
-
*
|
|
489
|
-
* emitter.emit('tick', 1)
|
|
449
|
+
* dispatcher.add(input)
|
|
490
450
|
* ```
|
|
491
451
|
*/
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
#listeners = {};
|
|
495
|
-
#wrappers = {};
|
|
496
|
-
#error;
|
|
497
|
-
constructor(options) {
|
|
498
|
-
const error = options?.error;
|
|
499
|
-
this.#error = isFunction$1(error) ? error : void 0;
|
|
500
|
-
const hooks = options?.on;
|
|
501
|
-
if (hooks !== void 0) this.#wire(hooks);
|
|
502
|
-
}
|
|
503
|
-
get destroyed() {
|
|
504
|
-
return this.#destroyed;
|
|
505
|
-
}
|
|
506
|
-
on(event, handler) {
|
|
507
|
-
if (this.#destroyed) return;
|
|
508
|
-
(this.#listeners[event] ??= /* @__PURE__ */ new Set()).add(handler);
|
|
509
|
-
}
|
|
510
|
-
once(event, handler) {
|
|
511
|
-
if (this.#destroyed) return;
|
|
512
|
-
const pending = this.#wrappers[event] ??= /* @__PURE__ */ new Map();
|
|
513
|
-
const wrapper = (...args) => {
|
|
514
|
-
this.#listeners[event]?.delete(wrapper);
|
|
515
|
-
const wrappers = pending.get(handler);
|
|
516
|
-
wrappers?.delete(wrapper);
|
|
517
|
-
if (wrappers !== void 0 && wrappers.size === 0) pending.delete(handler);
|
|
518
|
-
handler(...args);
|
|
519
|
-
};
|
|
520
|
-
const wrappers = pending.get(handler) ?? /* @__PURE__ */ new Set();
|
|
521
|
-
wrappers.add(wrapper);
|
|
522
|
-
pending.set(handler, wrappers);
|
|
523
|
-
this.on(event, wrapper);
|
|
524
|
-
}
|
|
525
|
-
off(event, handler) {
|
|
526
|
-
const listeners = this.#listeners[event];
|
|
527
|
-
const wrappers = this.#wrappers[event];
|
|
528
|
-
const pending = wrappers?.get(handler);
|
|
529
|
-
if (pending !== void 0) {
|
|
530
|
-
for (const wrapper of pending) listeners?.delete(wrapper);
|
|
531
|
-
wrappers?.delete(handler);
|
|
532
|
-
}
|
|
533
|
-
listeners?.delete(handler);
|
|
534
|
-
}
|
|
535
|
-
emit(event, ...args) {
|
|
536
|
-
if (this.#destroyed) return;
|
|
537
|
-
const listeners = this.#listeners[event];
|
|
538
|
-
if (listeners === void 0) return;
|
|
539
|
-
for (const handler of [...listeners]) try {
|
|
540
|
-
handler(...args);
|
|
541
|
-
} catch (error) {
|
|
542
|
-
this.#surface(error, event);
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
count(event) {
|
|
546
|
-
if (event !== void 0) return this.#listeners[event]?.size ?? 0;
|
|
547
|
-
let total = 0;
|
|
548
|
-
for (const set of Object.values(this.#listeners)) total += set?.size ?? 0;
|
|
549
|
-
return total;
|
|
550
|
-
}
|
|
551
|
-
clear(event) {
|
|
552
|
-
if (event !== void 0) {
|
|
553
|
-
delete this.#listeners[event];
|
|
554
|
-
delete this.#wrappers[event];
|
|
555
|
-
return;
|
|
556
|
-
}
|
|
557
|
-
this.#listeners = {};
|
|
558
|
-
this.#wrappers = {};
|
|
559
|
-
}
|
|
560
|
-
destroy() {
|
|
561
|
-
this.#listeners = {};
|
|
562
|
-
this.#wrappers = {};
|
|
563
|
-
this.#error = void 0;
|
|
564
|
-
this.#destroyed = true;
|
|
565
|
-
}
|
|
566
|
-
#surface(error, event) {
|
|
567
|
-
const handler = this.#error;
|
|
568
|
-
if (handler === void 0) return;
|
|
569
|
-
try {
|
|
570
|
-
handler(error, String(event));
|
|
571
|
-
} catch {}
|
|
572
|
-
}
|
|
573
|
-
#wire(hooks) {
|
|
574
|
-
for (const event of extractKeys(hooks)) {
|
|
575
|
-
const handler = hooks[event];
|
|
576
|
-
if (isFunction$1(handler)) this.on(event, handler);
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
};
|
|
580
|
-
Object.freeze([
|
|
581
|
-
"null",
|
|
582
|
-
"boolean",
|
|
583
|
-
"object",
|
|
584
|
-
"array",
|
|
585
|
-
"number",
|
|
586
|
-
"integer",
|
|
587
|
-
"string"
|
|
588
|
-
]);
|
|
589
|
-
/** Determine whether a value is a string. */
|
|
590
|
-
function isString(value) {
|
|
591
|
-
return typeof value === "string";
|
|
592
|
-
}
|
|
593
|
-
/** Determine whether a value is callable. */
|
|
594
|
-
function isFunction(value) {
|
|
595
|
-
return typeof value === "function";
|
|
452
|
+
function route(input) {
|
|
453
|
+
return input;
|
|
596
454
|
}
|
|
597
455
|
//#endregion
|
|
598
456
|
//#region src/core/Group.ts
|
|
@@ -1009,6 +867,6 @@ function createDispatcher(options) {
|
|
|
1009
867
|
return new Dispatcher(options);
|
|
1010
868
|
}
|
|
1011
869
|
//#endregion
|
|
1012
|
-
export { DispatchGroup, Dispatcher, Group, METHODS, Router, TIER_LITERAL, TIER_PARAM, TIER_WILDCARD, canonicalizePath, classifySegment, compareSpecificity, compilePath, computeSpecificity, createDispatcher, createRouter, decodeParam, escapeRegExp, joinPaths, matchPath, parseMethod };
|
|
870
|
+
export { DispatchGroup, Dispatcher, Group, METHODS, Router, TIER_LITERAL, TIER_PARAM, TIER_WILDCARD, canonicalizePath, classifySegment, compareSpecificity, compilePath, computeSpecificity, createDispatcher, createRouter, decodeParam, escapeRegExp, joinPaths, matchPath, parseMethod, route };
|
|
1013
871
|
|
|
1014
872
|
//# sourceMappingURL=index.js.map
|