@pithyjs/router 0.1.0-beta.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.
Files changed (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +621 -0
  3. package/dist/index.d.ts +29 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +49 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/router/core/config.d.ts +22 -0
  8. package/dist/router/core/config.d.ts.map +1 -0
  9. package/dist/router/core/config.js +54 -0
  10. package/dist/router/core/config.js.map +1 -0
  11. package/dist/router/core/constants.d.ts +89 -0
  12. package/dist/router/core/constants.d.ts.map +1 -0
  13. package/dist/router/core/constants.js +95 -0
  14. package/dist/router/core/constants.js.map +1 -0
  15. package/dist/router/core/history.d.ts +54 -0
  16. package/dist/router/core/history.d.ts.map +1 -0
  17. package/dist/router/core/history.js +89 -0
  18. package/dist/router/core/history.js.map +1 -0
  19. package/dist/router/core/matcher.d.ts +43 -0
  20. package/dist/router/core/matcher.d.ts.map +1 -0
  21. package/dist/router/core/matcher.js +242 -0
  22. package/dist/router/core/matcher.js.map +1 -0
  23. package/dist/router/core/params.d.ts +88 -0
  24. package/dist/router/core/params.d.ts.map +1 -0
  25. package/dist/router/core/params.js +150 -0
  26. package/dist/router/core/params.js.map +1 -0
  27. package/dist/router/core/pipeline.d.ts +90 -0
  28. package/dist/router/core/pipeline.d.ts.map +1 -0
  29. package/dist/router/core/pipeline.js +323 -0
  30. package/dist/router/core/pipeline.js.map +1 -0
  31. package/dist/router/core/route-tree.d.ts +76 -0
  32. package/dist/router/core/route-tree.d.ts.map +1 -0
  33. package/dist/router/core/route-tree.js +143 -0
  34. package/dist/router/core/route-tree.js.map +1 -0
  35. package/dist/router/core/router.d.ts +229 -0
  36. package/dist/router/core/router.d.ts.map +1 -0
  37. package/dist/router/core/router.js +762 -0
  38. package/dist/router/core/router.js.map +1 -0
  39. package/dist/router/core/types.d.ts +387 -0
  40. package/dist/router/core/types.d.ts.map +1 -0
  41. package/dist/router/core/types.js +22 -0
  42. package/dist/router/core/types.js.map +1 -0
  43. package/dist/router/core/utils.d.ts +66 -0
  44. package/dist/router/core/utils.d.ts.map +1 -0
  45. package/dist/router/core/utils.js +152 -0
  46. package/dist/router/core/utils.js.map +1 -0
  47. package/dist/router/features/coordinator.d.ts +75 -0
  48. package/dist/router/features/coordinator.d.ts.map +1 -0
  49. package/dist/router/features/coordinator.js +203 -0
  50. package/dist/router/features/coordinator.js.map +1 -0
  51. package/dist/router/features/errors/error-codes.d.ts +107 -0
  52. package/dist/router/features/errors/error-codes.d.ts.map +1 -0
  53. package/dist/router/features/errors/error-codes.js +247 -0
  54. package/dist/router/features/errors/error-codes.js.map +1 -0
  55. package/dist/router/features/errors/error-resolution.d.ts +31 -0
  56. package/dist/router/features/errors/error-resolution.d.ts.map +1 -0
  57. package/dist/router/features/errors/error-resolution.js +47 -0
  58. package/dist/router/features/errors/error-resolution.js.map +1 -0
  59. package/dist/router/features/errors/error-types.d.ts +60 -0
  60. package/dist/router/features/errors/error-types.d.ts.map +1 -0
  61. package/dist/router/features/errors/error-types.js +57 -0
  62. package/dist/router/features/errors/error-types.js.map +1 -0
  63. package/dist/router/features/errors/global-error-fallback.d.ts +33 -0
  64. package/dist/router/features/errors/global-error-fallback.d.ts.map +1 -0
  65. package/dist/router/features/errors/global-error-fallback.js +182 -0
  66. package/dist/router/features/errors/global-error-fallback.js.map +1 -0
  67. package/dist/router/features/errors/index.d.ts +15 -0
  68. package/dist/router/features/errors/index.d.ts.map +1 -0
  69. package/dist/router/features/errors/index.js +18 -0
  70. package/dist/router/features/errors/index.js.map +1 -0
  71. package/dist/router/features/errors/router-errors.d.ts +44 -0
  72. package/dist/router/features/errors/router-errors.d.ts.map +1 -0
  73. package/dist/router/features/errors/router-errors.js +53 -0
  74. package/dist/router/features/errors/router-errors.js.map +1 -0
  75. package/dist/router/features/guards/engine.d.ts +40 -0
  76. package/dist/router/features/guards/engine.d.ts.map +1 -0
  77. package/dist/router/features/guards/engine.js +67 -0
  78. package/dist/router/features/guards/engine.js.map +1 -0
  79. package/dist/router/features/guards/index.d.ts +52 -0
  80. package/dist/router/features/guards/index.d.ts.map +1 -0
  81. package/dist/router/features/guards/index.js +95 -0
  82. package/dist/router/features/guards/index.js.map +1 -0
  83. package/dist/router/features/loaders/cache.d.ts +60 -0
  84. package/dist/router/features/loaders/cache.d.ts.map +1 -0
  85. package/dist/router/features/loaders/cache.js +80 -0
  86. package/dist/router/features/loaders/cache.js.map +1 -0
  87. package/dist/router/features/loaders/engine.d.ts +17 -0
  88. package/dist/router/features/loaders/engine.d.ts.map +1 -0
  89. package/dist/router/features/loaders/engine.js +27 -0
  90. package/dist/router/features/loaders/engine.js.map +1 -0
  91. package/dist/router/features/loaders/index.d.ts +49 -0
  92. package/dist/router/features/loaders/index.d.ts.map +1 -0
  93. package/dist/router/features/loaders/index.js +112 -0
  94. package/dist/router/features/loaders/index.js.map +1 -0
  95. package/dist/router/features/loading-ui-manager.d.ts +69 -0
  96. package/dist/router/features/loading-ui-manager.d.ts.map +1 -0
  97. package/dist/router/features/loading-ui-manager.js +209 -0
  98. package/dist/router/features/loading-ui-manager.js.map +1 -0
  99. package/dist/router/features/module-loader.d.ts +50 -0
  100. package/dist/router/features/module-loader.d.ts.map +1 -0
  101. package/dist/router/features/module-loader.js +121 -0
  102. package/dist/router/features/module-loader.js.map +1 -0
  103. package/dist/router/features/outlet/errors.d.ts +24 -0
  104. package/dist/router/features/outlet/errors.d.ts.map +1 -0
  105. package/dist/router/features/outlet/errors.js +96 -0
  106. package/dist/router/features/outlet/errors.js.map +1 -0
  107. package/dist/router/features/outlet/index.d.ts +45 -0
  108. package/dist/router/features/outlet/index.d.ts.map +1 -0
  109. package/dist/router/features/outlet/index.js +95 -0
  110. package/dist/router/features/outlet/index.js.map +1 -0
  111. package/dist/router/features/outlet/mount.d.ts +38 -0
  112. package/dist/router/features/outlet/mount.d.ts.map +1 -0
  113. package/dist/router/features/outlet/mount.js +301 -0
  114. package/dist/router/features/outlet/mount.js.map +1 -0
  115. package/dist/router/features/outlet/segment-chain.d.ts +16 -0
  116. package/dist/router/features/outlet/segment-chain.d.ts.map +1 -0
  117. package/dist/router/features/outlet/segment-chain.js +62 -0
  118. package/dist/router/features/outlet/segment-chain.js.map +1 -0
  119. package/dist/router/features/prefetch/index.d.ts +97 -0
  120. package/dist/router/features/prefetch/index.d.ts.map +1 -0
  121. package/dist/router/features/prefetch/index.js +345 -0
  122. package/dist/router/features/prefetch/index.js.map +1 -0
  123. package/dist/router/features/ux/focus.d.ts +62 -0
  124. package/dist/router/features/ux/focus.d.ts.map +1 -0
  125. package/dist/router/features/ux/focus.js +136 -0
  126. package/dist/router/features/ux/focus.js.map +1 -0
  127. package/dist/router/features/ux/live-region.d.ts +81 -0
  128. package/dist/router/features/ux/live-region.d.ts.map +1 -0
  129. package/dist/router/features/ux/live-region.js +166 -0
  130. package/dist/router/features/ux/live-region.js.map +1 -0
  131. package/dist/router/features/ux/scroll-focus.d.ts +105 -0
  132. package/dist/router/features/ux/scroll-focus.d.ts.map +1 -0
  133. package/dist/router/features/ux/scroll-focus.js +111 -0
  134. package/dist/router/features/ux/scroll-focus.js.map +1 -0
  135. package/dist/router/features/ux/scroll.d.ts +71 -0
  136. package/dist/router/features/ux/scroll.d.ts.map +1 -0
  137. package/dist/router/features/ux/scroll.js +137 -0
  138. package/dist/router/features/ux/scroll.js.map +1 -0
  139. package/dist/router/features/ux/transitions.d.ts +120 -0
  140. package/dist/router/features/ux/transitions.d.ts.map +1 -0
  141. package/dist/router/features/ux/transitions.js +235 -0
  142. package/dist/router/features/ux/transitions.js.map +1 -0
  143. package/dist/router/integration/directive-binder.d.ts +20 -0
  144. package/dist/router/integration/directive-binder.d.ts.map +1 -0
  145. package/dist/router/integration/directive-binder.js +139 -0
  146. package/dist/router/integration/directive-binder.js.map +1 -0
  147. package/dist/router/integration/directives.d.ts +42 -0
  148. package/dist/router/integration/directives.d.ts.map +1 -0
  149. package/dist/router/integration/directives.js +109 -0
  150. package/dist/router/integration/directives.js.map +1 -0
  151. package/dist/router/integration/history-adapter.d.ts +76 -0
  152. package/dist/router/integration/history-adapter.d.ts.map +1 -0
  153. package/dist/router/integration/history-adapter.js +157 -0
  154. package/dist/router/integration/history-adapter.js.map +1 -0
  155. package/dist/router/integration/hmr.d.ts +83 -0
  156. package/dist/router/integration/hmr.d.ts.map +1 -0
  157. package/dist/router/integration/hmr.js +160 -0
  158. package/dist/router/integration/hmr.js.map +1 -0
  159. package/dist/router/integration/link-interceptor.d.ts +49 -0
  160. package/dist/router/integration/link-interceptor.d.ts.map +1 -0
  161. package/dist/router/integration/link-interceptor.js +94 -0
  162. package/dist/router/integration/link-interceptor.js.map +1 -0
  163. package/package.json +47 -0
@@ -0,0 +1,152 @@
1
+ /** @codex
2
+ {
3
+ "id": "pithy.router.core.utils",
4
+ "title": "Router Utility Functions",
5
+ "category": "runtime"
6
+ }
7
+ */
8
+ /**
9
+ * Extract HTMLElement from various value types
10
+ * Supports: HTMLElement, DocumentFragment, { el: ... }, HTML string
11
+ *
12
+ * @param value - Value that may contain an element
13
+ * @returns HTMLElement or null if extraction failed
14
+ *
15
+ * @codexApi {"parent":"pithy.router.core.utils","name":"extractElement","stability":"stable","signature":"function extractElement(value: any): HTMLElement | null"}
16
+ */
17
+ export function extractElement(value) {
18
+ if (!value)
19
+ return null;
20
+ const wrapFragment = (frag) => {
21
+ const wrapper = document.createElement('div');
22
+ // clone so callers can reuse their fragment
23
+ wrapper.appendChild(frag.cloneNode(true));
24
+ return wrapper;
25
+ };
26
+ // Direct HTMLElement
27
+ if (value instanceof HTMLElement) {
28
+ return value;
29
+ }
30
+ // Direct DocumentFragment
31
+ if (value instanceof DocumentFragment) {
32
+ return wrapFragment(value);
33
+ }
34
+ // { el: ... } shape
35
+ if (typeof value === 'object' && 'el' in value && value.el) {
36
+ const el = value.el;
37
+ if (el instanceof HTMLElement)
38
+ return el;
39
+ if (el instanceof DocumentFragment)
40
+ return wrapFragment(el);
41
+ }
42
+ // HTML string
43
+ if (typeof value === 'string') {
44
+ const wrapper = document.createElement('div');
45
+ wrapper.innerHTML = value;
46
+ return wrapper;
47
+ }
48
+ return null;
49
+ }
50
+ /**
51
+ * Generate a CSS selector for an element
52
+ * Used for scroll position restoration
53
+ *
54
+ * Priority:
55
+ * 1. data-remember-scroll-id attribute
56
+ * 2. element ID (#id)
57
+ * 3. data-remember-scroll attribute value
58
+ * 4. fallback to [data-remember-scroll]
59
+ *
60
+ * @param el - The element to generate a selector for
61
+ * @returns CSS selector string
62
+ *
63
+ * @codexApi {"parent":"pithy.router.core.utils","name":"selectorFor","stability":"stable","signature":"function selectorFor(el: HTMLElement): string"}
64
+ */
65
+ export function selectorFor(el) {
66
+ return (el.getAttribute('data-remember-scroll-id') ||
67
+ (el.id && `#${CSS.escape(el.id)}`) ||
68
+ (el.dataset.rememberScroll &&
69
+ `[data-remember-scroll="${el.dataset.rememberScroll}"]`) ||
70
+ '[data-remember-scroll]');
71
+ }
72
+ /**
73
+ * Combine multiple abort signals into one
74
+ * Returns a signal that aborts when any of the input signals abort
75
+ *
76
+ * @param signals - Array of AbortSignals to combine
77
+ * @returns Combined AbortSignal
78
+ *
79
+ * @codexApi {"parent":"pithy.router.core.utils","name":"combineAbortSignals","stability":"stable","signature":"function combineAbortSignals(signals: AbortSignal[]): AbortSignal"}
80
+ */
81
+ export function combineAbortSignals(signals) {
82
+ const controller = new AbortController();
83
+ for (const signal of signals) {
84
+ if (signal.aborted) {
85
+ controller.abort();
86
+ break;
87
+ }
88
+ signal.addEventListener('abort', () => {
89
+ controller.abort();
90
+ }, { once: true });
91
+ }
92
+ return controller.signal;
93
+ }
94
+ /**
95
+ * Check if a mouse event should be handled for navigation
96
+ * Filters out modified clicks (ctrl, meta, shift, alt) and non-left clicks
97
+ *
98
+ * @param event - MouseEvent to check
99
+ * @returns true if the event should trigger navigation
100
+ *
101
+ * @codexApi {"parent":"pithy.router.core.utils","name":"isNavigationClick","stability":"stable","signature":"function isNavigationClick(event: MouseEvent): boolean"}
102
+ */
103
+ export function isNavigationClick(event) {
104
+ // Only left clicks without modifier keys
105
+ return (event.button === 0 &&
106
+ !event.metaKey &&
107
+ !event.ctrlKey &&
108
+ !event.shiftKey &&
109
+ !event.altKey);
110
+ }
111
+ /**
112
+ * Check if an anchor element should be intercepted for client-side navigation
113
+ * Returns null if the link should not be intercepted (let browser handle)
114
+ * Returns the normalized href if it should be intercepted
115
+ *
116
+ * @param anchor - Anchor element to check
117
+ * @param basePath - Optional base path to strip from URLs
118
+ * @returns Normalized href string or null
119
+ *
120
+ * @codexApi {"parent":"pithy.router.core.utils","name":"shouldInterceptLink","stability":"stable","signature":"function shouldInterceptLink(anchor: HTMLAnchorElement, basePath?: string): string | null"}
121
+ */
122
+ export function shouldInterceptLink(anchor, basePath) {
123
+ // Check target attribute
124
+ if (anchor.target && anchor.target !== '_self')
125
+ return null;
126
+ // Check download attribute
127
+ if (anchor.hasAttribute('download'))
128
+ return null;
129
+ // Get raw href
130
+ const rawHref = anchor.getAttribute('href');
131
+ if (!rawHref || rawHref.startsWith('#'))
132
+ return null;
133
+ // Parse and validate URL
134
+ let url;
135
+ try {
136
+ url = new URL(rawHref, window.location.origin);
137
+ }
138
+ catch {
139
+ return null; // Invalid URL, let browser handle
140
+ }
141
+ // Check if same-origin
142
+ if (url.origin !== window.location.origin)
143
+ return null;
144
+ // Normalize path by stripping base path if provided
145
+ let pathname = url.pathname;
146
+ if (basePath) {
147
+ pathname = pathname.replace(new RegExp(`^${basePath}`), '');
148
+ }
149
+ // Return full href including search and hash
150
+ return pathname + url.search + url.hash;
151
+ }
152
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/router/core/utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ /** @codex
2
+ {
3
+ "id": "pithy.router.features.coordinator",
4
+ "title": "Feature Coordinator - Orchestrates Guards, Loaders, Loading UI, and UX Features",
5
+ "category": "runtime"
6
+ }
7
+ */
8
+ import { type RouteNode, type RouteMatch, type NavigationId, type RouterConfig, type GuardContext as BaseGuardContext, type LoaderContext as BaseLoaderContext, type GuardExecutionResult, type ResourceState } from '../core/types';
9
+ import { type GuardFunction } from './guards';
10
+ import { LoadingUIManager } from './loading-ui-manager';
11
+ export type GuardContext = BaseGuardContext;
12
+ /**
13
+ * Router state updates type
14
+ * Partial type to avoid circular dependency with RouterState from router.ts
15
+ */
16
+ export interface RouterStateUpdates {
17
+ loaderData?: ResourceState;
18
+ }
19
+ /**
20
+ * Loader context for loader execution (extends base with router state update)
21
+ */
22
+ export interface LoaderContext extends BaseLoaderContext {
23
+ updateRouterState?: (updates: RouterStateUpdates) => void;
24
+ }
25
+ /**
26
+ * Feature Coordinator
27
+ * Orchestrates guards, loaders, loading UI, scroll, focus, HMR, and history
28
+ *
29
+ * @codexApi {"parent":"pithy.router.features.coordinator","name":"FeatureCoordinator","stability":"stable","signature":"class FeatureCoordinator"}
30
+ */
31
+ export declare class FeatureCoordinator {
32
+ private guardManager;
33
+ private loadingUI;
34
+ constructor(_config: RouterConfig);
35
+ /**
36
+ * Get the loading UI manager
37
+ * Allows external access for router to set mounted element
38
+ */
39
+ getLoadingUI(): LoadingUIManager;
40
+ /**
41
+ * Load guards for a specific route pattern
42
+ * Dynamically imports the route config and extracts guards
43
+ *
44
+ * @codexApi {"parent":"pithy.router.features.coordinator","name":"loadGuards","stability":"stable","signature":"async loadGuards(pattern: string, routes: RouteNode[]): Promise<GuardFunction[]>"}
45
+ */
46
+ loadGuards(pattern: string, routes: RouteNode[]): Promise<GuardFunction[]>;
47
+ /**
48
+ * Execute guards for a route
49
+ * Returns guard result with allowed status and optional redirect
50
+ *
51
+ * @codexApi {"parent":"pithy.router.features.coordinator","name":"executeGuards","stability":"stable","signature":"async executeGuards(guards: GuardFunction[], context: GuardContext): Promise<GuardExecutionResult>"}
52
+ */
53
+ executeGuards(guards: GuardFunction[], context: GuardContext): Promise<GuardExecutionResult>;
54
+ /**
55
+ * Execute loaders for a route with caching, error handling, and state updates
56
+ * This is the COMPLETE implementation that handles everything
57
+ *
58
+ * @codexApi {"parent":"pithy.router.features.coordinator","name":"executeLoaders","stability":"stable","signature":"async executeLoaders(pattern: string, context: LoaderContext, routes: RouteNode[]): Promise<boolean>"}
59
+ */
60
+ executeLoaders(pattern: string, context: LoaderContext, routes: RouteNode[]): Promise<boolean>;
61
+ /**
62
+ * Show loading UI based on policy and route configuration
63
+ * Encapsulates the loading policy logic (replace vs overlay) and checks if route has loader
64
+ *
65
+ * @codexApi {"parent":"pithy.router.features.coordinator","name":"showLoadingUI","stability":"stable","signature":"async showLoadingUI(route: RouteNode | undefined, match: RouteMatch, navId: NavigationId, mountedElement: HTMLElement | null, loadingPolicy: string, routes: RouteNode[]): Promise<void>"}
66
+ */
67
+ showLoadingUI(route: RouteNode | undefined, match: RouteMatch, navId: NavigationId, mountedElement: HTMLElement | null, loadingPolicy: string, routes: RouteNode[]): Promise<void>;
68
+ /**
69
+ * Clear all loading UI
70
+ *
71
+ * @codexApi {"parent":"pithy.router.features.coordinator","name":"clearLoadingUI","stability":"stable","signature":"clearLoadingUI(): void"}
72
+ */
73
+ clearLoadingUI(): void;
74
+ }
75
+ //# sourceMappingURL=coordinator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinator.d.ts","sourceRoot":"","sources":["../../../src/router/features/coordinator.ts"],"names":[],"mappings":"AAAA;;;;;;EAME;AAEF,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,YAAY,EAEjB,KAAK,YAAY,IAAI,gBAAgB,EACrC,KAAK,aAAa,IAAI,iBAAiB,EACvC,KAAK,oBAAoB,EACzB,KAAK,aAAa,EACnB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAM5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AASxD,MAAM,MAAM,YAAY,GAAG,gBAAgB,CAAC;AAE5C;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,aAAa,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,aAAc,SAAQ,iBAAiB;IACtD,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC3D;AAED;;;;;GAKG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,SAAS,CAAmB;gBAExB,OAAO,EAAE,YAAY;IAKjC;;;OAGG;IACH,YAAY,IAAI,gBAAgB;IAIhC;;;;;OAKG;IACG,UAAU,CACd,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,SAAS,EAAE,GAClB,OAAO,CAAC,aAAa,EAAE,CAAC;IA4B3B;;;;;OAKG;IACG,aAAa,CACjB,MAAM,EAAE,aAAa,EAAE,EACvB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,oBAAoB,CAAC;IAIhC;;;;;OAKG;IACG,cAAc,CAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,SAAS,EAAE,GAClB,OAAO,CAAC,OAAO,CAAC;IAqInB;;;;;OAKG;IACG,aAAa,CACjB,KAAK,EAAE,SAAS,GAAG,SAAS,EAC5B,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,YAAY,EACnB,cAAc,EAAE,WAAW,GAAG,IAAI,EAClC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,SAAS,EAAE,GAClB,OAAO,CAAC,IAAI,CAAC;IAwBhB;;;;OAIG;IACH,cAAc,IAAI,IAAI;CAGvB"}
@@ -0,0 +1,203 @@
1
+ /** @codex
2
+ {
3
+ "id": "pithy.router.features.coordinator",
4
+ "title": "Feature Coordinator - Orchestrates Guards, Loaders, Loading UI, and UX Features",
5
+ "category": "runtime"
6
+ }
7
+ */
8
+ import { LOADER_FAILED, } from '../core/types';
9
+ import { LOADER_DEFAULTS } from '../core/constants';
10
+ import { GuardManager } from './guards';
11
+ import { executeRouteLoader, } from './loaders';
12
+ import { LoadingUIManager } from './loading-ui-manager';
13
+ import { RouterError, RouterErrorCode, setRouteError, clearRouteError, } from './errors';
14
+ /**
15
+ * Feature Coordinator
16
+ * Orchestrates guards, loaders, loading UI, scroll, focus, HMR, and history
17
+ *
18
+ * @codexApi {"parent":"pithy.router.features.coordinator","name":"FeatureCoordinator","stability":"stable","signature":"class FeatureCoordinator"}
19
+ */
20
+ export class FeatureCoordinator {
21
+ constructor(_config) {
22
+ this.guardManager = new GuardManager();
23
+ this.loadingUI = new LoadingUIManager();
24
+ }
25
+ /**
26
+ * Get the loading UI manager
27
+ * Allows external access for router to set mounted element
28
+ */
29
+ getLoadingUI() {
30
+ return this.loadingUI;
31
+ }
32
+ /**
33
+ * Load guards for a specific route pattern
34
+ * Dynamically imports the route config and extracts guards
35
+ *
36
+ * @codexApi {"parent":"pithy.router.features.coordinator","name":"loadGuards","stability":"stable","signature":"async loadGuards(pattern: string, routes: RouteNode[]): Promise<GuardFunction[]>"}
37
+ */
38
+ async loadGuards(pattern, routes) {
39
+ // Find the route node for this pattern
40
+ const route = routes.find(r => r.pattern === pattern);
41
+ if (!route || !route.imports.config) {
42
+ return []; // No config file, no guards
43
+ }
44
+ try {
45
+ // Dynamically import the route config
46
+ const configModule = await route.imports.config();
47
+ // Extract guards from the config module
48
+ if (configModule &&
49
+ configModule.guards &&
50
+ Array.isArray(configModule.guards)) {
51
+ return configModule.guards;
52
+ }
53
+ return [];
54
+ }
55
+ catch (error) {
56
+ console.error(`[Router] Failed to load guards for ${pattern}:`, error);
57
+ return [];
58
+ }
59
+ }
60
+ /**
61
+ * Execute guards for a route
62
+ * Returns guard result with allowed status and optional redirect
63
+ *
64
+ * @codexApi {"parent":"pithy.router.features.coordinator","name":"executeGuards","stability":"stable","signature":"async executeGuards(guards: GuardFunction[], context: GuardContext): Promise<GuardExecutionResult>"}
65
+ */
66
+ async executeGuards(guards, context) {
67
+ return this.guardManager.executeGuards(guards, context);
68
+ }
69
+ /**
70
+ * Execute loaders for a route with caching, error handling, and state updates
71
+ * This is the COMPLETE implementation that handles everything
72
+ *
73
+ * @codexApi {"parent":"pithy.router.features.coordinator","name":"executeLoaders","stability":"stable","signature":"async executeLoaders(pattern: string, context: LoaderContext, routes: RouteNode[]): Promise<boolean>"}
74
+ */
75
+ async executeLoaders(pattern, context, routes) {
76
+ const route = routes.find(r => r.pattern === pattern);
77
+ if (!route || !route.imports.loader) {
78
+ return true; // No loader file = success (nothing to fail)
79
+ }
80
+ try {
81
+ // Dynamically import the loader module
82
+ const loaderModule = await route.imports.loader();
83
+ // Extract loader function from the module
84
+ const loaderExport = loaderModule.loader || loaderModule.default;
85
+ if (typeof loaderExport !== 'function') {
86
+ return true; // No valid loader = success (nothing to fail)
87
+ }
88
+ const loaderFunction = loaderExport;
89
+ // Load route config to get cache options
90
+ let cacheOptions = {
91
+ strategy: 'swr',
92
+ ttl: LOADER_DEFAULTS.CACHE_TTL,
93
+ };
94
+ if (route.imports.config) {
95
+ try {
96
+ const configModule = await route.imports.config();
97
+ const routeCache = configModule?.cache;
98
+ if (routeCache && typeof routeCache === 'object') {
99
+ const cache = routeCache;
100
+ // Merge route cache config with defaults
101
+ cacheOptions = {
102
+ strategy: cache.strategy || cacheOptions.strategy,
103
+ ttl: cache.ttl || cacheOptions.ttl,
104
+ };
105
+ }
106
+ }
107
+ catch {
108
+ // Use defaults if config loading fails
109
+ }
110
+ }
111
+ // Execute the loader with caching and error handling
112
+ try {
113
+ const result = await executeRouteLoader(route.id, loaderFunction, {
114
+ params: context.params,
115
+ query: context.query,
116
+ signal: context.signal,
117
+ navId: context.navId,
118
+ }, cacheOptions);
119
+ // Don't treat abort as error
120
+ if (context.signal.aborted) {
121
+ return false;
122
+ }
123
+ // Check for LOADER_FAILED sentinel
124
+ if (result === LOADER_FAILED) {
125
+ const err = new RouterError('Loader failed', {
126
+ navId: String(context.navId),
127
+ routeId: route.id,
128
+ parentRouteId: undefined,
129
+ routePath: route.pattern,
130
+ ts: Date.now(),
131
+ }, undefined, RouterErrorCode.LOADER_FAILED_SENTINEL);
132
+ setRouteError(route.id, err);
133
+ return false;
134
+ }
135
+ // Success: clear any previous error
136
+ clearRouteError(route.id);
137
+ // Update router state with the loaded data (if callback provided)
138
+ if (context.updateRouterState) {
139
+ context.updateRouterState({
140
+ loaderData: {
141
+ status: 'ready',
142
+ data: result,
143
+ navId: context.navId,
144
+ loadedAt: Date.now(),
145
+ },
146
+ });
147
+ }
148
+ return true;
149
+ }
150
+ catch (cause) {
151
+ // Don't treat abort as error
152
+ if (context.signal.aborted) {
153
+ return false;
154
+ }
155
+ console.error('[Router] Loader failed:', cause);
156
+ // Create and set error
157
+ const err = cause instanceof RouterError
158
+ ? cause
159
+ : new RouterError(cause?.message ?? 'Loader failed', {
160
+ navId: String(context.navId),
161
+ routeId: route.id,
162
+ parentRouteId: undefined,
163
+ routePath: route.pattern,
164
+ ts: Date.now(),
165
+ }, cause, RouterErrorCode.LOADER_EXECUTION_ERROR);
166
+ setRouteError(route.id, err);
167
+ return false;
168
+ }
169
+ }
170
+ catch (error) {
171
+ console.error('[Router] Failed to load loader module:', error);
172
+ return false;
173
+ }
174
+ }
175
+ /**
176
+ * Show loading UI based on policy and route configuration
177
+ * Encapsulates the loading policy logic (replace vs overlay) and checks if route has loader
178
+ *
179
+ * @codexApi {"parent":"pithy.router.features.coordinator","name":"showLoadingUI","stability":"stable","signature":"async showLoadingUI(route: RouteNode | undefined, match: RouteMatch, navId: NavigationId, mountedElement: HTMLElement | null, loadingPolicy: string, routes: RouteNode[]): Promise<void>"}
180
+ */
181
+ async showLoadingUI(route, match, navId, mountedElement, loadingPolicy, routes) {
182
+ if (!mountedElement)
183
+ return;
184
+ const hasLoader = !!route?.imports.loader;
185
+ if (hasLoader) {
186
+ if (loadingPolicy === 'replace') {
187
+ await this.loadingUI.showAtomic(match.pattern, navId, mountedElement, routes);
188
+ }
189
+ else if (loadingPolicy === 'overlay') {
190
+ await this.loadingUI.showCustomOverlay(match.pattern, navId, mountedElement, routes);
191
+ }
192
+ }
193
+ }
194
+ /**
195
+ * Clear all loading UI
196
+ *
197
+ * @codexApi {"parent":"pithy.router.features.coordinator","name":"clearLoadingUI","stability":"stable","signature":"clearLoadingUI(): void"}
198
+ */
199
+ clearLoadingUI() {
200
+ this.loadingUI.clearAll();
201
+ }
202
+ }
203
+ //# sourceMappingURL=coordinator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinator.js","sourceRoot":"","sources":["../../../src/router/features/coordinator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,107 @@
1
+ /** @codex
2
+ {
3
+ "id": "pithy.router.error-codes",
4
+ "title": "Router Error Code Taxonomy",
5
+ "category": "types"
6
+ }
7
+ */
8
+ /** @codexApi {"parent":"pithy.router.error-codes","name":"RouterErrorCode","stability":"stable","signature":"enum RouterErrorCode"} */
9
+ /**
10
+ * Canonical error codes for router errors
11
+ * Provides deterministic error categorization and handling
12
+ */
13
+ export declare enum RouterErrorCode {
14
+ /** Loader function threw an error */
15
+ LOADER_EXECUTION_ERROR = "LOADER_EXECUTION_ERROR",
16
+ /** Loader timed out */
17
+ LOADER_TIMEOUT = "LOADER_TIMEOUT",
18
+ /** Loader was aborted/cancelled */
19
+ LOADER_ABORTED = "LOADER_ABORTED",
20
+ /** Loader returned LOADER_FAILED sentinel */
21
+ LOADER_FAILED_SENTINEL = "LOADER_FAILED_SENTINEL",
22
+ /** Guard function threw an error */
23
+ GUARD_EXECUTION_ERROR = "GUARD_EXECUTION_ERROR",
24
+ /** Guard timed out */
25
+ GUARD_TIMEOUT = "GUARD_TIMEOUT",
26
+ /** Guard was aborted/cancelled */
27
+ GUARD_ABORTED = "GUARD_ABORTED",
28
+ /** Guard denied navigation (returned false) */
29
+ GUARD_DENIED = "GUARD_DENIED",
30
+ /** Component factory function threw error */
31
+ COMPONENT_FACTORY_ERROR = "COMPONENT_FACTORY_ERROR",
32
+ /** Component render threw error */
33
+ COMPONENT_RENDER_ERROR = "COMPONENT_RENDER_ERROR",
34
+ /** Component module failed to load */
35
+ COMPONENT_LOAD_ERROR = "COMPONENT_LOAD_ERROR",
36
+ /** Component lifecycle hook threw error */
37
+ COMPONENT_LIFECYCLE_ERROR = "COMPONENT_LIFECYCLE_ERROR",
38
+ /** Route not found for path */
39
+ ROUTE_NOT_FOUND = "ROUTE_NOT_FOUND",
40
+ /** Navigation was aborted */
41
+ NAVIGATION_ABORTED = "NAVIGATION_ABORTED",
42
+ /** Navigation was superseded by another navigation */
43
+ NAVIGATION_SUPERSEDED = "NAVIGATION_SUPERSEDED",
44
+ /** Circular redirect detected */
45
+ CIRCULAR_REDIRECT = "CIRCULAR_REDIRECT",
46
+ /** Error boundary component failed to load */
47
+ ERROR_BOUNDARY_LOAD_ERROR = "ERROR_BOUNDARY_LOAD_ERROR",
48
+ /** Error boundary component threw error during render */
49
+ ERROR_BOUNDARY_RENDER_ERROR = "ERROR_BOUNDARY_RENDER_ERROR",
50
+ /** Unknown error with no specific categorization */
51
+ UNKNOWN_ERROR = "UNKNOWN_ERROR"
52
+ }
53
+ /** @codexApi {"parent":"pithy.router.error-codes","name":"ErrorSeverity","stability":"stable","signature":"enum ErrorSeverity"} */
54
+ /**
55
+ * Error severity levels for prioritization and handling
56
+ */
57
+ export declare enum ErrorSeverity {
58
+ /** Critical error - requires immediate attention, blocks navigation */
59
+ CRITICAL = "critical",
60
+ /** Error - navigation failed but recoverable */
61
+ ERROR = "error",
62
+ /** Warning - operation completed with issues */
63
+ WARNING = "warning",
64
+ /** Info - informational message about navigation state */
65
+ INFO = "info"
66
+ }
67
+ /** @codexApi {"parent":"pithy.router.error-codes","name":"ErrorRecoveryStrategy","stability":"stable","signature":"enum ErrorRecoveryStrategy"} */
68
+ /**
69
+ * Error recovery strategies for different error types
70
+ */
71
+ export declare enum ErrorRecoveryStrategy {
72
+ /** Show error UI with retry button */
73
+ SHOW_ERROR_UI = "show-error-ui",
74
+ /** Redirect to fallback route */
75
+ REDIRECT_FALLBACK = "redirect-fallback",
76
+ /** Silent fail - log error but don't show UI */
77
+ SILENT_FAIL = "silent-fail",
78
+ /** Retry operation automatically */
79
+ AUTO_RETRY = "auto-retry",
80
+ /** Throw to parent error boundary */
81
+ BUBBLE_UP = "bubble-up"
82
+ }
83
+ /**
84
+ * Metadata for each error code including severity and recovery strategy
85
+ */
86
+ interface ErrorCodeMetadata {
87
+ code: RouterErrorCode;
88
+ severity: ErrorSeverity;
89
+ defaultStrategy: ErrorRecoveryStrategy;
90
+ userMessage: string;
91
+ retryable: boolean;
92
+ }
93
+ /** @codexApi {"parent":"pithy.router.error-codes","name":"ERROR_TAXONOMY","stability":"stable","signature":"Record<RouterErrorCode, ErrorCodeMetadata>"} */
94
+ /**
95
+ * Complete error taxonomy with metadata for each error code
96
+ * Maps error codes to their handling characteristics
97
+ */
98
+ export declare const ERROR_TAXONOMY: Record<RouterErrorCode, ErrorCodeMetadata>;
99
+ /** @codexApi {"parent":"pithy.router.error-codes","name":"getErrorMetadata","stability":"stable","signature":"(code: RouterErrorCode) => ErrorCodeMetadata"} */
100
+ /**
101
+ * Get error metadata for a specific error code
102
+ * Provides severity, recovery strategy, and user message
103
+ * Used internally by RouterError instance methods
104
+ */
105
+ export declare function getErrorMetadata(code: RouterErrorCode): ErrorCodeMetadata;
106
+ export {};
107
+ //# sourceMappingURL=error-codes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../../../../src/router/features/errors/error-codes.ts"],"names":[],"mappings":"AAAA;;;;;;EAME;AAEF,uIAAuI;AACvI;;;GAGG;AACH,oBAAY,eAAe;IAEzB,qCAAqC;IACrC,sBAAsB,2BAA2B;IACjD,uBAAuB;IACvB,cAAc,mBAAmB;IACjC,mCAAmC;IACnC,cAAc,mBAAmB;IACjC,6CAA6C;IAC7C,sBAAsB,2BAA2B;IAGjD,oCAAoC;IACpC,qBAAqB,0BAA0B;IAC/C,sBAAsB;IACtB,aAAa,kBAAkB;IAC/B,kCAAkC;IAClC,aAAa,kBAAkB;IAC/B,+CAA+C;IAC/C,YAAY,iBAAiB;IAG7B,6CAA6C;IAC7C,uBAAuB,4BAA4B;IACnD,mCAAmC;IACnC,sBAAsB,2BAA2B;IACjD,sCAAsC;IACtC,oBAAoB,yBAAyB;IAC7C,2CAA2C;IAC3C,yBAAyB,8BAA8B;IAGvD,+BAA+B;IAC/B,eAAe,oBAAoB;IACnC,6BAA6B;IAC7B,kBAAkB,uBAAuB;IACzC,sDAAsD;IACtD,qBAAqB,0BAA0B;IAC/C,iCAAiC;IACjC,iBAAiB,sBAAsB;IAGvC,8CAA8C;IAC9C,yBAAyB,8BAA8B;IACvD,yDAAyD;IACzD,2BAA2B,gCAAgC;IAG3D,oDAAoD;IACpD,aAAa,kBAAkB;CAChC;AAED,mIAAmI;AACnI;;GAEG;AACH,oBAAY,aAAa;IACvB,uEAAuE;IACvE,QAAQ,aAAa;IACrB,gDAAgD;IAChD,KAAK,UAAU;IACf,gDAAgD;IAChD,OAAO,YAAY;IACnB,0DAA0D;IAC1D,IAAI,SAAS;CACd;AAED,mJAAmJ;AACnJ;;GAEG;AACH,oBAAY,qBAAqB;IAC/B,sCAAsC;IACtC,aAAa,kBAAkB;IAC/B,iCAAiC;IACjC,iBAAiB,sBAAsB;IACvC,gDAAgD;IAChD,WAAW,gBAAgB;IAC3B,oCAAoC;IACpC,UAAU,eAAe;IACzB,qCAAqC;IACrC,SAAS,cAAc;CACxB;AAED;;GAEG;AACH,UAAU,iBAAiB;IACzB,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,EAAE,aAAa,CAAC;IACxB,eAAe,EAAE,qBAAqB,CAAC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,4JAA4J;AAC5J;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,eAAe,EAAE,iBAAiB,CAiJrE,CAAC;AAEF,gKAAgK;AAChK;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,GAAG,iBAAiB,CAEzE"}