@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.
- package/LICENSE +21 -0
- package/README.md +621 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/router/core/config.d.ts +22 -0
- package/dist/router/core/config.d.ts.map +1 -0
- package/dist/router/core/config.js +54 -0
- package/dist/router/core/config.js.map +1 -0
- package/dist/router/core/constants.d.ts +89 -0
- package/dist/router/core/constants.d.ts.map +1 -0
- package/dist/router/core/constants.js +95 -0
- package/dist/router/core/constants.js.map +1 -0
- package/dist/router/core/history.d.ts +54 -0
- package/dist/router/core/history.d.ts.map +1 -0
- package/dist/router/core/history.js +89 -0
- package/dist/router/core/history.js.map +1 -0
- package/dist/router/core/matcher.d.ts +43 -0
- package/dist/router/core/matcher.d.ts.map +1 -0
- package/dist/router/core/matcher.js +242 -0
- package/dist/router/core/matcher.js.map +1 -0
- package/dist/router/core/params.d.ts +88 -0
- package/dist/router/core/params.d.ts.map +1 -0
- package/dist/router/core/params.js +150 -0
- package/dist/router/core/params.js.map +1 -0
- package/dist/router/core/pipeline.d.ts +90 -0
- package/dist/router/core/pipeline.d.ts.map +1 -0
- package/dist/router/core/pipeline.js +323 -0
- package/dist/router/core/pipeline.js.map +1 -0
- package/dist/router/core/route-tree.d.ts +76 -0
- package/dist/router/core/route-tree.d.ts.map +1 -0
- package/dist/router/core/route-tree.js +143 -0
- package/dist/router/core/route-tree.js.map +1 -0
- package/dist/router/core/router.d.ts +229 -0
- package/dist/router/core/router.d.ts.map +1 -0
- package/dist/router/core/router.js +762 -0
- package/dist/router/core/router.js.map +1 -0
- package/dist/router/core/types.d.ts +387 -0
- package/dist/router/core/types.d.ts.map +1 -0
- package/dist/router/core/types.js +22 -0
- package/dist/router/core/types.js.map +1 -0
- package/dist/router/core/utils.d.ts +66 -0
- package/dist/router/core/utils.d.ts.map +1 -0
- package/dist/router/core/utils.js +152 -0
- package/dist/router/core/utils.js.map +1 -0
- package/dist/router/features/coordinator.d.ts +75 -0
- package/dist/router/features/coordinator.d.ts.map +1 -0
- package/dist/router/features/coordinator.js +203 -0
- package/dist/router/features/coordinator.js.map +1 -0
- package/dist/router/features/errors/error-codes.d.ts +107 -0
- package/dist/router/features/errors/error-codes.d.ts.map +1 -0
- package/dist/router/features/errors/error-codes.js +247 -0
- package/dist/router/features/errors/error-codes.js.map +1 -0
- package/dist/router/features/errors/error-resolution.d.ts +31 -0
- package/dist/router/features/errors/error-resolution.d.ts.map +1 -0
- package/dist/router/features/errors/error-resolution.js +47 -0
- package/dist/router/features/errors/error-resolution.js.map +1 -0
- package/dist/router/features/errors/error-types.d.ts +60 -0
- package/dist/router/features/errors/error-types.d.ts.map +1 -0
- package/dist/router/features/errors/error-types.js +57 -0
- package/dist/router/features/errors/error-types.js.map +1 -0
- package/dist/router/features/errors/global-error-fallback.d.ts +33 -0
- package/dist/router/features/errors/global-error-fallback.d.ts.map +1 -0
- package/dist/router/features/errors/global-error-fallback.js +182 -0
- package/dist/router/features/errors/global-error-fallback.js.map +1 -0
- package/dist/router/features/errors/index.d.ts +15 -0
- package/dist/router/features/errors/index.d.ts.map +1 -0
- package/dist/router/features/errors/index.js +18 -0
- package/dist/router/features/errors/index.js.map +1 -0
- package/dist/router/features/errors/router-errors.d.ts +44 -0
- package/dist/router/features/errors/router-errors.d.ts.map +1 -0
- package/dist/router/features/errors/router-errors.js +53 -0
- package/dist/router/features/errors/router-errors.js.map +1 -0
- package/dist/router/features/guards/engine.d.ts +40 -0
- package/dist/router/features/guards/engine.d.ts.map +1 -0
- package/dist/router/features/guards/engine.js +67 -0
- package/dist/router/features/guards/engine.js.map +1 -0
- package/dist/router/features/guards/index.d.ts +52 -0
- package/dist/router/features/guards/index.d.ts.map +1 -0
- package/dist/router/features/guards/index.js +95 -0
- package/dist/router/features/guards/index.js.map +1 -0
- package/dist/router/features/loaders/cache.d.ts +60 -0
- package/dist/router/features/loaders/cache.d.ts.map +1 -0
- package/dist/router/features/loaders/cache.js +80 -0
- package/dist/router/features/loaders/cache.js.map +1 -0
- package/dist/router/features/loaders/engine.d.ts +17 -0
- package/dist/router/features/loaders/engine.d.ts.map +1 -0
- package/dist/router/features/loaders/engine.js +27 -0
- package/dist/router/features/loaders/engine.js.map +1 -0
- package/dist/router/features/loaders/index.d.ts +49 -0
- package/dist/router/features/loaders/index.d.ts.map +1 -0
- package/dist/router/features/loaders/index.js +112 -0
- package/dist/router/features/loaders/index.js.map +1 -0
- package/dist/router/features/loading-ui-manager.d.ts +69 -0
- package/dist/router/features/loading-ui-manager.d.ts.map +1 -0
- package/dist/router/features/loading-ui-manager.js +209 -0
- package/dist/router/features/loading-ui-manager.js.map +1 -0
- package/dist/router/features/module-loader.d.ts +50 -0
- package/dist/router/features/module-loader.d.ts.map +1 -0
- package/dist/router/features/module-loader.js +121 -0
- package/dist/router/features/module-loader.js.map +1 -0
- package/dist/router/features/outlet/errors.d.ts +24 -0
- package/dist/router/features/outlet/errors.d.ts.map +1 -0
- package/dist/router/features/outlet/errors.js +96 -0
- package/dist/router/features/outlet/errors.js.map +1 -0
- package/dist/router/features/outlet/index.d.ts +45 -0
- package/dist/router/features/outlet/index.d.ts.map +1 -0
- package/dist/router/features/outlet/index.js +95 -0
- package/dist/router/features/outlet/index.js.map +1 -0
- package/dist/router/features/outlet/mount.d.ts +38 -0
- package/dist/router/features/outlet/mount.d.ts.map +1 -0
- package/dist/router/features/outlet/mount.js +301 -0
- package/dist/router/features/outlet/mount.js.map +1 -0
- package/dist/router/features/outlet/segment-chain.d.ts +16 -0
- package/dist/router/features/outlet/segment-chain.d.ts.map +1 -0
- package/dist/router/features/outlet/segment-chain.js +62 -0
- package/dist/router/features/outlet/segment-chain.js.map +1 -0
- package/dist/router/features/prefetch/index.d.ts +97 -0
- package/dist/router/features/prefetch/index.d.ts.map +1 -0
- package/dist/router/features/prefetch/index.js +345 -0
- package/dist/router/features/prefetch/index.js.map +1 -0
- package/dist/router/features/ux/focus.d.ts +62 -0
- package/dist/router/features/ux/focus.d.ts.map +1 -0
- package/dist/router/features/ux/focus.js +136 -0
- package/dist/router/features/ux/focus.js.map +1 -0
- package/dist/router/features/ux/live-region.d.ts +81 -0
- package/dist/router/features/ux/live-region.d.ts.map +1 -0
- package/dist/router/features/ux/live-region.js +166 -0
- package/dist/router/features/ux/live-region.js.map +1 -0
- package/dist/router/features/ux/scroll-focus.d.ts +105 -0
- package/dist/router/features/ux/scroll-focus.d.ts.map +1 -0
- package/dist/router/features/ux/scroll-focus.js +111 -0
- package/dist/router/features/ux/scroll-focus.js.map +1 -0
- package/dist/router/features/ux/scroll.d.ts +71 -0
- package/dist/router/features/ux/scroll.d.ts.map +1 -0
- package/dist/router/features/ux/scroll.js +137 -0
- package/dist/router/features/ux/scroll.js.map +1 -0
- package/dist/router/features/ux/transitions.d.ts +120 -0
- package/dist/router/features/ux/transitions.d.ts.map +1 -0
- package/dist/router/features/ux/transitions.js +235 -0
- package/dist/router/features/ux/transitions.js.map +1 -0
- package/dist/router/integration/directive-binder.d.ts +20 -0
- package/dist/router/integration/directive-binder.d.ts.map +1 -0
- package/dist/router/integration/directive-binder.js +139 -0
- package/dist/router/integration/directive-binder.js.map +1 -0
- package/dist/router/integration/directives.d.ts +42 -0
- package/dist/router/integration/directives.d.ts.map +1 -0
- package/dist/router/integration/directives.js +109 -0
- package/dist/router/integration/directives.js.map +1 -0
- package/dist/router/integration/history-adapter.d.ts +76 -0
- package/dist/router/integration/history-adapter.d.ts.map +1 -0
- package/dist/router/integration/history-adapter.js +157 -0
- package/dist/router/integration/history-adapter.js.map +1 -0
- package/dist/router/integration/hmr.d.ts +83 -0
- package/dist/router/integration/hmr.d.ts.map +1 -0
- package/dist/router/integration/hmr.js +160 -0
- package/dist/router/integration/hmr.js.map +1 -0
- package/dist/router/integration/link-interceptor.d.ts +49 -0
- package/dist/router/integration/link-interceptor.d.ts.map +1 -0
- package/dist/router/integration/link-interceptor.js +94 -0
- package/dist/router/integration/link-interceptor.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/** @codex
|
|
2
|
+
{
|
|
3
|
+
"id": "pithy.router.error-fallback",
|
|
4
|
+
"title": "Global Error Fallback Component",
|
|
5
|
+
"category": "runtime"
|
|
6
|
+
}
|
|
7
|
+
*/
|
|
8
|
+
import { html } from '@pithyjs/core';
|
|
9
|
+
/** @codexApi {"parent":"pithy.router.error-fallback","name":"GlobalErrorFallback","stability":"stable","signature":"(props: ErrorComponentProps) => Component","description":"Default error UI when no route-specific error.ts exists"} */
|
|
10
|
+
/**
|
|
11
|
+
* Global fallback error component
|
|
12
|
+
* Shown when no route-specific error.ts exists
|
|
13
|
+
* Provides basic error display with retry button
|
|
14
|
+
*
|
|
15
|
+
* @param props - Error component props
|
|
16
|
+
* @returns PithyJS component instance
|
|
17
|
+
*/
|
|
18
|
+
export function GlobalErrorFallback({ error, retry }) {
|
|
19
|
+
const dev = typeof import.meta !== 'undefined' &&
|
|
20
|
+
import.meta.env?.DEV === true;
|
|
21
|
+
// Use user-friendly message if error is a RouterError
|
|
22
|
+
const errorMessage = error?.getUserMessage
|
|
23
|
+
? error.getUserMessage()
|
|
24
|
+
: error?.message || 'Something went wrong';
|
|
25
|
+
// Check if error is retryable
|
|
26
|
+
const isRetryable = error?.isRetryable ? error.isRetryable() : true;
|
|
27
|
+
// Get severity for styling
|
|
28
|
+
const severity = error?.getSeverity ? error.getSeverity() : 'error';
|
|
29
|
+
const isCritical = severity === 'critical';
|
|
30
|
+
const isError = severity === 'error';
|
|
31
|
+
const isWarning = severity === 'warning';
|
|
32
|
+
const isInfo = severity === 'info';
|
|
33
|
+
const errorDetails = JSON.stringify(error?.ctx, null, 2);
|
|
34
|
+
const errorStack = error?.cause
|
|
35
|
+
? String(error.cause.stack || error.cause)
|
|
36
|
+
: '';
|
|
37
|
+
function handleRetry() {
|
|
38
|
+
retry();
|
|
39
|
+
}
|
|
40
|
+
return html(`
|
|
41
|
+
<section
|
|
42
|
+
class="route-error"
|
|
43
|
+
[class.severity-critical]="isCritical"
|
|
44
|
+
[class.severity-error]="isError"
|
|
45
|
+
[class.severity-warning]="isWarning"
|
|
46
|
+
[class.severity-info]="isInfo"
|
|
47
|
+
role="alert"
|
|
48
|
+
tabindex="-1"
|
|
49
|
+
aria-live="assertive"
|
|
50
|
+
>
|
|
51
|
+
<h3>Could not load this section</h3>
|
|
52
|
+
<p>{{ errorMessage }}</p>
|
|
53
|
+
|
|
54
|
+
<div @if="dev" class="error-details">
|
|
55
|
+
<details>
|
|
56
|
+
<summary>Details</summary>
|
|
57
|
+
<pre>{{ errorDetails }}</pre>
|
|
58
|
+
<pre @if="errorStack">{{ errorStack }}</pre>
|
|
59
|
+
</details>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<button @if="isRetryable" @click="handleRetry()">Retry</button>
|
|
63
|
+
|
|
64
|
+
<style>
|
|
65
|
+
.route-error {
|
|
66
|
+
padding: 2rem;
|
|
67
|
+
text-align: center;
|
|
68
|
+
background: #fff;
|
|
69
|
+
border: 1px solid #e0e0e0;
|
|
70
|
+
border-radius: 8px;
|
|
71
|
+
margin: 2rem auto;
|
|
72
|
+
max-width: 600px;
|
|
73
|
+
position: relative;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* Severity-based left border accent */
|
|
77
|
+
.route-error.severity-critical {
|
|
78
|
+
border-left: 4px solid #d32f2f;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.route-error.severity-error {
|
|
82
|
+
border-left: 4px solid #f57c00;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.route-error.severity-warning {
|
|
86
|
+
border-left: 4px solid #fbc02d;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.route-error.severity-info {
|
|
90
|
+
border-left: 4px solid #1976d2;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.route-error h3 {
|
|
94
|
+
color: #d32f2f;
|
|
95
|
+
margin: 0 0 1rem;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* Severity-specific heading colors */
|
|
99
|
+
.route-error.severity-critical h3 {
|
|
100
|
+
color: #b71c1c;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.route-error.severity-error h3 {
|
|
104
|
+
color: #d32f2f;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.route-error.severity-warning h3 {
|
|
108
|
+
color: #f57c00;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.route-error.severity-info h3 {
|
|
112
|
+
color: #1976d2;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.route-error p {
|
|
116
|
+
color: #666;
|
|
117
|
+
margin: 0 0 1.5rem;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.error-details {
|
|
121
|
+
text-align: left;
|
|
122
|
+
margin: 1rem 0;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.route-error details {
|
|
126
|
+
padding: 1rem;
|
|
127
|
+
background: #f5f5f5;
|
|
128
|
+
border-radius: 4px;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.route-error summary {
|
|
132
|
+
cursor: pointer;
|
|
133
|
+
font-weight: 600;
|
|
134
|
+
color: #666;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.route-error pre {
|
|
138
|
+
margin: 0.5rem 0 0;
|
|
139
|
+
padding: 0.5rem;
|
|
140
|
+
background: #fff;
|
|
141
|
+
border: 1px solid #ddd;
|
|
142
|
+
border-radius: 4px;
|
|
143
|
+
overflow-x: auto;
|
|
144
|
+
font-size: 0.875rem;
|
|
145
|
+
white-space: pre-wrap;
|
|
146
|
+
word-wrap: break-word;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.route-error button {
|
|
150
|
+
background: #1976d2;
|
|
151
|
+
color: white;
|
|
152
|
+
border: none;
|
|
153
|
+
padding: 0.75rem 1.5rem;
|
|
154
|
+
border-radius: 4px;
|
|
155
|
+
font-size: 1rem;
|
|
156
|
+
cursor: pointer;
|
|
157
|
+
transition: background 0.2s;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.route-error button:hover {
|
|
161
|
+
background: #1565c0;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.route-error button:active {
|
|
165
|
+
background: #0d47a1;
|
|
166
|
+
}
|
|
167
|
+
</style>
|
|
168
|
+
</section>
|
|
169
|
+
`, {
|
|
170
|
+
dev,
|
|
171
|
+
errorMessage,
|
|
172
|
+
isRetryable,
|
|
173
|
+
isCritical,
|
|
174
|
+
isError,
|
|
175
|
+
isWarning,
|
|
176
|
+
isInfo,
|
|
177
|
+
errorDetails,
|
|
178
|
+
errorStack,
|
|
179
|
+
handleRetry,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=global-error-fallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-error-fallback.js","sourceRoot":"","sources":["../../../../src/router/features/errors/global-error-fallback.ts"],"names":[],"mappings":"AAAA;;;;;;EAME;AAEF,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAerC,2OAA2O;AAC3O;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAuB;IACvE,MAAM,GAAG,GACP,OAAO,MAAM,CAAC,IAAI,KAAK,WAAW;QACjC,MAAM,CAAC,IAAoC,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;IAEjE,sDAAsD;IACtD,MAAM,YAAY,GAAG,KAAK,EAAE,cAAc;QACxC,CAAC,CAAC,KAAK,CAAC,cAAc,EAAE;QACxB,CAAC,CAAC,KAAK,EAAE,OAAO,IAAI,sBAAsB,CAAC;IAE7C,8BAA8B;IAC9B,MAAM,WAAW,GAAG,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAEpE,2BAA2B;IAC3B,MAAM,QAAQ,GAAG,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;IACpE,MAAM,UAAU,GAAG,QAAQ,KAAK,UAAU,CAAC;IAC3C,MAAM,OAAO,GAAG,QAAQ,KAAK,OAAO,CAAC;IACrC,MAAM,SAAS,GAAG,QAAQ,KAAK,SAAS,CAAC;IACzC,MAAM,MAAM,GAAG,QAAQ,KAAK,MAAM,CAAC;IAEnC,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACzD,MAAM,UAAU,GAAG,KAAK,EAAE,KAAK;QAC7B,CAAC,CAAC,MAAM,CAAE,KAAK,CAAC,KAA6B,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC;QACnE,CAAC,CAAC,EAAE,CAAC;IAEP,SAAS,WAAW;QAClB,KAAK,EAAE,CAAC;IACV,CAAC;IAED,OAAO,IAAI,CACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiID,EACC;QACE,GAAG;QACH,YAAY;QACZ,WAAW;QACX,UAAU;QACV,OAAO;QACP,SAAS;QACT,MAAM;QACN,YAAY;QACZ,UAAU;QACV,WAAW;KACZ,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** @codex
|
|
2
|
+
{
|
|
3
|
+
"id": "pithy.router.errors",
|
|
4
|
+
"title": "Router Error Handling System",
|
|
5
|
+
"category": "runtime"
|
|
6
|
+
}
|
|
7
|
+
*/
|
|
8
|
+
export { RouterError, RouterErrorCode } from './error-types';
|
|
9
|
+
export type { ErrorContext } from './error-types';
|
|
10
|
+
export { ErrorSeverity, ErrorRecoveryStrategy, ERROR_TAXONOMY, getErrorMetadata, } from './error-codes';
|
|
11
|
+
export { routeErrors, setRouteError, clearRouteError, clearAllRouteErrors, } from './router-errors';
|
|
12
|
+
export { resolveErrorImport, hasErrorComponent } from './error-resolution';
|
|
13
|
+
export { GlobalErrorFallback } from './global-error-fallback';
|
|
14
|
+
export type { ErrorComponentProps } from './global-error-fallback';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/router/features/errors/index.ts"],"names":[],"mappings":"AAAA;;;;;;EAME;AAGF,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC7D,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGlD,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,cAAc,EACd,gBAAgB,GACjB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,WAAW,EACX,aAAa,EACb,eAAe,EACf,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAG3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,YAAY,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** @codex
|
|
2
|
+
{
|
|
3
|
+
"id": "pithy.router.errors",
|
|
4
|
+
"title": "Router Error Handling System",
|
|
5
|
+
"category": "runtime"
|
|
6
|
+
}
|
|
7
|
+
*/
|
|
8
|
+
// Error types and classes
|
|
9
|
+
export { RouterError, RouterErrorCode } from './error-types';
|
|
10
|
+
// Error codes and taxonomy
|
|
11
|
+
export { ErrorSeverity, ErrorRecoveryStrategy, ERROR_TAXONOMY, getErrorMetadata, } from './error-codes';
|
|
12
|
+
// Error state management
|
|
13
|
+
export { routeErrors, setRouteError, clearRouteError, clearAllRouteErrors, } from './router-errors';
|
|
14
|
+
// Error resolution
|
|
15
|
+
export { resolveErrorImport, hasErrorComponent } from './error-resolution';
|
|
16
|
+
// Global error fallback component
|
|
17
|
+
export { GlobalErrorFallback } from './global-error-fallback';
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/router/features/errors/index.ts"],"names":[],"mappings":"AAAA;;;;;;EAME;AAEF,0BAA0B;AAC1B,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAG7D,2BAA2B;AAC3B,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,cAAc,EACd,gBAAgB,GACjB,MAAM,eAAe,CAAC;AAEvB,yBAAyB;AACzB,OAAO,EACL,WAAW,EACX,aAAa,EACb,eAAe,EACf,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAEzB,mBAAmB;AACnB,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE3E,kCAAkC;AAClC,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** @codex
|
|
2
|
+
{
|
|
3
|
+
"id": "pithy.router.error-state",
|
|
4
|
+
"title": "Router Error State Management",
|
|
5
|
+
"category": "runtime"
|
|
6
|
+
}
|
|
7
|
+
*/
|
|
8
|
+
import { RouterError } from './error-types';
|
|
9
|
+
/**
|
|
10
|
+
* Map of route errors keyed by route ID
|
|
11
|
+
*/
|
|
12
|
+
type RouteErrors = Map<string, RouterError>;
|
|
13
|
+
/** @codexApi {"parent":"pithy.router.error-state","name":"routeErrors","stability":"internal","signature":"Signal<Map<string, RouterError>>","description":"Global reactive signal holding all route errors by route ID"} */
|
|
14
|
+
/**
|
|
15
|
+
* Global signal holding all route errors
|
|
16
|
+
* Reactive - updates trigger outlet updates
|
|
17
|
+
* @internal Used internally by the router for error state tracking
|
|
18
|
+
*/
|
|
19
|
+
export declare const routeErrors: import("@pithyjs/signals").Signal<RouteErrors>;
|
|
20
|
+
/** @codexApi {"parent":"pithy.router.error-state","name":"setRouteError","stability":"stable","signature":"(routeId: string, err: RouterError) => void","description":"Set an error for a route, triggering reactive outlet update"} */
|
|
21
|
+
/**
|
|
22
|
+
* Set an error for a specific route
|
|
23
|
+
* Triggers reactive update of affected outlets with error UI
|
|
24
|
+
*
|
|
25
|
+
* @param routeId - ID of the route that encountered an error
|
|
26
|
+
* @param err - RouterError instance with context
|
|
27
|
+
*/
|
|
28
|
+
export declare function setRouteError(routeId: string, err: RouterError): void;
|
|
29
|
+
/** @codexApi {"parent":"pithy.router.error-state","name":"clearRouteError","stability":"stable","signature":"(routeId: string) => void","description":"Clear error for a specific route on retry or navigation"} */
|
|
30
|
+
/**
|
|
31
|
+
* Clear error for a specific route
|
|
32
|
+
* Called on successful retry or navigation away from error state
|
|
33
|
+
*
|
|
34
|
+
* @param routeId - ID of the route to clear error for
|
|
35
|
+
*/
|
|
36
|
+
export declare function clearRouteError(routeId: string): void;
|
|
37
|
+
/** @codexApi {"parent":"pithy.router.error-state","name":"clearAllRouteErrors","stability":"stable","signature":"() => void","description":"Clear all route errors on successful navigation"} */
|
|
38
|
+
/**
|
|
39
|
+
* Clear all route errors
|
|
40
|
+
* Called on successful navigation to reset all error states
|
|
41
|
+
*/
|
|
42
|
+
export declare function clearAllRouteErrors(): void;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=router-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router-errors.d.ts","sourceRoot":"","sources":["../../../../src/router/features/errors/router-errors.ts"],"names":[],"mappings":"AAAA;;;;;;EAME;AAGF,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C;;GAEG;AACH,KAAK,WAAW,GAAG,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAE5C,6NAA6N;AAC7N;;;;GAIG;AACH,eAAO,MAAM,WAAW,gDAAiC,CAAC;AAE1D,wOAAwO;AACxO;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI,CAMrE;AAED,oNAAoN;AACpN;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAMrD;AAED,iMAAiM;AACjM;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/** @codex
|
|
2
|
+
{
|
|
3
|
+
"id": "pithy.router.error-state",
|
|
4
|
+
"title": "Router Error State Management",
|
|
5
|
+
"category": "runtime"
|
|
6
|
+
}
|
|
7
|
+
*/
|
|
8
|
+
import { signal } from '@pithyjs/signals';
|
|
9
|
+
/** @codexApi {"parent":"pithy.router.error-state","name":"routeErrors","stability":"internal","signature":"Signal<Map<string, RouterError>>","description":"Global reactive signal holding all route errors by route ID"} */
|
|
10
|
+
/**
|
|
11
|
+
* Global signal holding all route errors
|
|
12
|
+
* Reactive - updates trigger outlet updates
|
|
13
|
+
* @internal Used internally by the router for error state tracking
|
|
14
|
+
*/
|
|
15
|
+
export const routeErrors = signal(new Map());
|
|
16
|
+
/** @codexApi {"parent":"pithy.router.error-state","name":"setRouteError","stability":"stable","signature":"(routeId: string, err: RouterError) => void","description":"Set an error for a route, triggering reactive outlet update"} */
|
|
17
|
+
/**
|
|
18
|
+
* Set an error for a specific route
|
|
19
|
+
* Triggers reactive update of affected outlets with error UI
|
|
20
|
+
*
|
|
21
|
+
* @param routeId - ID of the route that encountered an error
|
|
22
|
+
* @param err - RouterError instance with context
|
|
23
|
+
*/
|
|
24
|
+
export function setRouteError(routeId, err) {
|
|
25
|
+
routeErrors.set((m) => {
|
|
26
|
+
const n = new Map(m);
|
|
27
|
+
n.set(routeId, err);
|
|
28
|
+
return n;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/** @codexApi {"parent":"pithy.router.error-state","name":"clearRouteError","stability":"stable","signature":"(routeId: string) => void","description":"Clear error for a specific route on retry or navigation"} */
|
|
32
|
+
/**
|
|
33
|
+
* Clear error for a specific route
|
|
34
|
+
* Called on successful retry or navigation away from error state
|
|
35
|
+
*
|
|
36
|
+
* @param routeId - ID of the route to clear error for
|
|
37
|
+
*/
|
|
38
|
+
export function clearRouteError(routeId) {
|
|
39
|
+
routeErrors.set((m) => {
|
|
40
|
+
const n = new Map(m);
|
|
41
|
+
n.delete(routeId);
|
|
42
|
+
return n;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/** @codexApi {"parent":"pithy.router.error-state","name":"clearAllRouteErrors","stability":"stable","signature":"() => void","description":"Clear all route errors on successful navigation"} */
|
|
46
|
+
/**
|
|
47
|
+
* Clear all route errors
|
|
48
|
+
* Called on successful navigation to reset all error states
|
|
49
|
+
*/
|
|
50
|
+
export function clearAllRouteErrors() {
|
|
51
|
+
routeErrors.set(new Map());
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=router-errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router-errors.js","sourceRoot":"","sources":["../../../../src/router/features/errors/router-errors.ts"],"names":[],"mappings":"AAAA;;;;;;EAME;AAEF,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAQ1C,6NAA6N;AAC7N;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAc,IAAI,GAAG,EAAE,CAAC,CAAC;AAE1D,wOAAwO;AACxO;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe,EAAE,GAAgB;IAC7D,WAAW,CAAC,GAAG,CAAC,CAAC,CAAc,EAAE,EAAE;QACjC,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;QACrB,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACpB,OAAO,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;AACL,CAAC;AAED,oNAAoN;AACpN;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,WAAW,CAAC,GAAG,CAAC,CAAC,CAAc,EAAE,EAAE;QACjC,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;QACrB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAClB,OAAO,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;AACL,CAAC;AAED,iMAAiM;AACjM;;;GAGG;AACH,MAAM,UAAU,mBAAmB;IACjC,WAAW,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** @codex
|
|
2
|
+
{
|
|
3
|
+
"id": "pithy.router.guards.engine",
|
|
4
|
+
"title": "Pure Guard Execution Engine",
|
|
5
|
+
"category": "runtime"
|
|
6
|
+
}
|
|
7
|
+
*/
|
|
8
|
+
import type { GuardContext, GuardFunction, SyncGuardResult } from './index';
|
|
9
|
+
/** @codexApi {"parent":"pithy.router.guards.engine","name":"GuardExecution","stability":"stable","signature":"class GuardExecution"} */
|
|
10
|
+
/**
|
|
11
|
+
* Individual guard execution wrapper with cancellation support
|
|
12
|
+
* Pure execution logic extracted from GuardManager
|
|
13
|
+
*/
|
|
14
|
+
export declare class GuardExecution {
|
|
15
|
+
private abortController;
|
|
16
|
+
private promise;
|
|
17
|
+
constructor(guard: GuardFunction, context: GuardContext, index: number);
|
|
18
|
+
/**
|
|
19
|
+
* Execute a single guard and handle errors
|
|
20
|
+
*/
|
|
21
|
+
private executeGuard;
|
|
22
|
+
/**
|
|
23
|
+
* Abort this guard execution
|
|
24
|
+
*/
|
|
25
|
+
abort(): void;
|
|
26
|
+
/**
|
|
27
|
+
* Get the promise for this guard execution
|
|
28
|
+
*/
|
|
29
|
+
getPromise(): Promise<{
|
|
30
|
+
result: SyncGuardResult;
|
|
31
|
+
error: Error | null;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
/** @codexApi {"parent":"pithy.router.guards.engine","name":"abortRemainingGuards","stability":"stable","signature":"(guardExecutions: GuardExecution[], startIndex: number) => void"} */
|
|
35
|
+
/**
|
|
36
|
+
* Abort remaining guards after first failure
|
|
37
|
+
* Pure function for guard cancellation logic
|
|
38
|
+
*/
|
|
39
|
+
export declare function abortRemainingGuards(guardExecutions: GuardExecution[], startIndex: number): void;
|
|
40
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../../src/router/features/guards/engine.ts"],"names":[],"mappings":"AAAA;;;;;;EAME;AAEF,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAG5E,wIAAwI;AACxI;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,OAAO,CAA4D;gBAE/D,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM;IAgBtE;;OAEG;YACW,YAAY;IAmB1B;;OAEG;IACI,KAAK,IAAI,IAAI;IAIpB;;OAEG;IACI,UAAU,IAAI,OAAO,CAAC;QAC3B,MAAM,EAAE,eAAe,CAAC;QACxB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;KACrB,CAAC;CAGH;AAED,yLAAyL;AACzL;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,eAAe,EAAE,cAAc,EAAE,EACjC,UAAU,EAAE,MAAM,GACjB,IAAI,CAON"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/** @codex
|
|
2
|
+
{
|
|
3
|
+
"id": "pithy.router.guards.engine",
|
|
4
|
+
"title": "Pure Guard Execution Engine",
|
|
5
|
+
"category": "runtime"
|
|
6
|
+
}
|
|
7
|
+
*/
|
|
8
|
+
import { combineAbortSignals } from '../../core/utils';
|
|
9
|
+
/** @codexApi {"parent":"pithy.router.guards.engine","name":"GuardExecution","stability":"stable","signature":"class GuardExecution"} */
|
|
10
|
+
/**
|
|
11
|
+
* Individual guard execution wrapper with cancellation support
|
|
12
|
+
* Pure execution logic extracted from GuardManager
|
|
13
|
+
*/
|
|
14
|
+
export class GuardExecution {
|
|
15
|
+
constructor(guard, context, index) {
|
|
16
|
+
this.abortController = new AbortController();
|
|
17
|
+
// Chain the parent signal with our own
|
|
18
|
+
const combinedSignal = combineAbortSignals([
|
|
19
|
+
context.signal,
|
|
20
|
+
this.abortController.signal,
|
|
21
|
+
]);
|
|
22
|
+
this.promise = this.executeGuard(guard, { ...context, signal: combinedSignal }, index);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Execute a single guard and handle errors
|
|
26
|
+
*/
|
|
27
|
+
async executeGuard(guard, context, index) {
|
|
28
|
+
try {
|
|
29
|
+
const result = await Promise.resolve(guard(context));
|
|
30
|
+
return { result, error: null };
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
return {
|
|
34
|
+
result: false,
|
|
35
|
+
error: error instanceof Error
|
|
36
|
+
? error
|
|
37
|
+
: new Error(`Guard ${index} failed: ${String(error)}`),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Abort this guard execution
|
|
43
|
+
*/
|
|
44
|
+
abort() {
|
|
45
|
+
this.abortController.abort();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get the promise for this guard execution
|
|
49
|
+
*/
|
|
50
|
+
getPromise() {
|
|
51
|
+
return this.promise;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** @codexApi {"parent":"pithy.router.guards.engine","name":"abortRemainingGuards","stability":"stable","signature":"(guardExecutions: GuardExecution[], startIndex: number) => void"} */
|
|
55
|
+
/**
|
|
56
|
+
* Abort remaining guards after first failure
|
|
57
|
+
* Pure function for guard cancellation logic
|
|
58
|
+
*/
|
|
59
|
+
export function abortRemainingGuards(guardExecutions, startIndex) {
|
|
60
|
+
for (let i = startIndex; i < guardExecutions.length; i++) {
|
|
61
|
+
const execution = guardExecutions[i];
|
|
62
|
+
if (execution) {
|
|
63
|
+
execution.abort();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../../src/router/features/guards/engine.ts"],"names":[],"mappings":"AAAA;;;;;;EAME;AAGF,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD,wIAAwI;AACxI;;;GAGG;AACH,MAAM,OAAO,cAAc;IAIzB,YAAY,KAAoB,EAAE,OAAqB,EAAE,KAAa;QACpE,IAAI,CAAC,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;QAE7C,uCAAuC;QACvC,MAAM,cAAc,GAAG,mBAAmB,CAAC;YACzC,OAAO,CAAC,MAAM;YACd,IAAI,CAAC,eAAe,CAAC,MAAM;SAC5B,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,YAAY,CAC9B,KAAK,EACL,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,EACtC,KAAK,CACN,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,YAAY,CACxB,KAAoB,EACpB,OAAqB,EACrB,KAAa;QAEb,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YACrD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACjC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,MAAM,EAAE,KAAK;gBACb,KAAK,EACH,KAAK,YAAY,KAAK;oBACpB,CAAC,CAAC,KAAK;oBACP,CAAC,CAAC,IAAI,KAAK,CAAC,SAAS,KAAK,YAAY,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;aAC3D,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACI,KAAK;QACV,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;IAC/B,CAAC;IAED;;OAEG;IACI,UAAU;QAIf,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF;AAED,yLAAyL;AACzL;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAClC,eAAiC,EACjC,UAAkB;IAElB,KAAK,IAAI,CAAC,GAAG,UAAU,EAAE,CAAC,GAAG,eAAe,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzD,MAAM,SAAS,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,SAAS,EAAE,CAAC;YACd,SAAS,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** @codex
|
|
2
|
+
{
|
|
3
|
+
"id": "pithy.router.guards",
|
|
4
|
+
"title": "Route Guards and Redirects with Zero-Flash Navigation",
|
|
5
|
+
"category": "runtime"
|
|
6
|
+
}
|
|
7
|
+
*/
|
|
8
|
+
import type { NavigationId, GuardContext, SyncGuardResult, GuardResult, GuardFunction, GuardExecutionResult } from '../../core/types';
|
|
9
|
+
export type { GuardContext, SyncGuardResult, GuardResult, GuardFunction, GuardExecutionResult, };
|
|
10
|
+
/** @codexApi {"parent":"pithy.router.guards","name":"RedirectConfig","stability":"stable","signature":"interface RedirectConfig","description":"Redirect configuration for guard results with optional history replacement"} */
|
|
11
|
+
/**
|
|
12
|
+
* Redirect configuration for guard results
|
|
13
|
+
* Allows guards to redirect navigation with optional history replacement
|
|
14
|
+
*/
|
|
15
|
+
export interface RedirectConfig {
|
|
16
|
+
/** Target path to redirect to */
|
|
17
|
+
redirect: string;
|
|
18
|
+
/** Whether to replace current history entry */
|
|
19
|
+
replace?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** @codexApi {"parent":"pithy.router.guards","name":"GuardManager","stability":"stable","signature":"class GuardManager","description":"Manages route guards with zero-flash navigation and cancellation"} */
|
|
22
|
+
/**
|
|
23
|
+
* Guard manager for handling route guards with zero-flash navigation
|
|
24
|
+
* Implements guards/redirects pre-commit from architectural improvements
|
|
25
|
+
*/
|
|
26
|
+
export declare class GuardManager {
|
|
27
|
+
private activeGuardSets;
|
|
28
|
+
/** @codexApi {"parent":"pithy.router.guards","name":"executeGuards","stability":"stable","signature":"(guards: GuardFunction[], context: GuardContext) => Promise<GuardExecutionResult>","description":"Execute guards in parallel with proper cancellation support"} */
|
|
29
|
+
/**
|
|
30
|
+
* Execute guards for a navigation with parallel evaluation and proper cancellation
|
|
31
|
+
*/
|
|
32
|
+
executeGuards(guards: GuardFunction[], context: GuardContext): Promise<GuardExecutionResult>;
|
|
33
|
+
/** @codexApi {"parent":"pithy.router.guards","name":"cancelGuards","stability":"stable","signature":"(navId: NavigationId) => void","description":"Cancel all active guards for a navigation"} */
|
|
34
|
+
/**
|
|
35
|
+
* Cancel all guards for a navigation
|
|
36
|
+
*/
|
|
37
|
+
cancelGuards(navId: NavigationId): void;
|
|
38
|
+
}
|
|
39
|
+
/** @codexApi {"parent":"pithy.router.guards","name":"AuthProvider","stability":"stable","signature":"interface AuthProvider","description":"Authentication provider interface for user state and permissions"} */
|
|
40
|
+
/**
|
|
41
|
+
* Authentication provider interface - implement this in your app
|
|
42
|
+
* Provides user authentication state and permissions for guard evaluation
|
|
43
|
+
*/
|
|
44
|
+
export interface AuthProvider {
|
|
45
|
+
/** Check if user is currently authenticated */
|
|
46
|
+
isAuthenticated(): Promise<boolean> | boolean;
|
|
47
|
+
/** Get current user's role */
|
|
48
|
+
getUserRole(): Promise<string | null> | string | null;
|
|
49
|
+
/** Get current user's permissions */
|
|
50
|
+
getUserPermissions(): Promise<string[]> | string[];
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/router/features/guards/index.ts"],"names":[],"mappings":"AAAA;;;;;;EAME;AAEF,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,WAAW,EACX,aAAa,EACb,oBAAoB,EACrB,MAAM,kBAAkB,CAAC;AAI1B,YAAY,EACV,YAAY,EACZ,eAAe,EACf,WAAW,EACX,aAAa,EACb,oBAAoB,GACrB,CAAC;AAEF,gOAAgO;AAChO;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,8MAA8M;AAC9M;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,eAAe,CAA6C;IAEpE,yQAAyQ;IACzQ;;OAEG;IACU,aAAa,CACxB,MAAM,EAAE,aAAa,EAAE,EACvB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,oBAAoB,CAAC;IA8EhC,kMAAkM;IAClM;;OAEG;IACI,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;CAO/C;AAED,kNAAkN;AAClN;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,+CAA+C;IAC/C,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAC9C,8BAA8B;IAC9B,WAAW,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC;IACtD,qCAAqC;IACrC,kBAAkB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC;CACpD"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/** @codex
|
|
2
|
+
{
|
|
3
|
+
"id": "pithy.router.guards",
|
|
4
|
+
"title": "Route Guards and Redirects with Zero-Flash Navigation",
|
|
5
|
+
"category": "runtime"
|
|
6
|
+
}
|
|
7
|
+
*/
|
|
8
|
+
import { GuardExecution, abortRemainingGuards } from './engine';
|
|
9
|
+
/** @codexApi {"parent":"pithy.router.guards","name":"GuardManager","stability":"stable","signature":"class GuardManager","description":"Manages route guards with zero-flash navigation and cancellation"} */
|
|
10
|
+
/**
|
|
11
|
+
* Guard manager for handling route guards with zero-flash navigation
|
|
12
|
+
* Implements guards/redirects pre-commit from architectural improvements
|
|
13
|
+
*/
|
|
14
|
+
export class GuardManager {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.activeGuardSets = new Map();
|
|
17
|
+
}
|
|
18
|
+
/** @codexApi {"parent":"pithy.router.guards","name":"executeGuards","stability":"stable","signature":"(guards: GuardFunction[], context: GuardContext) => Promise<GuardExecutionResult>","description":"Execute guards in parallel with proper cancellation support"} */
|
|
19
|
+
/**
|
|
20
|
+
* Execute guards for a navigation with parallel evaluation and proper cancellation
|
|
21
|
+
*/
|
|
22
|
+
async executeGuards(guards, context) {
|
|
23
|
+
if (guards.length === 0) {
|
|
24
|
+
return { allowed: true };
|
|
25
|
+
}
|
|
26
|
+
const { navId } = context;
|
|
27
|
+
// Cancel any existing guards for this navigation
|
|
28
|
+
this.cancelGuards(navId);
|
|
29
|
+
// Create guard executions with individual cancellation support
|
|
30
|
+
const guardExecutions = guards.map((guard, index) => new GuardExecution(guard, context, index));
|
|
31
|
+
this.activeGuardSets.set(navId, guardExecutions);
|
|
32
|
+
try {
|
|
33
|
+
// Execute all guards in parallel
|
|
34
|
+
const guardPromises = guardExecutions.map(execution => execution.getPromise());
|
|
35
|
+
const results = await Promise.all(guardPromises);
|
|
36
|
+
// Process results in order - first failure wins
|
|
37
|
+
for (let i = 0; i < results.length; i++) {
|
|
38
|
+
const guardResult = results[i];
|
|
39
|
+
if (!guardResult)
|
|
40
|
+
continue;
|
|
41
|
+
const { result, error } = guardResult;
|
|
42
|
+
if (error) {
|
|
43
|
+
// Abort remaining guards and return error
|
|
44
|
+
abortRemainingGuards(guardExecutions, i + 1);
|
|
45
|
+
return { allowed: false, error };
|
|
46
|
+
}
|
|
47
|
+
// Check if navigation was aborted
|
|
48
|
+
if (context.signal.aborted) {
|
|
49
|
+
return { allowed: false };
|
|
50
|
+
}
|
|
51
|
+
// Process guard result
|
|
52
|
+
if (result === false) {
|
|
53
|
+
// Guard denied navigation - abort remaining guards
|
|
54
|
+
abortRemainingGuards(guardExecutions, i + 1);
|
|
55
|
+
return { allowed: false };
|
|
56
|
+
}
|
|
57
|
+
if (typeof result === 'string') {
|
|
58
|
+
// Guard returned redirect path - abort remaining guards
|
|
59
|
+
abortRemainingGuards(guardExecutions, i + 1);
|
|
60
|
+
return {
|
|
61
|
+
allowed: false,
|
|
62
|
+
redirect: { redirect: result, replace: false },
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (typeof result === 'object' && result.redirect) {
|
|
66
|
+
// Guard returned redirect config - abort remaining guards
|
|
67
|
+
abortRemainingGuards(guardExecutions, i + 1);
|
|
68
|
+
return {
|
|
69
|
+
allowed: false,
|
|
70
|
+
redirect: result,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
// Guard allowed (result === true), continue to next guard
|
|
74
|
+
}
|
|
75
|
+
// All guards allowed navigation
|
|
76
|
+
return { allowed: true };
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
// Clean up active guards
|
|
80
|
+
this.activeGuardSets.delete(navId);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/** @codexApi {"parent":"pithy.router.guards","name":"cancelGuards","stability":"stable","signature":"(navId: NavigationId) => void","description":"Cancel all active guards for a navigation"} */
|
|
84
|
+
/**
|
|
85
|
+
* Cancel all guards for a navigation
|
|
86
|
+
*/
|
|
87
|
+
cancelGuards(navId) {
|
|
88
|
+
const guardExecutions = this.activeGuardSets.get(navId);
|
|
89
|
+
if (guardExecutions) {
|
|
90
|
+
guardExecutions.forEach(execution => execution.abort());
|
|
91
|
+
this.activeGuardSets.delete(navId);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/router/features/guards/index.ts"],"names":[],"mappings":"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"}
|