@real-router/core 0.1.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.
@@ -0,0 +1,216 @@
1
+ import { ErrorCodeKeys, ErrorCodeValues, EventToNameMap, ErrorCodeToValueMap, State, DefaultDependencies, Route, Options, Router } from 'core-types';
2
+ export { ActivationFn, ActivationFnFactory, CancelFn, Config, DefaultDependencies, DoneFn, Listener, Middleware, MiddlewareFactory, NavigationOptions, Options, Params, Plugin, PluginFactory, Route, Router, SimpleState, State, StateMeta, SubscribeFn, SubscribeState, Subscription, Unsubscribe } from 'core-types';
3
+
4
+ type ConstantsKeys = "UNKNOWN_ROUTE";
5
+ type Constants = Record<ConstantsKeys, string>;
6
+ type ErrorCodes = Record<ErrorCodeKeys, ErrorCodeValues>;
7
+ /**
8
+ * Error codes for router operations.
9
+ * Used to identify specific failure scenarios in navigation and lifecycle.
10
+ * Frozen to prevent accidental modifications.
11
+ */
12
+ declare const errorCodes: ErrorCodeToValueMap;
13
+ /**
14
+ * General router constants.
15
+ * Special route names and identifiers.
16
+ */
17
+ declare const constants: Constants;
18
+ /**
19
+ * Event names for router event system.
20
+ * Used with addEventListener/removeEventListener for reactive subscriptions.
21
+ */
22
+ declare const events: EventToNameMap;
23
+
24
+ declare class RouterError extends Error {
25
+ [key: string]: unknown;
26
+ readonly segment: string | undefined;
27
+ readonly path: string | undefined;
28
+ readonly redirect: State | undefined;
29
+ code: string;
30
+ /**
31
+ * Creates a new RouterError instance.
32
+ *
33
+ * The options object accepts built-in fields (message, segment, path, redirect)
34
+ * and any additional custom fields, which will all be attached to the error instance.
35
+ *
36
+ * @param code - The error code (e.g., "ROUTE_NOT_FOUND", "CANNOT_ACTIVATE")
37
+ * @param options - Optional configuration object
38
+ * @param options.message - Custom error message (defaults to code if not provided)
39
+ * @param options.segment - The route segment where the error occurred
40
+ * @param options.path - The full path where the error occurred
41
+ * @param options.redirect - Optional redirect state for navigation errors
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * // Basic error
46
+ * const err1 = new RouterError("ROUTE_NOT_FOUND");
47
+ *
48
+ * // Error with custom message
49
+ * const err2 = new RouterError("ERR", { message: "Something went wrong" });
50
+ *
51
+ * // Error with context and custom fields
52
+ * const err3 = new RouterError("CANNOT_ACTIVATE", {
53
+ * message: "Insufficient permissions",
54
+ * segment: "admin",
55
+ * path: "/admin/users",
56
+ * userId: "123" // custom field
57
+ * });
58
+ *
59
+ * // Error with redirect
60
+ * const err4 = new RouterError("TRANSITION_ERR", {
61
+ * redirect: { name: "home", path: "/", params: {} }
62
+ * });
63
+ * ```
64
+ */
65
+ constructor(code: string, { message, segment, path, redirect, ...rest }?: {
66
+ [key: string]: unknown;
67
+ message?: string | undefined;
68
+ segment?: string | undefined;
69
+ path?: string | undefined;
70
+ redirect?: State | undefined;
71
+ });
72
+ /**
73
+ * Updates the error code and conditionally updates the message.
74
+ *
75
+ * If the current message is one of the standard error code values
76
+ * (e.g., "ROUTE_NOT_FOUND", "SAME_STATES"), it will be replaced with the new code.
77
+ * This allows keeping error messages in sync with codes when using standard error codes.
78
+ *
79
+ * If the message is custom (not a standard error code), it will be preserved.
80
+ *
81
+ * @param newCode - The new error code to set
82
+ *
83
+ * @example
84
+ * // Message follows code (standard error code as message)
85
+ * const err = new RouterError("ROUTE_NOT_FOUND", { message: "ROUTE_NOT_FOUND" });
86
+ * err.setCode("CUSTOM_ERROR"); // message becomes "CUSTOM_ERROR"
87
+ *
88
+ * @example
89
+ * // Custom message is preserved
90
+ * const err = new RouterError("ERR", { message: "Custom error message" });
91
+ * err.setCode("NEW_CODE"); // message stays "Custom error message"
92
+ */
93
+ setCode(newCode: string): void;
94
+ /**
95
+ * Copies properties from another Error instance to this RouterError.
96
+ *
97
+ * This method updates the message, cause, and stack trace from the provided error.
98
+ * Useful for wrapping native errors while preserving error context.
99
+ *
100
+ * @param err - The Error instance to copy properties from
101
+ * @throws {TypeError} If err is null or undefined
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * const routerErr = new RouterError("TRANSITION_ERR");
106
+ * try {
107
+ * // some operation that might fail
108
+ * } catch (nativeErr) {
109
+ * routerErr.setErrorInstance(nativeErr);
110
+ * throw routerErr;
111
+ * }
112
+ * ```
113
+ */
114
+ setErrorInstance(err: Error): void;
115
+ /**
116
+ * Adds custom fields to the error object.
117
+ *
118
+ * This method allows attaching arbitrary data to the error for debugging or logging purposes.
119
+ * All fields become accessible as properties on the error instance and are included in JSON serialization.
120
+ *
121
+ * Reserved method names (setCode, setErrorInstance, setAdditionalFields, hasField, getField, toJSON)
122
+ * are automatically filtered out to prevent accidental overwriting of class methods.
123
+ *
124
+ * @param fields - Object containing custom fields to add to the error
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * const err = new RouterError("CANNOT_ACTIVATE");
129
+ * err.setAdditionalFields({
130
+ * userId: "123",
131
+ * attemptedRoute: "/admin",
132
+ * reason: "insufficient permissions"
133
+ * });
134
+ *
135
+ * console.log(err.userId); // "123"
136
+ * console.log(JSON.stringify(err)); // includes all custom fields
137
+ * ```
138
+ */
139
+ setAdditionalFields(fields: Record<string, unknown>): void;
140
+ /**
141
+ * Checks if a custom field exists on the error object.
142
+ *
143
+ * This method checks for both custom fields added via setAdditionalFields()
144
+ * and built-in fields (code, message, segment, etc.).
145
+ *
146
+ * @param key - The field name to check
147
+ * @returns `true` if the field exists, `false` otherwise
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * const err = new RouterError("ERR", { segment: "users" });
152
+ * err.setAdditionalFields({ userId: "123" });
153
+ *
154
+ * err.hasField("userId"); // true
155
+ * err.hasField("segment"); // true
156
+ * err.hasField("unknown"); // false
157
+ * ```
158
+ */
159
+ hasField(key: string): boolean;
160
+ /**
161
+ * Retrieves a custom field value from the error object.
162
+ *
163
+ * This method can access both custom fields and built-in fields.
164
+ * Returns `undefined` if the field doesn't exist.
165
+ *
166
+ * @param key - The field name to retrieve
167
+ * @returns The field value, or `undefined` if it doesn't exist
168
+ *
169
+ * @example
170
+ * ```typescript
171
+ * const err = new RouterError("ERR");
172
+ * err.setAdditionalFields({ userId: "123", role: "admin" });
173
+ *
174
+ * err.getField("userId"); // "123"
175
+ * err.getField("role"); // "admin"
176
+ * err.getField("code"); // "ERR" (built-in field)
177
+ * err.getField("unknown"); // undefined
178
+ * ```
179
+ */
180
+ getField(key: string): unknown;
181
+ /**
182
+ * Serializes the error to a JSON-compatible object.
183
+ *
184
+ * This method is automatically called by JSON.stringify() and includes:
185
+ * - Built-in fields: code, message, segment (if set), path (if set), redirect (if set)
186
+ * - All custom fields added via setAdditionalFields() or constructor
187
+ * - Excludes: stack trace (for security/cleanliness)
188
+ *
189
+ * @returns A plain object representation of the error, suitable for JSON serialization
190
+ *
191
+ * @example
192
+ * ```typescript
193
+ * const err = new RouterError("ROUTE_NOT_FOUND", {
194
+ * message: "Route not found",
195
+ * path: "/admin/users/123"
196
+ * });
197
+ * err.setAdditionalFields({ userId: "123" });
198
+ *
199
+ * JSON.stringify(err);
200
+ * // {
201
+ * // "code": "ROUTE_NOT_FOUND",
202
+ * // "message": "Route not found",
203
+ * // "path": "/admin/users/123",
204
+ * // "userId": "123"
205
+ * // }
206
+ * ```
207
+ */
208
+ toJSON(): Record<string, unknown>;
209
+ }
210
+
211
+ /**
212
+ * Creates a new router instance.
213
+ */
214
+ declare const createRouter: <Dependencies extends DefaultDependencies = DefaultDependencies>(routes?: Route<Dependencies>[], options?: Partial<Options>, dependencies?: Dependencies) => Router<Dependencies>;
215
+
216
+ export { type Constants, type ErrorCodes, RouterError, constants, createRouter, errorCodes, events };
@@ -0,0 +1 @@
1
+ var e=require("type-guards"),t=require("route-tree"),r=Symbol("real-router.routeTree"),n=Symbol("real-router.routeDefinitions"),o=Symbol("real-router.resolvedForwardMap"),a=Symbol("real-router.rootPath"),i=Symbol("real-router.config"),s=Object.freeze({ROUTER_NOT_STARTED:"NOT_STARTED",NO_START_PATH_OR_STATE:"NO_START_PATH_OR_STATE",ROUTER_ALREADY_STARTED:"ALREADY_STARTED",ROUTE_NOT_FOUND:"ROUTE_NOT_FOUND",SAME_STATES:"SAME_STATES",CANNOT_DEACTIVATE:"CANNOT_DEACTIVATE",CANNOT_ACTIVATE:"CANNOT_ACTIVATE",TRANSITION_ERR:"TRANSITION_ERR",TRANSITION_CANCELLED:"CANCELLED"}),c={UNKNOWN_ROUTE:"@@real-router/UNKNOWN_ROUTE"},u="onStart",d="onStop",f="onTransitionStart",l="onTransitionCancel",p="onTransitionSuccess",m="onTransitionError",h={ROUTER_START:"$start",ROUTER_STOP:"$stop",TRANSITION_START:"$$start",TRANSITION_CANCEL:"$$cancel",TRANSITION_SUCCESS:"$$success",TRANSITION_ERROR:"$$error"},w=new WeakSet;function v(e){if(null!==e&&"object"==typeof e&&!Object.isFrozen(e))if(Object.freeze(e),Array.isArray(e))for(const t of e)v(t);else for(const t in e)v(e[t])}function y(e){return e?(w.has(e)||(v(e),w.add(e)),e):e}function g(e){switch(e){case"never":return"never";case"always":return"always";default:return"default"}}function T(e){const t={trailingSlashMode:g(e.trailingSlash),queryParamsMode:e.queryParamsMode,urlParamsEncoding:e.urlParamsEncoding};return void 0!==e.queryParams&&(t.queryParams=e.queryParams),t}var S=new Set(Object.values(s)),E=new Set(["code","segment","path","redirect"]),R=new Set(["setCode","setErrorInstance","setAdditionalFields","hasField","getField","toJSON"]),b=class extends Error{segment;path;redirect;code;constructor(e,{message:t,segment:r,path:n,redirect:o,...a}={}){super(t??e),this.code=e,this.segment=r,this.path=n,this.redirect=o?function(e){if(!e)return e;if("object"!=typeof(t=e)||null===t||"string"!=typeof t.name||"string"!=typeof t.path||"object"!=typeof t.params||null===t.params)throw new TypeError("[deepFreezeState] Expected valid State object, got: "+typeof e);var t;const r=structuredClone(e),n=new WeakSet;return function e(t){if(null===t||"object"!=typeof t)return;if(n.has(t))return;n.add(t),Object.freeze(t);const r=Array.isArray(t)?t:Object.values(t);for(const t of r)e(t)}(r),r}(o):void 0;for(const[e,t]of Object.entries(a)){if(E.has(e))throw new TypeError(`[RouterError] Cannot set reserved property "${e}"`);R.has(e)||(this[e]=t)}}setCode(e){this.code=e,S.has(this.message)&&(this.message=e)}setErrorInstance(e){if(!e)throw new TypeError("[RouterError.setErrorInstance] err parameter is required and must be an Error instance");this.message=e.message,this.cause=e.cause,this.stack=e.stack??""}setAdditionalFields(e){for(const[t,r]of Object.entries(e)){if(E.has(t))throw new TypeError(`[RouterError.setAdditionalFields] Cannot set reserved property "${t}"`);R.has(t)||(this[t]=r)}}hasField(e){return e in this}getField(e){return this[e]}toJSON(){const e={code:this.code,message:this.message};void 0!==this.segment&&(e.segment=this.segment),void 0!==this.path&&(e.path=this.path),void 0!==this.redirect&&(e.redirect=this.redirect);const t=new Set(["code","message","segment","path","redirect","stack"]);for(const r in this)Object.hasOwn(this,r)&&!t.has(r)&&(e[r]=this[r]);return e}};function O(e,t){if("string"!=typeof t)throw new TypeError(`[router.${e}]: dependency name must be a string, got ${typeof t}`)}function N(e,t){const r=Object.keys(e).length;if(20===r)console.warn(`[router.${t}] 20 dependencies registered. Consider if all are necessary.`);else if(50===r)console.error(`[router.${t}] 50 dependencies registered! This indicates architectural problems. Hard limit at 100.`);else if(r>=100)throw new Error(`[router.${t}] Dependency limit exceeded (100). Current: ${r}. This is likely a bug in your code. If you genuinely need more dependencies, your architecture needs refactoring.`)}function A(e){return e.name?e.name:"anonymous"}function $(t,r){if("function"!=typeof t)throw new TypeError(`[router.useMiddleware] Middleware factory must return a function, got ${e.getTypeDescription(t)}. Factory: ${A(r)}`)}function I(t){const r=new Set,n=new Map;return t.useMiddleware=(...o)=>{!function(e,t){const r=e+t;if(r>50)throw new Error(`[router.useMiddleware] Middleware limit exceeded (50). Current: ${t}, Attempting to add: ${e}. This indicates an architectural problem. Consider consolidating middleware.`);r>=30?console.error(`[router.useMiddleware] ${r} middleware registered! This is excessive and will impact performance. Hard limit at 50.`):r>=15&&console.warn(`[router.useMiddleware] ${r} middleware registered. Consider if all are necessary.`)}(o.length,r.size),o.forEach((t,n)=>{if(function(t,r){if("function"!=typeof t)throw new TypeError(`[router.useMiddleware] Expected middleware factory function at index ${r}, got ${e.getTypeDescription(t)}`)}(t,n),r.has(t))throw new Error(`[router.useMiddleware] Middleware factory already registered. To re-register, first unsubscribe the existing middleware. Factory: ${A(t)}`)});const a=[];try{for(const e of o){const r=e(t,t.getDependency);$(r,e),a.push({factory:e,middleware:r})}}catch(e){throw console.error("[router.useMiddleware] Failed to initialize middleware, rolling back",e),e}for(const{factory:e,middleware:t}of a)r.add(e),n.set(e,t);return()=>{for(const{factory:e}of a)r.delete(e)||console.warn("[router.useMiddleware] Attempted to remove non-existent middleware factory. This might indicate a memory leak or incorrect cleanup logic."),n.delete(e)}},t.clearMiddleware=()=>(r.clear(),n.clear(),t),t.getMiddlewareFactories=()=>[...r],t.getMiddlewareFunctions=()=>[...n.values()],t}var P=(e,t)=>{if(t)return t.setCode(e),t},_=(e,t)=>{const r=e.meta,n=t.meta,o=r?.params,a=n?.params,i=o&&a?{...o,...a}:o??a??{},s={id:1,options:{},redirected:!1,...n,...r,params:i};return{...e,meta:s}},j=(t,r,n)=>{const o=n?{segment:n}:{};void 0!==t&&("boolean"!=typeof t?e.isState(t)?r(void 0,t):e.isPromise(t)?t.then(e=>{"boolean"==typeof e?e?r():r(new b(s.TRANSITION_ERR,o)):r(void 0,e)},e=>{let t=o;e instanceof Error?(t={...o,message:e.message,stack:e.stack},"cause"in e&&void 0!==e.cause&&(t.cause=e.cause)):e&&"object"==typeof e&&(t={...o,...e}),r(new b(s.TRANSITION_ERR,t))}):r(new b(s.TRANSITION_ERR,{...o,message:"Invalid lifecycle result type: "+typeof t})):t?r():r(new b(s.TRANSITION_ERR,o)))},D=new Set(["code","segment","path","redirect"]);function k(e,t){const r=t?{segment:t}:{};if(e instanceof Error)return{...r,message:e.message,stack:e.stack,..."cause"in e&&void 0!==e.cause&&{cause:e.cause}};if(e&&"object"==typeof e){const t={};for(const[r,n]of Object.entries(e))D.has(r)||(t[r]=n);return{...r,...t}}return r}function C(e,t,r){try{e(t,r)}catch(e){console.error("[core:lifecycle] Error in lifecycle callback:",e)}}var x=(t,r,n,o,a,i,c)=>{let u=r;const d=o.filter(e=>t.has(e));if(0===d.length)return void C(c,void 0,u);let f=0;const l=(e,t)=>{if(e)if(e.redirect){const t=new b(a,{message:"Guards cannot redirect. Use middleware for redirects.",attemptedRedirect:e.redirect});p(t)}else p(e);else p(void 0,t)},p=(r,o)=>{if(i())return void C(c,new b(s.TRANSITION_CANCELLED),u);if(r)return void C(c,P(a,r),u);if(o&&o!==u&&e.isState(o)){if(o.name!==u.name){const e=new b(a,{message:"Guards cannot redirect to different route. Use middleware.",attemptedRedirect:{name:o.name,params:o.params,path:o.path}});return void C(c,e,u)}(o.params!==u.params||o.path!==u.path)&&console.error("[core:transition] Warning: State mutated during transition",{from:u,to:o}),u=_(o,u)}if(f>=d.length)return void C(c,void 0,u);const p=d[f++],m=t.get(p);try{const e=m.call(null,u,n,l);j(e,l,p)}catch(e){l(new b(s.TRANSITION_ERR,k(e,p)))}};p()};function L(e,t,r){try{e(t,r)}catch(e){console.error("[real-router:middleware] Error in middleware callback:",e)}}var M=".";function U(e){const t=[];for(let r=e.length-1;r>=0;r--)t.push(e[r]);return t}function F(e,t){const r=t.meta?.params[e];if(!r||"object"!=typeof r)return{};const n={};for(const e in r){if(!Object.hasOwn(r,e))continue;if(void 0===r[e])continue;const o=t.params[e];null!=o&&("string"==typeof o||"number"==typeof o||"boolean"==typeof o?n[e]=String(o):console.warn(`[transitionPath.extractSegmentParams] Unsupported param type for key "${e}": ${typeof o}. Only primitives (string, number, boolean) are supported.`,typeof o))}return n}function W(e){if(!e)return[""];const t=e.indexOf(M);if(-1===t)return[e];const r=e.indexOf(M,t+1);if(-1===r)return[e.slice(0,t),e];const n=e.indexOf(M,r+1);return-1===n?[e.slice(0,t),e.slice(0,r),e]:-1===e.indexOf(M,n+1)?[e.slice(0,t),e.slice(0,r),e.slice(0,n),e]:function(e){const t=e.split(M),r=t.length,n=[t[0]];let o=t[0].length;for(let a=1;a<r-1;a++)o+=1+t[a].length,n.push(e.slice(0,o));return n.push(e),n}(e)}function q(t,r){if(e.validateState(t,"getTransitionPath"),!r)return{intersection:"",toActivate:W(t.name),toDeactivate:[]};if(e.validateState(r,"getTransitionPath"),(t.meta?.options??{}).reload)return{intersection:"",toActivate:W(t.name),toDeactivate:U(W(r.name))};const n=void 0!==t.meta?.params,o=void 0!==r.meta?.params;if(!n&&!o)return{intersection:"",toActivate:W(t.name),toDeactivate:U(W(r.name))};if(t.name===r.name&&n&&o){const e=t.meta&&0===Object.keys(t.meta.params).length,n=r.meta&&0===Object.keys(r.meta.params).length;if(e&&n)return{intersection:t.name,toActivate:[],toDeactivate:[]}}const a=W(t.name),i=W(r.name),s=function(e,t,r,n,o){for(let a=0;a<o;a++){const o=r[a],i=n[a];if(o!==i)return a;const s=F(o,e),c=F(i,t),u=Object.keys(s),d=Object.keys(c);if(u.length!==d.length)return a;for(const e of u)if(s[e]!==c[e])return a}return o}(t,r,a,i,Math.min(i.length,a.length)),c=[];for(let e=i.length-1;e>=s;e--)c.push(i[e]);const u=a.slice(s);return{intersection:r&&s>0?i[s-1]:"",toDeactivate:c,toActivate:u}}function z(t,r,n,o,a){let i=!1,u=!1;const[d,f]=t.getLifecycleFunctions(),l=t.getMiddlewareFunctions(),p=r.name===c.UNKNOWN_ROUTE,m=()=>i||!t.isActive(),h=(e,t)=>{u||(u=!0,a(e,t??r))};return(()=>{const{toDeactivate:a,toActivate:i}=q(r,n),c=!p&&i.length>0,u=l.length>0;var w;w=(o,a)=>{o?h(o,a):((e,t)=>{c?x(f,e,n,i,s.CANNOT_ACTIVATE,m,(e,r)=>{t(e,r)}):t(void 0,e)})(a,(o,a)=>{o?h(o,a):((t,r)=>{u?((t,r,n,o,a)=>{let i=r,c=0;const u=(e,t)=>{e?d(e):d(void 0,t)},d=(r,d)=>{if(o())return void L(a,new b(s.TRANSITION_CANCELLED),i);if(r)return void L(a,P(s.TRANSITION_ERR,r),i);if(d&&d!==i&&e.isState(d)&&((d.name!==i.name||d.params!==i.params||d.path!==i.path)&&console.error("[real-router:middleware] Warning: State mutated during middleware execution",{from:i,to:d}),i=_(d,i)),c>=t.length)return void L(a,void 0,i);const f=t[c++];try{const e=f.call(null,i,n,u);j(e,u)}catch(e){u(new b(s.TRANSITION_ERR,k(e)))}};d()})(l,t,n,m,(e,t)=>{r(e,t)}):r(void 0,t)})(a,(e,o)=>{if(e)h(e,o);else{if(n){const e=W(r.name),o=W(n.name),a=new Set(e);for(const e of o)!a.has(e)&&d.has(e)&&t.clearCanDeactivate(e)}h(void 0,o)}})})},n&&!o.forceDeactivate&&a.length>0?x(d,r,n,a,s.CANNOT_DEACTIVATE,m,w):w(void 0,r)})(),()=>{i||u||(i=!0,h(new b(s.TRANSITION_CANCELLED)))}}var B=()=>{};function K(e,...t){try{e(...t)}catch(e){console.error("[router.navigate] Error in navigation callback:",e)}}function V(t){let r=null,n=!1;return t.navigate=function(r,n,o,a){const{params:i,opts:c,callback:u}=function(e,t,r){if("function"==typeof e)return{params:{},opts:{},callback:e};const n=e??{};return"function"==typeof t?{params:n,opts:{},callback:t}:{params:n,opts:t??{},callback:r??B}}(n,o,a);if(!t.isStarted())return K(u,new b(s.ROUTER_NOT_STARTED)),B;if(!e.isNavigationOptions(c))throw new TypeError(`[router.navigate] Invalid options: ${e.getTypeDescription(c)}. Expected NavigationOptions object.`);const d=t.buildStateWithSegments(r,i);if(!d){const e=new b(s.ROUTE_NOT_FOUND);return K(u,e),t.invokeEventListeners(h.TRANSITION_ERROR,void 0,t.getState(),e),B}const{state:f,segments:l}=d,p=t.makeState(f.name,f.params,t.buildPathWithSegments(f.name,f.params,l),{params:f.meta,options:c,redirected:c.redirected??!1});if(c.skipTransition)return K(u,void 0,p),B;const m=t.getState();if(!c.reload&&!c.force&&t.areStatesEqual(m,p,!1)){const e=new b(s.SAME_STATES);return K(u,e),t.invokeEventListeners(h.TRANSITION_ERROR,p,m,e),B}return t.navigateToState(p,m,c,u,!0)},t.navigateToDefault=function(r,n){const o=t.getOptions();if(!o.defaultRoute)return B;let a={},i=B;if("function"==typeof r?i=r:r&&(a=r,i=n??B),!e.isNavigationOptions(a))throw new TypeError(`[router.navigateToDefault] Invalid options: ${e.getTypeDescription(a)}. Expected NavigationOptions object.`);return t.navigate(o.defaultRoute,o.defaultParams,a,i)},t.navigateToState=(e,o,a,i,u)=>(n&&console.warn("[router.navigate] Concurrent navigation detected on shared router instance. For SSR, use router.clone() to create isolated instance per request."),r&&(r(),r=null),n=!1,n=!0,t.invokeEventListeners(h.TRANSITION_START,e,o),r=z(t,e,o,a,(d,f)=>{if(n=!1,r=null,d)d.code===s.TRANSITION_CANCELLED?t.invokeEventListeners(h.TRANSITION_CANCEL,e,o):t.invokeEventListeners(h.TRANSITION_ERROR,e,o,d),K(i,d);else if(f.name===c.UNKNOWN_ROUTE||t.hasRoute(f.name))t.setState(f),u&&t.invokeEventListeners(h.TRANSITION_SUCCESS,f,o,a),K(i,void 0,f);else{const e=new b(s.ROUTE_NOT_FOUND,{routeName:f.name});K(i,e),t.invokeEventListeners(h.TRANSITION_ERROR,void 0,t.getState(),e)}}),r),t.isNavigating=()=>t.isStarted()&&n,t}function H(e,t,...r){if(0===t.size)return;const n=[...t];for(const t of n)try{Function.prototype.apply.call(t,void 0,r)}catch(t){console.error(`[Router] Error in listener for ${e}:`,t)}}function G(t){const r={};function n(e){const t=r[e];if(t)return t;const n=new Set;return r[e]=n,n}let o=null;const a=()=>(o??={[h.ROUTER_START]:0,[h.TRANSITION_START]:0,[h.TRANSITION_SUCCESS]:0,[h.TRANSITION_ERROR]:0,[h.TRANSITION_CANCEL]:0,[h.ROUTER_STOP]:0},o),i=new Set([h.ROUTER_START,h.TRANSITION_START,h.TRANSITION_SUCCESS,h.TRANSITION_ERROR,h.TRANSITION_CANCEL,h.ROUTER_STOP]),s=(e,t)=>{if(!i.has(e))throw new Error(`Invalid event name: ${e}`);if("function"!=typeof t)throw new TypeError(`Expected callback to be a function for event ${e}`)};t.invokeEventListeners=(t,r,o,s)=>{(e=>{if(!i.has(e))throw new Error(`Invalid event name: ${e}`);if(a()[e]>=5)throw new Error(`[Router] Maximum recursion depth (5) exceeded for event: ${e}`)})(t);const c=a();try{switch(c[t]++,t){case h.TRANSITION_START:case h.TRANSITION_CANCEL:if(!r)throw new TypeError(`[router.invokeEventListeners] toState is required for event "${t}"`);if(!e.isState(r))throw new TypeError(`[router.invokeEventListeners] toState is invalid for event "${t}". Expected State object with name, path, and params.`);if(o&&!e.isState(o))throw new TypeError(`[router.invokeEventListeners] fromState is invalid for event "${t}". Expected State object with name, path, and params.`);H(t,n(t),r,o);break;case h.TRANSITION_ERROR:if(r&&!e.isState(r))throw new TypeError(`[router.invokeEventListeners] toState is invalid for event "${t}". Expected State object with name, path, and params.`);if(o&&!e.isState(o))throw new TypeError(`[router.invokeEventListeners] fromState is invalid for event "${t}". Expected State object with name, path, and params.`);if(!s)throw new TypeError(`[router.invokeEventListeners] error is required for event "${t}"`);if(!(s instanceof b))throw new TypeError(`[router.invokeEventListeners] error must be a RouterError instance for event "${t}". Got: ${"object"==typeof s?s.constructor.name:typeof s}`);H(t,n(t),r,o,s);break;case h.TRANSITION_SUCCESS:if(!r)throw new TypeError(`[router.invokeEventListeners] toState is required for event "${t}"`);if(!e.isState(r))throw new TypeError(`[router.invokeEventListeners] toState is invalid for event "${t}". Expected State object with name, path, and params.`);if(o&&!e.isState(o))throw new TypeError(`[router.invokeEventListeners] fromState is invalid for event "${t}". Expected State object with name, path, and params.`);if(!s)throw new TypeError(`[router.invokeEventListeners] options is required for event "${t}"`);if(s instanceof b)throw new TypeError(`[router.invokeEventListeners] options cannot be a RouterError for event "${t}". Use TRANSITION_ERROR event for errors.`);if(!e.isNavigationOptions(s))throw new TypeError(`[router.invokeEventListeners] options is invalid for event "${t}". Expected NavigationOptions object.`);H(t,n(t),r,o,s);break;default:H(t,n(t))}}finally{c[t]--}},t.hasListeners=e=>{if(!i.has(e))return!1;const t=r[e];return void 0!==t&&t.size>0},t.removeEventListener=(e,t)=>{s(e,t);const n=r[e];n&&0!==n.size&&(n.delete(t)||console.warn(`[Router] Attempted to remove non-existent listener for "${e}". This might indicate a memory leak or incorrect cleanup logic.`))},t.addEventListener=(e,r)=>{s(e,r);const o=n(e);if(o.has(r))throw new Error(`[router.addEventListener] Listener already exists for event "${e}". Each listener function can only be registered once per event. Store the returned unsubscribe function to remove the listener.`);if(1e3===o.size&&console.warn(`[router.addEventListener] Warning: Event "${e}" has ${o.size} listeners. This might indicate a memory leak.`),o.size>=1e4)throw new Error(`[router.addEventListener] Maximum listener limit (10000) reached for event "${e}". This is a critical memory leak. The application is creating listeners exponentially. Check for loops or recursive calls that register listeners.`);return o.add(r),()=>{t.removeEventListener(e,r)}},t.subscribe=function(e){if("function"!=typeof e)throw new TypeError("[router.subscribe] Expected a function. For Observable pattern use router[Symbol.observable]().subscribe(observer)");return t.addEventListener(h.TRANSITION_SUCCESS,(t,r)=>{e({route:t,previousRoute:r})})};const c="function"==typeof Symbol&&Symbol.observable||"@@observable",u=new WeakMap;return t[c]=function(){return{subscribe(e,r={}){const n="function"==typeof e?{next:e}:e,o=u.get(n);if(o?.active)return console.warn("[router.observable] Duplicate subscription prevented. Same observer already subscribed."),{unsubscribe:o.unsubscribe,get closed(){return!o.active}};const{signal:a,replay:i=!0}=r;if(a?.aborted)return{unsubscribe:()=>{},closed:!0};let s=!1;const c=e=>{if(!s&&n.next)try{n.next(e)}catch(e){if(console.error("[router.observable] Error in observer.next:",e),n.error)try{n.error(e)}catch(e){console.error("[router.observable] Error in observer.error:",e)}}},d=t.addEventListener(h.TRANSITION_SUCCESS,(e,t)=>{c({route:e,previousRoute:t})}),f={unsubscribe:()=>{if(!s&&(s=!0,f.active=!1,d(),n.complete))try{n.complete()}catch(e){console.error("[router.observable] Error in observer.complete:",e)}},active:!0};if(u.set(n,f),a&&a.addEventListener("abort",()=>{f.unsubscribe()},{once:!0}),i){const e=t.getState();e&&queueMicrotask(()=>{c({route:e,previousRoute:void 0})})}return{unsubscribe:f.unsubscribe,get closed(){return s}}},[c](){return this}}},t}var Y={defaultRoute:"",defaultParams:{},trailingSlash:"preserve",queryParamsMode:"loose",queryParams:{arrayFormat:"none",booleanFormat:"none",nullFormat:"default"},caseSensitive:!1,urlParamsEncoding:"default",allowNotFound:!0,rewritePathOnMatch:!0},J={trailingSlash:["strict","never","always","preserve"],queryParamsMode:["default","strict","loose"],urlParamsEncoding:["default","uri","uriComponent","none"]},Q={arrayFormat:["none","brackets","index","comma"],booleanFormat:["none","string","empty-true"],nullFormat:["default","hidden"]};function Z(t,r,n,o){if(n&&"object"==typeof n)return function(t,r,n){if(!t||"object"!=typeof t||t.constructor!==Object)throw new TypeError(`[router.${n}] Invalid type for "${r}": expected plain object, got ${e.getTypeDescription(t)}`);for(const e in t)if(Object.getOwnPropertyDescriptor(t,e)?.get)throw new TypeError(`[router.${n}] Getters not allowed in "${r}": "${e}"`)}(r,t,o),void("queryParams"===t&&function(t,r){for(const n in t){if(!e.isObjKey(n,Q)){const e=Object.keys(Q).map(e=>`"${e}"`).join(", ");throw new TypeError(`[router.${r}] Unknown queryParams key: "${n}". Valid keys: ${e}`)}const o=t[n],a=Q[n];if(!a.includes(o)){const e=a.map(e=>`"${e}"`).join(", ");throw new TypeError(`[router.${r}] Invalid value for queryParams.${n}: expected one of ${e}, got "${String(o)}"`)}}}(r,o));if(typeof r!=typeof n)throw new TypeError(`[router.${o}] Invalid type for "${t}": expected ${typeof n}, got ${typeof r}`);t in J&&function(e,t,r){const n=J[e];if(!n.includes(t)){const o=n.map(e=>`"${e}"`).join(", ");throw new TypeError(`[router.${r}] Invalid value for "${e}": expected one of ${o}, got "${String(t)}"`)}}(t,r,o)}function X(e){Object.freeze(e);for(const t of Object.keys(e)){const r=e[t];r&&"object"==typeof r&&r.constructor===Object&&X(r)}return e}var ee="router.usePlugin",te={[u]:h.ROUTER_START,[d]:h.ROUTER_STOP,[p]:h.TRANSITION_SUCCESS,[f]:h.TRANSITION_START,[m]:h.TRANSITION_ERROR,[l]:h.TRANSITION_CANCEL},re=Object.keys(te).filter(t=>e.isObjKey(t,te));function ne(t){const r=new Set;function n(r){const n=r(t,t.getDependency);(t=>{if(!t||"object"!=typeof t||Array.isArray(t))throw new TypeError(`[router.usePlugin] Plugin factory must return an object, got ${e.getTypeDescription(t)}`);if("function"==typeof t.then)throw new TypeError("[router.usePlugin] Async plugin factories are not supported. Factory returned a Promise instead of a plugin object.");for(const r in t)if("teardown"!==r&&!e.isObjKey(r,te))throw new TypeError(`[router.usePlugin] Unknown property '${r}'. Plugin must only contain event handlers and optional teardown.`)})(n),Object.freeze(n);const o=[];for(const e of re)e in n&&("function"==typeof n[e]?(o.push(t.addEventListener(te[e],n[e])),e===u&&t.isStarted()&&console.warn(`[${ee}] Router already started, onStart will not be called`)):console.warn(`[${ee}] Property '${e}' is not a function, skipping`));return()=>{o.forEach(e=>{e()}),"function"==typeof n.teardown&&n.teardown()}}return t.getPlugins=()=>[...r],t.usePlugin=(...e)=>{((e,t)=>{const r=e+t;if(r>50)throw new Error("[router.usePlugin] Plugin limit exceeded (50)");r>=25?console.error(`[${ee}] ${r} plugins registered!`):r>=10&&console.warn(`[${ee}] ${r} plugins registered`)})(e.length,r.size);const t=function(e,t){const r=new Set;for(const n of e){if("function"!=typeof n)throw new TypeError("[router.usePlugin] Expected plugin factory function, got "+typeof n);if(t.has(n))throw new Error("[router.usePlugin] Plugin factory already registered. To re-register, first unsubscribe the existing plugin.");r.has(n)?console.warn(`[${ee}] Duplicate factory in batch, will be registered once`):r.add(n)}return r}(e,r),o=[];try{for(const e of t){const t=n(e);o.push({factory:e,cleanup:t})}}catch(e){for(const{cleanup:e}of o)try{e()}catch(e){console.error(`[${ee}] Cleanup error:`,e)}throw e}for(const{factory:e}of o)r.add(e);let a=!1;return()=>{if(!a){a=!0;for(const{factory:e}of o)r.delete(e);for(const{cleanup:e}of o)try{e()}catch(e){console.error(`[${ee}] Error during cleanup:`,e)}}}},t}function oe(t,r){if(!e.isBoolean(t)&&"function"!=typeof t)throw new TypeError(`[router.${r}] Handler must be a boolean or factory function, got ${e.getTypeDescription(t)}`)}function ae(t){const r=new Map,n=new Map,o=new Map,a=new Map,i=new Set;function s(r,n,o,a,s,c){if(i.has(n))throw new Error(`[router.${c}] Cannot modify route "${n}" during its own registration`);a.has(n)?console.warn(`[router.${c}] Overwriting existing ${r} handler for route "${n}"`):function(e,t){if(e>=200)throw new Error(`[router.${t}] Lifecycle handler limit exceeded (200). This indicates too many routes with individual handlers. Consider using middleware for cross-cutting concerns.`);e>=100?console.error(`[router.${t}] ${e} lifecycle handlers registered! This is excessive. Hard limit at 200.`):e>=50&&console.warn(`[router.${t}] ${e} lifecycle handlers registered. Consider consolidating logic.`)}(a.size+1,c);const u=e.isBoolean(o)?function(e){const t=()=>e;return()=>t}(o):o;a.set(n,u),i.add(n);try{const r=u(t,t.getDependency);if("function"!=typeof r)throw new TypeError(`[router.${c}] Factory must return a function, got ${e.getTypeDescription(r)}`);s.set(n,r)}catch(e){throw a.delete(n),e}finally{i.delete(n)}}return t.getLifecycleFactories=()=>{const e={},t={};for(const[t,n]of r)e[t]=n;for(const[e,r]of n)t[e]=r;return[e,t]},t.getLifecycleFunctions=()=>[o,a],t.canActivate=(r,o)=>(e.validateRouteName(r,"canActivate"),oe(o,"canActivate"),s("activate",r,o,n,a,"canActivate"),t),t.canDeactivate=(n,a)=>(e.validateRouteName(n,"canDeactivate"),oe(a,"canDeactivate"),s("deactivate",n,a,r,o,"canDeactivate"),t),t.clearCanDeactivate=(n,a=!1)=>{if(e.validateRouteName(n,"clearCanDeactivate"),i.has(n))throw new Error(`[router.clearCanDeactivate] Cannot modify route "${n}" during its own registration`);const s=r.delete(n),c=o.delete(n);return a||s||c||console.warn(`[router.clearCanDeactivate] No canDeactivate handler found for route "${n}"`),t},t.clearCanActivate=(r,o=!1)=>{if(e.validateRouteName(r,"clearCanActivate"),i.has(r))throw new Error(`[router.clearCanActivate] Cannot modify route "${r}" during its own registration`);const s=n.delete(r),c=a.delete(r);return o||s||c||console.warn(`[router.clearCanActivate] No canActivate handler found for route "${r}"`),t},t}function ie(e){return e[r]}function se(e,t){e[r]=t}function ce(e){return e[o]}function ue(e,t){e[o]=t}function de(e){return e[i]}function fe(e,r){const n=r??function(e){let t="";for(const r of e)r.name&&(t&&(t+="."),t+=r.name);return t}(e.segments);return{name:n,params:e.params,meta:t.getMetaFromSegments(e.segments)}}var le=Symbol("real-router.buildOptionsCache");function pe(r){return r.buildPath=(n,o)=>{if(!e.isString(n)||""===n)throw new TypeError("[real-router] buildPath: route must be a non-empty string, got "+("string"==typeof n?'""':typeof n));if(n===c.UNKNOWN_ROUTE)return e.isString(o?.path)?o.path:"";const a=de(r),i=Object.hasOwn(a.defaultParams,n)?{...a.defaultParams[n],...o}:o??{},s="function"==typeof a.encoders[n]?a.encoders[n]({...i}):i,u=r[le]??T(r.getOptions());return t.buildPath(ie(r),n,s,u)},r.buildPathWithSegments=(n,o,a)=>{if(!e.isString(n)||""===n)throw new TypeError("[real-router] buildPathWithSegments: route must be a non-empty string, got "+("string"==typeof n?'""':typeof n));if(n===c.UNKNOWN_ROUTE)return e.isString(o.path)?o.path:"";const i=de(r),s=Object.hasOwn(i.defaultParams,n)?{...i.defaultParams[n],...o}:o,u="function"==typeof i.encoders[n]?i.encoders[n]({...s}):s,d=r[le]??T(r.getOptions());return t.buildPath(ie(r),n,u,d,a)},r.matchPath=(n,o)=>{if(!e.isString(n))throw new TypeError("[real-router] matchPath: path must be a string, got "+typeof n);const a=r.getOptions(),i=function(e){return{...T(e),caseSensitive:e.caseSensitive,strictTrailingSlash:"strict"===e.trailingSlash,strongMatching:!1}}(a),s=t.matchSegments(ie(r),n,i);if(s){const e=fe(s),{name:t,params:i,meta:c}=e,{decoders:u}=de(r),d="function"==typeof u[t]?u[t](i):i,{name:f,params:l}=r.forwardState(t,d),p=a.rewritePathOnMatch?r.buildPath(f,l):n;return r.makeState(f,l,p,{params:c,options:{},source:o,redirected:!1})}},r.setRootPath=e=>{const o=r;o[a]=e,se(r,t.createRouteTree("",e,o[n],{skipValidation:!0}))},r.getRootPath=()=>r[a]||"",r}var me=()=>{},he=new b(s.NO_START_PATH_OR_STATE),we=new b(s.ROUTER_ALREADY_STARTED),ve=Symbol("started"),ye=Symbol("active");function ge(t){t[ve]=!1,t[ye]=!1;const r=()=>{t[ye]=!1};return t.isStarted=()=>!!t[ve],t.isActive=()=>!!t[ye],t.start=(...n)=>{const o=t.getOptions(),[a,i]=(e=>{if(e.length>2)throw new Error("Invalid number of arguments");const[t,r]=e;return t?"function"==typeof t?[void 0,t]:[t,r??me]:[void 0,me]})(n);let c=!1;if(t.isStarted()||t.isActive())return c=!0,i(we),t;if(!a&&!o.defaultRoute)return c=!0,t.hasListeners(h.TRANSITION_ERROR)&&t.invokeEventListeners(h.TRANSITION_ERROR,void 0,void 0,he),i(he),t;t[ye]=!0;const u=(e,r={})=>{t.navigateToState(e,void 0,r,(e,t)=>{f(e,t)},!1)},d={replace:!0},f=(e,n,o=!1)=>{e?(r(),o&&t.hasListeners(h.TRANSITION_ERROR)&&t.invokeEventListeners(h.TRANSITION_ERROR,void 0,void 0,e)):(t[ve]=!0,t.invokeEventListeners(h.ROUTER_START),t.invokeEventListeners(h.TRANSITION_SUCCESS,n,void 0,{replace:!0})),((e,t)=>{c?console.warn("[real-router] Callback already invoked"):(c=!0,i(e,t))})(e,n)},l=a??o.defaultRoute,p=((t,r)=>{if("string"==typeof t)return r.matchPath(t);if(e.isState(t)){try{r.buildPath(t.name,t.params)}catch{return}return t}})(l,t),m="string"==typeof l?l:"";return(void 0!==p||o.allowNotFound||o.defaultRoute&&!a)&&function(e,t){delete e[le],e[le]=T(t)}(t,o),p?u(p,d):o.defaultRoute&&!a?((e,r,n)=>{const o=t.buildState(e,r);if(!o)return void f(new b(s.ROUTE_NOT_FOUND,{routeName:e}),void 0,!0);const a=t.makeState(o.name,o.params,t.buildPath(o.name,o.params),{params:o.meta,options:n,redirected:!1});u(a,n)})(o.defaultRoute,o.defaultParams,d):o.allowNotFound?u(t.makeNotFoundState(m,d),d):f(new b(s.ROUTE_NOT_FOUND,{path:m}),void 0,!0),t},t.stop=()=>(r(),t.isStarted()&&(t[ve]=!1,t.setState(void 0),t.invokeEventListeners(h.ROUTER_STOP)),t),t}function Te(t,r){if(void 0!==t.canActivate&&"function"!=typeof t.canActivate)throw new TypeError(`[router.addRoute] canActivate must be a function for route "${r}", got ${e.getTypeDescription(t.canActivate)}`);if(void 0!==t.defaultParams){const n=t.defaultParams;if(null===n||"object"!=typeof n||Array.isArray(n))throw new TypeError(`[router.addRoute] defaultParams must be an object for route "${r}", got ${e.getTypeDescription(t.defaultParams)}`)}if(t.children)for(const e of t.children)Te(e,`${r}.${e.name}`)}function Se(e){const t=new Set;for(const r of e){const e=r.parser;for(const r of e.urlParams)t.add(r);for(const r of e.spatParams)t.add(r)}return t}function Ee(e){const t=new Set,r=/[*:]([A-Z_a-z]\w*)/g;let n;for(;null!==(n=r.exec(e));)t.add(n[1]);return t}function Re(e,t,r="",n=[]){for(const o of e){const e=r?`${r}.${o.name}`:o.name,a=[...n,o.path];if(e===t)return a;if(o.children&&t.startsWith(`${e}.`))return Re(o.children,t,e,a)}}function be(e){const t=new Set;for(const r of e)for(const e of Ee(r))t.add(e);return t}function Oe(e,t=""){const r=new Set;for(const n of e){const e=t?`${t}.${n.name}`:n.name;if(r.add(e),n.children)for(const t of Oe(n.children,e))r.add(t)}return r}function Ne(e,t=""){const r=new Map;for(const n of e){const e=t?`${t}.${n.name}`:n.name;if(n.forwardTo&&r.set(e,n.forwardTo),n.children)for(const[t,o]of Ne(n.children,e))r.set(t,o)}return r}function Ae(e,r,n,o,a){const i=function(e,t){const r=t.split(".");let n=e;for(const e of r)if(n=n.childrenByName.get(e),!n)return!1;return!0}(a,r),s=o.has(r);if(!i&&!s)throw new Error(`[router.addRoute] forwardTo target "${r}" does not exist for route "${e}"`);const c=be(Re(n,e)),u=function(e,r,n,o){return r?Se(t.getSegmentsByName(n,e)):be(Re(o,e))}(r,i,a,n),d=[...u].filter(e=>!c.has(e));if(d.length>0)throw new Error(`[router.addRoute] forwardTo target "${r}" requires params [${d.join(", ")}] that are not available in source route "${e}"`)}function $e(e,t,r){const n=Oe(e),o=Ne(e),a={...t};for(const[e,t]of o)a[e]=t;for(const[t,a]of o)Ae(t,a,e,n,r);for(const e of Object.keys(a))Pe(e,a)}function Ie(e,t){e.canActivate&&t.canActivate(e.name,e.canActivate)}function Pe(e,t,r=100){const n=new Set,o=[e];let a=e;for(;t[a];){const e=t[a];if(n.has(e)){const t=o.indexOf(e),r=[...o.slice(t),e];throw new Error(`Circular forwardTo: ${r.join(" → ")}`)}if(n.add(a),o.push(e),a=e,o.length>r)throw new Error(`forwardTo chain exceeds maximum depth (${r}): ${o.join(" → ")}`)}return a}function _e(e){const{forwardMap:t}=de(e),r={};for(const e of Object.keys(t))r[e]=Pe(e,t);ue(e,r)}function je(e,t){e.forwardTo&&(e.canActivate&&console.warn(`[real-router] Route "${e.name}" has both forwardTo and canActivate. canActivate will be ignored because forwardTo creates a redirect (industry standard). Move canActivate to the target route "${e.forwardTo}".`),de(t).forwardMap[e.name]=e.forwardTo)}function De(e,t){const r=de(t);e.decodeParams&&(r.decoders[e.name]=t=>e.decodeParams?.(t)??t),e.encodeParams&&(r.encoders[e.name]=t=>e.encodeParams?.(t)??t)}function ke(e,t){e.defaultParams&&(de(t).defaultParams[e.name]=e.defaultParams)}function Ce(e,t,r=""){for(const n of e){const e=r?`${r}.${n.name}`:n.name,o={...n,name:e};Ie(o,t),je(o,t),De(o,t),ke(o,t),n.children&&Ce(n.children,t,e)}}function xe(e,t){for(const r of Object.keys(e))t(r)&&delete e[r]}function Le(e){const t={name:e.name,path:e.path};return e.children&&(t.children=e.children.map(e=>Le(e))),t}function Me(e,t,r=""){for(let n=0;n<e.length;n++){const o=e[n],a=r?`${r}.${o.name}`:o.name;if(a===t)return e.splice(n,1),!0;if(o.children&&t.startsWith(`${a}.`)&&Me(o.children,t,a))return!0}return!1}function Ue(e,t,r){void 0!==r&&(null===r?delete e[t]:e[t]=r)}var Fe=new Set;function We(r){return r.isActiveRoute=(t,n={},o=!1,a=!0)=>{if(Fe.has(t)||(e.validateRouteName(t,"isActiveRoute"),Fe.add(t)),function(t){if(!e.isParams(t))throw new TypeError(`[router.isActiveRoute] Invalid params structure: ${e.getTypeDescription(t)}`)}(n),void 0!==o&&"boolean"!=typeof o)throw new TypeError("[router.isActiveRoute] strictEquality must be a boolean, got "+typeof o);if(void 0!==a&&"boolean"!=typeof a)throw new TypeError("[router.isActiveRoute] ignoreQueryParams must be a boolean, got "+typeof a);if(""===t)return console.warn('[real-router] isActiveRoute("") called with empty string. The root node is not considered active for any named route. To check if router has active state, use: router.getState() !== undefined'),!1;const i=r.getState();if(!i)return!1;const s=i.name;if(s!==t&&!s.startsWith(`${t}.`)&&!t.startsWith(`${s}.`))return!1;const c=de(r).defaultParams[t];if(o||s===t){const e=c?{...c,...n}:n;return r.areStatesEqual({name:t,params:e,path:""},i,a)}const u=i.params;return!!function(e,t){for(const r in e)if(e[r]!==t[r])return!1;return!0}(n,u)&&(!c||function(e,t,r){for(const n in e)if(!(n in r)&&e[n]!==t[n])return!1;return!0}(c,u,n))},r.shouldUpdateNode=t=>{if(!e.isString(t))throw new TypeError("[router.shouldUpdateNode] nodeName must be a string, got "+typeof t);return(e,r)=>{if(!e||"object"!=typeof e||!("name"in e))throw new TypeError("[router.shouldUpdateNode] toState must be valid State object");if(e.meta?.options.reload)return!0;if(""===t&&!r)return!0;const{intersection:n,toActivate:o,toDeactivate:a}=q(e,r);return t===n||!!o.includes(t)||a.includes(t)}},r.clone=(e={})=>{const n=ie(r),o=He(t.routeTreeToDefinitions(n),r.getOptions(),e);o.useMiddleware(...r.getMiddlewareFactories()),o.usePlugin(...r.getPlugins());const a=de(r);!function(e,t){e[i]=t}(o,{decoders:{...a.decoders},encoders:{...a.encoders},defaultParams:structuredClone(a.defaultParams),forwardMap:{...a.forwardMap}}),ue(o,{...ce(r)});const[s,c]=r.getLifecycleFactories();for(const e of Object.keys(s))o.canDeactivate(e,s[e]);for(const e of Object.keys(c))o.canActivate(e,c[e]);return o},r}function qe(e){return null===e?"null":Array.isArray(e)?"array":typeof e}function ze(e,t){if(null!=e){if("function"!=typeof e)throw new TypeError(`[real-router] updateRoute: ${t} must be a function or null, got ${typeof e}`);if("AsyncFunction"===e.constructor.name)throw new TypeError(`[real-router] updateRoute: ${t} cannot be an async function`)}}function Be(r){return o=>{const i=function(e){return t=>{const r=e=>e===t||e.startsWith(`${t}.`),n=de(e);xe(n.decoders,r),xe(n.encoders,r),xe(n.defaultParams,r),xe(n.forwardMap,r),xe(n.forwardMap,e=>r(n.forwardMap[e]));const[o,a]=e.getLifecycleFactories();for(const t of Object.keys(a))r(t)&&e.clearCanActivate(t,!0);for(const t of Object.keys(o))r(t)&&e.clearCanDeactivate(t,!0)}}(o),s=(c=de(o).forwardMap,(e,r,n,o)=>{const a=t.getSegmentsByName(o,r);if(!a)throw new Error(`[real-router] updateRoute: forwardTo target "${r}" does not exist`);const i=Se(n),s=[...Se(a)].filter(e=>!i.has(e));if(s.length>0)throw new Error(`[real-router] updateRoute: forwardTo target "${r}" requires params [${s.join(", ")}] that are not available in source route "${e}"`);c[e]=r});var c;o.forward=(e,r)=>{console.warn("[router.forward] Method is deprecated. Use `forwardTo` property in route configuration instead.");const n=ie(o),a=t.getSegmentsByName(n,e);if(!a)throw new Error(`[real-router] forward: source route "${e}" does not exist`);const i=t.getSegmentsByName(n,r);if(!i)throw new Error(`[real-router] forward: target route "${r}" does not exist`);const s=Se(a),c=Se(i),u=[];for(const e of c)s.has(e)||u.push(e);if(u.length>0)throw new Error(`[real-router] forward: target route "${r}" requires params [${u.join(", ")}] that are not available in source route "${e}"`);return de(o).forwardMap[e]=r,_e(o),o};const u=o,d=r.map(e=>Le(e));function f(e,r=!1){se(o,t.createRouteTree("",u[a],e,{skipValidation:r}))}function l(){return ie(o)}return u[a]="",se(o,t.createRouteTree("",u[a],d)),ue(o,{}),u[n]=d,Ce(r,o),_e(o),o.addRoute=e=>{const r=Array.isArray(e)?[...e]:[e];!function(e){const r=new Set,n=new Map;for(const o of e)t.validateRoute(o,"addRoute",l(),"",r,n),Te(o,o.name);$e(e,de(o).forwardMap,l())}(r);for(const e of r)d.push(Le(e));return Ce(r,o),f(d,!0),_e(o),o},o.removeRoute=t=>{e.validateRouteName(t,"removeRoute");const r=o.getState();if(r){const e=r.name,n=e===t,a=e.startsWith(`${t}.`);if(n||a)return console.warn(`[router.removeRoute] Cannot remove route "${t}" — it is currently active${n?"":` (current: "${e}")`}. Navigate away first.`),o}return o.isNavigating()&&console.warn(`[router.removeRoute] Route "${t}" removed while navigation is in progress. This may cause unexpected behavior.`),Me(d,t)?(i(t),f(d,!0),_e(o),o):(console.warn(`[router.removeRoute] Route "${t}" not found. No changes made.`),o)},o.clearRoutes=()=>{if(o.isNavigating())return console.error("[router.clearRoutes] Cannot clear routes while navigation is in progress. Wait for navigation to complete."),o;d.length=0;const e=de(o);for(const t in e.decoders)delete e.decoders[t];for(const t in e.encoders)delete e.encoders[t];for(const t in e.defaultParams)delete e.defaultParams[t];for(const t in e.forwardMap)delete e.forwardMap[t];const[t,r]=o.getLifecycleFactories();for(const e in r)o.clearCanActivate(e,!0);for(const e in t)o.clearCanDeactivate(e,!0);return o.setState(void 0),f(d,!0),_e(o),o},o.getRoute=r=>{e.validateRouteName(r,"getRoute");const n=l(),a=t.getSegmentsByName(n,r);if(!a)return;const i=a.at(-1),s=t.nodeToDefinition(i),[,c]=o.getLifecycleFactories(),u=function(e,t){const r=(n,o)=>{const a={name:n.name,path:n.path},i=e.forwardMap[o];return i&&(a.forwardTo=i),o in e.defaultParams&&(a.defaultParams=e.defaultParams[o]),o in e.decoders&&(a.decodeParams=e.decoders[o]),o in e.encoders&&(a.encodeParams=e.encoders[o]),o in t&&(a.canActivate=t[o]),n.children&&(a.children=n.children.map(e=>r(e,`${o}.${e.name}`))),a};return r}(de(o),c);return u(s,r)},o.hasRoute=r=>{e.validateRouteName(r,"hasRoute");const n=l();return t.hasSegmentsByName(n,r)},o.updateRoute=(r,n)=>{e.validateRouteName(r,"updateRoute"),function(e){if(null===e||"object"!=typeof e||Array.isArray(e))throw new TypeError(`[real-router] updateRoute: updates must be an object, got ${qe(e)}`)}(n);const a=l(),i=t.getSegmentsByName(a,r);if(!i)throw new ReferenceError(`[real-router] updateRoute: route "${r}" does not exist`);o.isNavigating()&&console.error(`[router.updateRoute] Route "${r}" config modified while navigation is in progress. Changes will apply immediately and may affect the current transition.`);const c=de(o),{forwardTo:u,defaultParams:d,decodeParams:f,encodeParams:p,canActivate:m}=n;return null!=u&&Pe(r,{...c.forwardMap,[r]:u}),function(e){if(null!=e&&("object"!=typeof e||Array.isArray(e)))throw new TypeError(`[real-router] updateRoute: defaultParams must be an object or null, got ${qe(e)}`)}(d),ze(f,"decodeParams"),ze(p,"encodeParams"),void 0!==u&&(null===u?delete c.forwardMap[r]:s(r,u,i,a),_e(o)),Ue(c.defaultParams,r,d),Ue(c.decoders,r,f),Ue(c.encoders,r,p),void 0!==m&&(null===m?o.clearCanActivate(r,!0):o.canActivate(r,m)),o},o}}function Ke(e,t){return e===t||!(!Array.isArray(e)||!Array.isArray(t))&&e.length===t.length&&e.every((e,r)=>Ke(e,t[r]))}function Ve(r){let n,o,a=0;const i=()=>ie(r),s=new Map;return r.getState=()=>n,r.setState=t=>{void 0!==t&&e.validateState(t,"router.setState"),o=n,n=t?Object.isFrozen(t)?t:y(t):void 0},r.getPreviousState=()=>o,r.makeState=(t,n,o,i,s)=>{if(!e.isString(t))throw new TypeError(`[router.makeState] Invalid name: ${e.getTypeDescription(t)}. Expected string.`);if(void 0!==n&&!e.isParams(n))throw new TypeError(`[router.makeState] Invalid params: ${e.getTypeDescription(n)}. Expected plain object.`);if(void 0!==o&&!e.isString(o))throw new TypeError(`[router.makeState] Invalid path: ${e.getTypeDescription(o)}. Expected string.`);if(void 0!==s&&"number"!=typeof s)throw new TypeError(`[router.makeState] Invalid forceId: ${e.getTypeDescription(s)}. Expected number.`);const c=i?{...i,id:s??++a,params:i.params,options:i.options,redirected:i.redirected}:void 0,u=de(r).defaultParams;let d;return d=Object.hasOwn(u,t)?{...u[t],...n}:n?{...n}:{},y({name:t,params:d,path:o??r.buildPath(t,n),meta:c})},r.makeNotFoundState=(t,n)=>{if(!e.isString(t))throw new TypeError(`[router.makeNotFoundState] Invalid path: ${e.getTypeDescription(t)}. Expected string.`);if(void 0!==n&&!e.isNavigationOptions(n))throw new TypeError(`[router.makeNotFoundState] Invalid options: ${e.getTypeDescription(n)}. Expected NavigationOptions object.`);return r.makeState(c.UNKNOWN_ROUTE,{path:t},t,n?{options:n,params:{},redirected:!1}:void 0)},r.areStatesEqual=(e,r,n=!0)=>{if(!e||!r)return!!e==!!r;if(e.name!==r.name)return!1;if(n){const n=e.meta?.params??r.meta?.params;return(n?function(e){const t=[];for(const r in e){const n=e[r];for(const e in n)"url"===n[e]&&t.push(e)}return t}(n):(e=>{const r=s.get(e);if(void 0!==r)return r;const n=t.getSegmentsByName(i(),e);if(!n)return s.set(e,[]),[];const o=n.flatMap(e=>e.parser?e.parser.urlParams:[]);return s.set(e,o),o})(e.name)).every(t=>Ke(e.params[t],r.params[t]))}const o=Object.keys(e.params),a=Object.keys(r.params);return o.length===a.length&&o.every(t=>t in r.params&&Ke(e.params[t],r.params[t]))},r.areStatesDescendants=(t,r)=>(e.validateState(t,"areStatesDescendants"),e.validateState(r,"areStatesDescendants"),console.warn("[real-router] areStatesDescendants is deprecated and will be removed in the next major version. Use router.isActiveRoute() instead."),!!r.name.startsWith(`${t.name}.`)&&Object.keys(t.params).every(e=>Ke(t.params[e],r.params[e]))),r.forwardState=(t,n)=>{if(!e.isString(t))throw new TypeError(`[router.forwardState] Invalid routeName: ${e.getTypeDescription(t)}. Expected string.`);if(!e.isParams(n))throw new TypeError(`[router.forwardState] Invalid routeParams: ${e.getTypeDescription(n)}. Expected plain object.`);const o=ce(r)[t]??t,{defaultParams:a}=de(r),i=Object.hasOwn(a,t),s=Object.hasOwn(a,o);let c;return c=i&&s?{...a[t],...a[o],...n}:i?{...a[t],...n}:s?{...a[o],...n}:n,{name:o,params:c}},r.buildState=(n,o)=>{if(!e.isString(n))throw new TypeError(`[router.buildState] Invalid routeName: ${e.getTypeDescription(n)}. Expected string.`);if(!e.isParams(o))throw new TypeError(`[router.buildState] Invalid routeParams: ${e.getTypeDescription(o)}. Expected plain object.`);const{name:a,params:s}=r.forwardState(n,o),c=t.getSegmentsByName(i(),a);if(c)return fe({segments:c,params:s},a)},r.buildStateWithSegments=(n,o)=>{if(!e.isString(n))throw new TypeError(`[router.buildStateWithSegments] Invalid routeName: ${e.getTypeDescription(n)}. Expected string.`);if(!e.isParams(o))throw new TypeError(`[router.buildStateWithSegments] Invalid routeParams: ${e.getTypeDescription(o)}. Expected plain object.`);const{name:a,params:s}=r.forwardState(n,o),c=t.getSegmentsByName(i(),a);if(c)return{state:fe({segments:c,params:s},a),segments:c}},r}var He=(t=[],r={},n={})=>{const o={[i]:{decoders:{},encoders:{},defaultParams:{},forwardMap:{}}};return((...e)=>t=>e.reduce((e,t)=>t(e),t))(function(t){return r=>{for(const[r,n]of Object.entries(t)){if(!e.isObjKey(r,Y))throw new TypeError(`[router.options] Unknown option: "${r}"`);void 0!==n&&Z(r,n,Y[r],"withOptions")}let n=X({...Y,...t});return r.getOptions=()=>n,r.setOption=(t,o)=>{if(!e.isString(t))throw new TypeError("[router.setOption]: option name must be a string, got "+typeof t);if(r.isStarted()&&"defaultRoute"!==t&&"defaultParams"!==t)throw new Error("[router.setOption] Options cannot be changed after router.start(). Only defaultRoute/defaultParams can be changed after start.");if(!Object.hasOwn(n,t))throw new ReferenceError(`[router.setOption]: option "${t}" not found`);Z(t,o,Y[t],"setOption");const a=o&&"object"==typeof o&&o.constructor===Object?{...o}:o;return n=X({...n,[t]:a}),r},r}}(r),function(t){const r=t=>{if(!t||"object"!=typeof t||t.constructor!==Object)throw new TypeError(`[router.setDependencies] Invalid argument: expected plain object, received ${e.getTypeDescription(t)}`);for(const e in t)if(Object.getOwnPropertyDescriptor(t,e)?.get)throw new TypeError(`[router.setDependencies] Getters not allowed: "${e}"`);N({...n,...t},"setDependencies");const r=[];for(const e in t)void 0!==t[e]&&(Object.hasOwn(n,e)&&r.push(e),n[e]=t[e]);r.length>0&&console.warn("[router.setDependencies] Overwritten:",r.join(", "))},n=Object.create(null);return r(t),t=>(t.setDependency=(e,r)=>{if(void 0===r)return t;if(O("setDependency",e),Object.hasOwn(n,e)){const t=n[e],o=t!==r,a=Number.isNaN(t)&&Number.isNaN(r);o&&!a&&console.warn("[router.setDependency] Router dependency already exists and is being overwritten:",e)}else N(n,"setDependency");return n[e]=r,t},t.setDependencies=e=>(r(e),t),t.getDependency=e=>{O("getDependency",e);const t=n[e];if(void 0===t)throw new ReferenceError(`[router.getDependency]: dependency "${String(e)}" not found`);return t},t.getDependencies=()=>({...n}),t.removeDependency=r=>(Object.hasOwn(n,r)||console.warn(`[router.removeDependency] Attempted to remove non-existent dependency: "${e.getTypeDescription(r)}"`),delete n[r],t),t.hasDependency=e=>Object.hasOwn(n,e),t.resetDependencies=()=>{for(const e in n)delete n[e];return t},t)}(n),G,Ve,ge,ae,V,ne,I,function(e){return t=>[Be(e),pe,We].reduce((e,t)=>t(e),t)}(t))(o)};exports.RouterError=b,exports.constants=c,exports.createRouter=He,exports.errorCodes=s,exports.events=h;//# sourceMappingURL=index.js.map