( opts: RouterIntegrationOptions<S>, )
| 96 | * Create an app-bound router integration. |
| 97 | */ |
| 98 | export function createRouterIntegration<S>( |
| 99 | opts: RouterIntegrationOptions<S>, |
| 100 | ): RouterIntegration<S> { |
| 101 | let routeRegistry = createRouteRegistry(opts.routes); |
| 102 | let routeMap = routeRegistry.routeMap; |
| 103 | let recordById = routeRegistry.recordById; |
| 104 | if (!routeMap.has(opts.initialRoute)) { |
| 105 | throw new ZrUiError( |
| 106 | "ZRUI_INVALID_PROPS", |
| 107 | `initialRoute \"${opts.initialRoute}\" was not found in routes`, |
| 108 | ); |
| 109 | } |
| 110 | |
| 111 | let state = createRouterState(opts.initialRoute, { |
| 112 | ...(opts.maxHistoryDepth === undefined ? {} : { maxDepth: opts.maxHistoryDepth }), |
| 113 | }); |
| 114 | |
| 115 | const focusSnapshotsByVisitId = new Map<number, WidgetFocusSnapshot>(); |
| 116 | |
| 117 | function normalizeKnownRouteId(routeId: string): string { |
| 118 | const normalized = routeId.trim(); |
| 119 | if (!normalized) { |
| 120 | throw new ZrUiError("ZRUI_INVALID_PROPS", "route id must be a non-empty string"); |
| 121 | } |
| 122 | if (!routeMap.has(normalized)) { |
| 123 | throw new ZrUiError("ZRUI_INVALID_PROPS", `unknown route id: ${normalized}`); |
| 124 | } |
| 125 | return normalized; |
| 126 | } |
| 127 | |
| 128 | function resolveGuardedNavigation( |
| 129 | routeId: string, |
| 130 | params: RouteParams | undefined, |
| 131 | action: "navigate" | "replace" | "back", |
| 132 | ): Readonly<{ routeId: string; params: RouteParams }> | null { |
| 133 | const from = currentRouteFromState(state); |
| 134 | let resolvedRouteId = normalizeKnownRouteId(routeId); |
| 135 | let resolvedParams = normalizeRouteParams(params); |
| 136 | const seen = new Set<string>(); |
| 137 | |
| 138 | for (let depth = 0; depth <= GUARD_MAX_REDIRECT_DEPTH; depth += 1) { |
| 139 | const record = recordById.get(resolvedRouteId); |
| 140 | if (!record) { |
| 141 | throw new ZrUiError( |
| 142 | "ZRUI_INVALID_STATE", |
| 143 | `route id "${resolvedRouteId}" is not registered`, |
| 144 | ); |
| 145 | } |
| 146 | const to = Object.freeze({ id: resolvedRouteId, params: resolvedParams }); |
| 147 | let redirected = false; |
| 148 | for (const ancestryRouteId of record.ancestry) { |
| 149 | const ancestryRoute = routeMap.get(ancestryRouteId); |
| 150 | if (!ancestryRoute) { |
| 151 | throw new ZrUiError( |
| 152 | "ZRUI_INVALID_STATE", |
| 153 | `route id "${ancestryRouteId}" is not registered`, |
| 154 | ); |
| 155 | } |
no test coverage detected