@real-router/browser-plugin 0.11.0 → 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,60 +1,74 @@
1
- import { State as State$1, PluginFactory, Params as Params$1 } from '@real-router/core';
2
-
1
+ import { Params, PluginFactory, State } from "@real-router/core";
2
+ //#region src/types.d.ts
3
3
  /**
4
4
  * Browser plugin configuration.
5
5
  */
6
6
  interface BrowserPluginOptions {
7
- /**
8
- * Force deactivation of current route even if canDeactivate returns false.
9
- *
10
- * @default true
11
- */
12
- forceDeactivate?: boolean;
13
- /**
14
- * Base path for all routes (e.g., "/app" for hosted at /app/).
15
- *
16
- * @default ""
17
- */
18
- base?: string;
7
+ /**
8
+ * Force deactivation of current route even if canDeactivate returns false.
9
+ *
10
+ * @default true
11
+ */
12
+ forceDeactivate?: boolean;
13
+ /**
14
+ * Base path for all routes (e.g., "/app" for hosted at /app/).
15
+ *
16
+ * @default ""
17
+ */
18
+ base?: string;
19
19
  }
20
-
20
+ //#endregion
21
+ //#region ../browser-env/dist/esm/index.d.mts
22
+ //#region src/types.d.ts
21
23
  interface HistoryBrowser {
22
- pushState: (state: State$1, path: string) => void;
23
- replaceState: (state: State$1, path: string) => void;
24
- addPopstateListener: (fn: (evt: PopStateEvent) => void) => () => void;
25
- getHash: () => string;
24
+ pushState: (state: State, path: string) => void;
25
+ replaceState: (state: State, path: string) => void;
26
+ addPopstateListener: (fn: (evt: PopStateEvent) => void) => () => void;
27
+ getHash: () => string;
26
28
  }
27
29
  interface Browser extends HistoryBrowser {
28
- getLocation: () => string;
30
+ getLocation: () => string;
29
31
  }
30
-
32
+ /**
33
+ * Shared mutable state across plugin instances created by the same factory.
34
+ * Enables cleanup of a previous instance's popstate listener when the factory is reused.
35
+ */
36
+ //#endregion
37
+ //#region src/factory.d.ts
31
38
  declare function browserPluginFactory(opts?: Partial<BrowserPluginOptions>, browser?: Browser): PluginFactory;
32
-
39
+ //#endregion
40
+ //#region ../core-types/dist/esm/index.d.mts
33
41
  type TransitionPhase = "deactivating" | "activating";
34
42
  type TransitionReason = "success" | "blocked" | "cancelled" | "error";
35
43
  interface TransitionMeta {
36
- phase: TransitionPhase;
37
- reason: TransitionReason;
38
- reload?: boolean;
39
- redirected?: boolean;
40
- from?: string;
41
- blocker?: string;
42
- segments: {
43
- deactivated: string[];
44
- activated: string[];
45
- intersection: string;
46
- };
47
- }
48
- interface State<P extends Params = Params> {
49
- name: string;
50
- params: P;
51
- path: string;
52
- transition?: TransitionMeta | undefined;
44
+ phase: TransitionPhase;
45
+ reason: TransitionReason;
46
+ reload?: boolean;
47
+ redirected?: boolean;
48
+ from?: string;
49
+ blocker?: string;
50
+ segments: {
51
+ deactivated: string[];
52
+ activated: string[];
53
+ intersection: string;
54
+ };
53
55
  }
54
- interface Params {
55
- [key: string]: string | string[] | number | number[] | boolean | boolean[] | Params | Params[] | Record<string, string | number | boolean> | null | undefined;
56
+ interface State$1<P extends Params$1 = Params$1> {
57
+ name: string;
58
+ params: P;
59
+ path: string;
60
+ transition?: TransitionMeta | undefined;
56
61
  }
57
-
62
+ interface Params$1 {
63
+ [key: string]: string | string[] | number | number[] | boolean | boolean[] | Params$1 | Params$1[] | Record<string, string | number | boolean> | null | undefined;
64
+ } //#endregion
65
+ //#region src/limits.d.ts
66
+ /**
67
+ * Configuration for router resource limits.
68
+ * Controls maximum allowed values for various router operations to prevent resource exhaustion.
69
+ */
70
+ //#endregion
71
+ //#region ../type-guards/dist/esm/index.d.mts
58
72
  /**
59
73
  * Enhanced type guard for State with deep validation.
60
74
  * Checks not only presence but also types of all required fields.
@@ -67,31 +81,40 @@ interface Params {
67
81
  * isStateStrict({ name: 'home', params: {}, path: '/', meta: { id: 1 } }); // true
68
82
  * isStateStrict({ name: 'home', params: 'invalid', path: '/' }); // false
69
83
  */
70
- declare function isStateStrict<P extends Params = Params>(value: unknown): value is State<P>;
71
-
84
+ declare function isStateStrict<P extends Params$1 = Params$1>(value: unknown): value is State$1<P>; //#endregion
85
+ //#region src/guards/primitives.d.ts
86
+ /**
87
+ * Type guard for string type.
88
+ *
89
+ * @param value - Value to check
90
+ * @returns true if value is a string
91
+ */
92
+ //#endregion
93
+ //#region src/index.d.ts
72
94
  /**
73
95
  * Module augmentation for real-router.
74
96
  * Extends Router interface with browser plugin methods.
75
97
  */
76
98
  declare module "@real-router/core" {
77
- interface Router {
78
- /**
79
- * Builds full URL for a route with base path and hash prefix.
80
- * Added by browser plugin.
81
- */
82
- buildUrl: (name: string, params?: Params$1) => string;
83
- /**
84
- * Matches URL and returns corresponding state.
85
- * Added by browser plugin.
86
- */
87
- matchUrl: (url: string) => State$1 | undefined;
88
- /**
89
- * Replaces current history state without triggering navigation.
90
- * Added by browser plugin.
91
- */
92
- replaceHistoryState: (name: string, params?: Params$1, title?: string) => void;
93
- start(path?: string): Promise<State$1>;
94
- }
99
+ interface Router {
100
+ /**
101
+ * Builds full URL for a route with base path and hash prefix.
102
+ * Added by browser plugin.
103
+ */
104
+ buildUrl: (name: string, params?: Params) => string;
105
+ /**
106
+ * Matches URL and returns corresponding state.
107
+ * Added by browser plugin.
108
+ */
109
+ matchUrl: (url: string) => State | undefined;
110
+ /**
111
+ * Replaces current history state without triggering navigation.
112
+ * Added by browser plugin.
113
+ */
114
+ replaceHistoryState: (name: string, params?: Params, title?: string) => void;
115
+ start(path?: string): Promise<State>;
116
+ }
95
117
  }
96
-
118
+ //#endregion
97
119
  export { type Browser, type BrowserPluginOptions, browserPluginFactory, isStateStrict as isState };
120
+ //# sourceMappingURL=index.d.ts.map
package/dist/cjs/index.js CHANGED
@@ -1 +1,2 @@
1
- "use strict";var e=require("@real-router/core/api"),t=require("@real-router/core"),r=/^[A-Z_a-z][\w-]*(?:\.[A-Z_a-z][\w-]*)*$/;function o(e,t=new WeakSet){if(null==e)return!0;const r=typeof e;if("string"===r||"boolean"===r)return!0;if("number"===r)return Number.isFinite(e);if("function"===r||"symbol"===r)return!1;if(Array.isArray(e))return!t.has(e)&&(t.add(e),e.every(e=>o(e,t)));if("object"===r){if(t.has(e))return!1;t.add(e);const r=Object.getPrototypeOf(e);return(null===r||r===Object.prototype)&&Object.values(e).every(e=>o(e,t))}return!1}function n(e){if(null==e)return!0;const t=typeof e;return"string"===t||"boolean"===t||"number"===t&&Number.isFinite(e)}function a(e){if("object"!=typeof e||null===e||Array.isArray(e))return!1;const t=Object.getPrototypeOf(e);if(null!==t&&t!==Object.prototype)return!1;let r=!1;for(const t in e){if(!Object.hasOwn(e,t))continue;const o=e[t];if(!n(o)){const e=typeof o;if("function"===e||"symbol"===e)return!1;r=!0;break}}return!r||o(e)}function s(e){return"object"==typeof e&&null!==e&&!!function(e){return function(e){return"string"==typeof e&&(""===e||!(e.length>1e4)&&(!!e.startsWith("@@")||r.test(e)))}(e.name)&&"string"==typeof e.path&&a(e.params)}(e)}var i=(e,t)=>{globalThis.history.pushState(e,"",t)},c=(e,t)=>{globalThis.history.replaceState(e,"",t)},l=e=>(globalThis.addEventListener("popstate",e),()=>{globalThis.removeEventListener("popstate",e)}),u=()=>globalThis.location.hash,p=()=>{},h=e=>{let t=!1;return r=>{t||(console.warn(`[browser-env] Browser API is running in a non-browser environment (context: "${e}"). Method "${r}" is a no-op. This is expected for SSR, but may indicate misconfiguration if you expected browser behavior.`),t=!0)}},f=e=>{const t=h(e);return{pushState:()=>{t("pushState")},replaceState:()=>{t("replaceState")},addPopstateListener:()=>(t("addPopstateListener"),p),getHash:()=>(t("getHash"),"")}};function d(e,t,r,o){const n={name:e.name,params:e.params,path:e.path};r?o.replaceState(n,t):o.pushState(n,t)}function b(e){let r=!1,o=null;async function n(a){if(r)return console.warn(`[${e.loggerContext}] Transition in progress, deferring popstate event`),void(o=a);r=!0;try{const t=function(e,t,r){if(s(e.state))return{name:e.state.name,params:e.state.params};const o=t.matchPath(r.getLocation());return o?{name:o.name,params:o.params}:void 0}(a,e.api,e.browser);t?await e.router.navigate(t.name,t.params,e.transitionOptions):e.allowNotFound?e.router.navigateToNotFound(e.browser.getLocation()):await e.router.navigateToDefault({...e.transitionOptions,reload:!0,replace:!0})}catch(r){r instanceof t.RouterError||function(t){console.error(`[${e.loggerContext}] Critical error in onPopState`,t);try{const t=e.router.getState();if(t){const r=e.buildUrl(t.name,t.params);e.browser.replaceState(t,r)}}catch(t){console.error(`[${e.loggerContext}] Failed to recover from critical error`,t)}}(r)}finally{r=!1,function(){if(o){const t=o;o=null,console.warn(`[${e.loggerContext}] Processing deferred popstate event`),n(t)}}()}}return e=>{n(e)}}function g(e,t,r,o){return(n,a={})=>{const s=e.buildState(n,a);if(!s)throw new Error(`[real-router] Cannot replace state: route "${n}" is not found`);d(e.makeState(s.name,s.params,t.buildPath(s.name,s.params),{params:s.meta}),o(n,a),!0,r)}}var m={forceDeactivate:!0,base:""},v="browser-plugin";function w(e,t){if(t&&e.startsWith(t)){const r=e.slice(t.length);return r.startsWith("/")?r:`/${r}`}return e}var y,S,P=class{#e;#t;#r;#o;#n;constructor(e,t,r,o,n,a){var s;this.#e=e,this.#t=o,this.#r=(s=o,t.addInterceptor("start",(e,t)=>e(t??s.getLocation())));const i=(t,o)=>{return n=e.buildPath(t,o),r.base+n;var n};this.#o=t.extendRouter({buildUrl:i,matchUrl:e=>{const o=function(e,t){const r=function(e,t){try{const r=new URL(e,globalThis.location.origin);return["http:","https:"].includes(r.protocol)?r:(console.warn(`[${t}] Invalid URL protocol in ${e}`),null)}catch(r){return console.warn(`[${t}] Could not parse url ${e}`,r),null}}(e,v);return r?w(r.pathname,t)+r.search:null}(e,r.base);return o?t.matchPath(o):void 0},replaceHistoryState:g(t,e,o,i)});const c=b({router:e,api:t,browser:o,allowNotFound:t.getOptions().allowNotFound,transitionOptions:n,loggerContext:"browser-plugin",buildUrl:(t,r)=>e.buildUrl(t,r)});this.#n=function(e){return{onStart:()=>{e.shared.removePopStateListener&&e.shared.removePopStateListener(),e.shared.removePopStateListener=e.browser.addPopstateListener(e.handler)},onStop:()=>{e.shared.removePopStateListener&&(e.shared.removePopStateListener(),e.shared.removePopStateListener=void 0)},teardown:()=>{e.shared.removePopStateListener&&(e.shared.removePopStateListener(),e.shared.removePopStateListener=void 0),e.cleanup()}}}({browser:o,shared:a,handler:c,cleanup:()=>{this.#r(),this.#o()}})}getPlugin(){return{...this.#n,onTransitionSuccess:(e,t,r)=>{const o=(a=t,((n=r).replace??!a)||!!n.reload&&e.path===a.path);var n,a;const s=this.#e.buildUrl(e.name,e.params);d(e,t&&t.path!==e.path?s:s+this.#t.getHash(),o,this.#t)}}}},L=(y=m,S=v,e=>{if(e)for(const t of Object.keys(e))if(t in y){const r=e[t],o=typeof y[t],n=typeof r;if(void 0!==r&&n!==o)throw new Error(`[${S}] Invalid type for '${t}': expected ${o}, got ${n}`)}});exports.browserPluginFactory=function(t,r){L(t);const o={...m,...t};o.base=function(e){if(!e)return e;let t=e;return t.startsWith("/")||(t=`/${t}`),t.endsWith("/")&&(t=t.slice(0,-1)),t}(o.base);const n=r??function(e,t){if(void 0!==globalThis.window&&globalThis.history)return{pushState:i,replaceState:c,addPopstateListener:l,getLocation:e,getHash:u};const r=h(t);return{...f(t),getLocation:()=>(r("getLocation"),"")}}(()=>(e=>{try{return encodeURI(decodeURI(e))}catch(t){return console.warn(`[browser-env] Could not encode path "${e}"`,t),e}})(w(globalThis.location.pathname,o.base))+globalThis.location.search,"browser-plugin"),a={forceDeactivate:o.forceDeactivate,source:"popstate",replace:!0},s={removePopStateListener:void 0};return function(t){return new P(t,e.getPluginApi(t),o,n,a,s).getPlugin()}},exports.isState=s;//# sourceMappingURL=index.js.map
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@real-router/core/api`),t=require(`@real-router/core`);const n=/^[A-Z_a-z][\w-]*(?:\.[A-Z_a-z][\w-]*)*$/;function r(e){return typeof e==`string`?e===``?!0:e.length>1e4?!1:e.startsWith(`@@`)?!0:n.test(e):!1}function i(e,t=new WeakSet){if(e==null)return!0;let n=typeof e;if(n===`string`||n===`boolean`)return!0;if(n===`number`)return Number.isFinite(e);if(n===`function`||n===`symbol`)return!1;if(Array.isArray(e))return t.has(e)?!1:(t.add(e),e.every(e=>i(e,t)));if(n===`object`){if(t.has(e))return!1;t.add(e);let n=Object.getPrototypeOf(e);return n!==null&&n!==Object.prototype?!1:Object.values(e).every(e=>i(e,t))}return!1}function a(e){if(e==null)return!0;let t=typeof e;return t===`string`||t===`boolean`?!0:t===`number`?Number.isFinite(e):!1}function o(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);if(t!==null&&t!==Object.prototype)return!1;let n=!1;for(let t in e){if(!Object.hasOwn(e,t))continue;let r=e[t];if(!a(r)){let e=typeof r;if(e===`function`||e===`symbol`)return!1;n=!0;break}}return n?i(e):!0}function s(e){return r(e.name)&&typeof e.path==`string`&&o(e.params)}function c(e){return!(typeof e!=`object`||!e||!s(e))}const l=()=>globalThis.window!==void 0&&!!globalThis.history,u=(e,t)=>{globalThis.history.pushState(e,``,t)},d=(e,t)=>{globalThis.history.replaceState(e,``,t)},f=e=>(globalThis.addEventListener(`popstate`,e),()=>{globalThis.removeEventListener(`popstate`,e)}),p=()=>globalThis.location.hash;function m(e){if(!e)return e;let t=e;return t.startsWith(`/`)||(t=`/${t}`),t.endsWith(`/`)&&(t=t.slice(0,-1)),t}const h=e=>{try{return encodeURI(decodeURI(e))}catch(t){return console.warn(`[browser-env] Could not encode path "${e}"`,t),e}},g=()=>{},_=e=>{let t=!1;return n=>{t||=(console.warn(`[browser-env] Browser API is running in a non-browser environment (context: "${e}"). Method "${n}" is a no-op. This is expected for SSR, but may indicate misconfiguration if you expected browser behavior.`),!0)}},v=e=>{let t=_(e);return{pushState:()=>{t(`pushState`)},replaceState:()=>{t(`replaceState`)},addPopstateListener:()=>(t(`addPopstateListener`),g),getHash:()=>(t(`getHash`),``)}};function y(e,t,n){if(c(e.state))return{name:e.state.name,params:e.state.params};let r=t.matchPath(n.getLocation());return r?{name:r.name,params:r.params}:void 0}function b(e,t,n,r){let i={name:e.name,params:e.params,path:e.path};n?r.replaceState(i,t):r.pushState(i,t)}function x(e,t){return n=>{if(n){for(let r of Object.keys(n))if(r in e){let i=n[r],a=typeof e[r],o=typeof i;if(i!==void 0&&o!==a)throw Error(`[${t}] Invalid type for '${r}': expected ${a}, got ${o}`)}}}}function S(e,t){if(l())return{pushState:u,replaceState:d,addPopstateListener:f,getLocation:e,getHash:p};let n=_(t);return{...v(t),getLocation:()=>(n(`getLocation`),``)}}function C(e){let n=!1,r=null;function i(){if(r){let t=r;r=null,console.warn(`[${e.loggerContext}] Processing deferred popstate event`),o(t)}}function a(t){console.error(`[${e.loggerContext}] Critical error in onPopState`,t);try{let t=e.router.getState();if(t){let n=e.buildUrl(t.name,t.params);e.browser.replaceState(t,n)}}catch(t){console.error(`[${e.loggerContext}] Failed to recover from critical error`,t)}}async function o(o){if(n){console.warn(`[${e.loggerContext}] Transition in progress, deferring popstate event`),r=o;return}n=!0;try{let t=y(o,e.api,e.browser);t?await e.router.navigate(t.name,t.params,e.transitionOptions):e.allowNotFound?e.router.navigateToNotFound(e.browser.getLocation()):await e.router.navigateToDefault({...e.transitionOptions,reload:!0,replace:!0})}catch(e){e instanceof t.RouterError||a(e)}finally{n=!1,i()}}return e=>void o(e)}function w(e){return{onStart:()=>{e.shared.removePopStateListener&&e.shared.removePopStateListener(),e.shared.removePopStateListener=e.browser.addPopstateListener(e.handler)},onStop:()=>{e.shared.removePopStateListener&&(e.shared.removePopStateListener(),e.shared.removePopStateListener=void 0)},teardown:()=>{e.shared.removePopStateListener&&(e.shared.removePopStateListener(),e.shared.removePopStateListener=void 0),e.cleanup()}}}function T(e,t){return e.addInterceptor(`start`,(e,n)=>e(n??t.getLocation()))}function E(e,t,n,r){return(i,a={})=>{let o=e.buildState(i,a);if(!o)throw Error(`[real-router] Cannot replace state: route "${i}" is not found`);b(e.makeState(o.name,o.params,t.buildPath(o.name,o.params),{params:o.meta}),r(i,a),!0,n)}}function D(e,t,n){return(e.replace??!n)||!!e.reload&&t.path===n.path}function O(e,t){try{let n=new URL(e,globalThis.location.origin);return[`http:`,`https:`].includes(n.protocol)?n:(console.warn(`[${t}] Invalid URL protocol in ${e}`),null)}catch(n){return console.warn(`[${t}] Could not parse url ${e}`,n),null}}const k={forceDeactivate:!0,base:``},A=`browser-plugin`;function j(e,t){if(t&&e.startsWith(t)){let n=e.slice(t.length);return n.startsWith(`/`)?n:`/${n}`}return e}function M(e,t){return t+e}function N(e,t){let n=O(e,A);return n?j(n.pathname,t)+n.search:null}var P=class{#e;#t;#n;#r;#i;constructor(e,t,n,r,i,a){this.#e=e,this.#t=r,this.#n=T(t,r);let o=(t,r)=>M(e.buildPath(t,r),n.base);this.#r=t.extendRouter({buildUrl:o,matchUrl:e=>{let r=N(e,n.base);return r?t.matchPath(r):void 0},replaceHistoryState:E(t,e,r,o)}),this.#i=w({browser:r,shared:a,handler:C({router:e,api:t,browser:r,allowNotFound:t.getOptions().allowNotFound,transitionOptions:i,loggerContext:`browser-plugin`,buildUrl:(t,n)=>e.buildUrl(t,n)}),cleanup:()=>{this.#n(),this.#r()}})}getPlugin(){return{...this.#i,onTransitionSuccess:(e,t,n)=>{let r=D(n,e,t),i=this.#e.buildUrl(e.name,e.params);b(e,!t||t.path===e.path?i+this.#t.getHash():i,r,this.#t)}}}};const F=x(k,A);function I(t,n){F(t);let r={...k,...t};r.base=m(r.base);let i=n??S(()=>h(j(globalThis.location.pathname,r.base))+globalThis.location.search,`browser-plugin`),a={forceDeactivate:r.forceDeactivate,source:`popstate`,replace:!0},o={removePopStateListener:void 0};return function(t){return new P(t,(0,e.getPluginApi)(t),r,i,a,o).getPlugin()}}exports.browserPluginFactory=I,exports.isState=c;
2
+ //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/constants.ts","../../src/url-utils.ts","../../src/plugin.ts","../../src/validation.ts","../../src/factory.ts"],"names":["i","getPluginApi"],"mappings":"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","file":"index.js","sourcesContent":["// packages/browser-plugin/modules/constants.ts\n\nimport type { BrowserPluginOptions } from \"./types\";\n\nexport const defaultOptions: Required<BrowserPluginOptions> = {\n forceDeactivate: true,\n base: \"\",\n};\n\n/**\n * Source identifier for transitions triggered by browser events.\n * Used to distinguish browser-initiated navigation (back/forward buttons)\n * from programmatic navigation (router.navigate()).\n */\nexport const source = \"popstate\";\n\nexport const LOGGER_CONTEXT = \"browser-plugin\";\n","// packages/browser-plugin/src/url-utils.ts\n\nimport { safeParseUrl } from \"browser-env\";\n\nimport { LOGGER_CONTEXT } from \"./constants\";\n\nexport function extractPath(pathname: string, base: string): string {\n if (base && pathname.startsWith(base)) {\n const stripped = pathname.slice(base.length);\n\n return stripped.startsWith(\"/\") ? stripped : `/${stripped}`;\n }\n\n return pathname;\n}\n\nexport function buildUrl(path: string, base: string): string {\n return base + path;\n}\n\nexport function urlToPath(url: string, base: string): string | null {\n const parsedUrl = safeParseUrl(url, LOGGER_CONTEXT);\n\n return parsedUrl\n ? extractPath(parsedUrl.pathname, base) + parsedUrl.search\n : null;\n}\n","import {\n createPopstateHandler,\n createPopstateLifecycle,\n createStartInterceptor,\n createReplaceHistoryState,\n shouldReplaceHistory,\n updateBrowserState,\n} from \"browser-env\";\n\nimport { buildUrl, urlToPath } from \"./url-utils\";\n\nimport type { BrowserPluginOptions } from \"./types\";\nimport type {\n NavigationOptions,\n Params,\n Router,\n State,\n Plugin,\n} from \"@real-router/core\";\nimport type { PluginApi } from \"@real-router/core/api\";\nimport type { Browser, SharedFactoryState } from \"browser-env\";\n\nexport class BrowserPlugin {\n readonly #router: Router;\n readonly #browser: Browser;\n readonly #removeStartInterceptor: () => void;\n readonly #removeExtensions: () => void;\n readonly #lifecycle: Pick<Plugin, \"onStart\" | \"onStop\" | \"teardown\">;\n\n constructor(\n router: Router,\n api: PluginApi,\n options: Required<BrowserPluginOptions>,\n browser: Browser,\n transitionOptions: {\n source: string;\n replace: true;\n forceDeactivate?: boolean;\n },\n shared: SharedFactoryState,\n ) {\n this.#router = router;\n this.#browser = browser;\n\n this.#removeStartInterceptor = createStartInterceptor(api, browser);\n\n const pluginBuildUrl = (route: string, params?: Params) => {\n const path = router.buildPath(route, params);\n\n return buildUrl(path, options.base);\n };\n\n this.#removeExtensions = api.extendRouter({\n buildUrl: pluginBuildUrl,\n matchUrl: (url: string) => {\n const path = urlToPath(url, options.base);\n\n return path ? api.matchPath(path) : undefined;\n },\n replaceHistoryState: createReplaceHistoryState(\n api,\n router,\n browser,\n pluginBuildUrl,\n ),\n });\n\n const handler = createPopstateHandler({\n router,\n api,\n browser,\n allowNotFound: api.getOptions().allowNotFound,\n transitionOptions,\n loggerContext: \"browser-plugin\",\n buildUrl: (name: string, params?: Params) =>\n router.buildUrl(name, params),\n });\n\n this.#lifecycle = createPopstateLifecycle({\n browser,\n shared,\n handler,\n cleanup: () => {\n this.#removeStartInterceptor();\n this.#removeExtensions();\n },\n });\n }\n\n getPlugin(): Plugin {\n return {\n ...this.#lifecycle,\n\n onTransitionSuccess: (\n toState: State,\n fromState: State | undefined,\n navOptions: NavigationOptions,\n ) => {\n const replaceHistory = shouldReplaceHistory(\n navOptions,\n toState,\n fromState,\n );\n\n const url = this.#router.buildUrl(toState.name, toState.params);\n\n const shouldPreserveHash =\n !fromState || fromState.path === toState.path;\n\n const finalUrl = shouldPreserveHash\n ? url + this.#browser.getHash()\n : url;\n\n updateBrowserState(toState, finalUrl, replaceHistory, this.#browser);\n },\n };\n }\n}\n","import { createOptionsValidator } from \"browser-env\";\n\nimport { LOGGER_CONTEXT, defaultOptions } from \"./constants\";\n\nimport type { BrowserPluginOptions } from \"./types\";\n\nexport const validateOptions = createOptionsValidator<BrowserPluginOptions>(\n defaultOptions,\n LOGGER_CONTEXT,\n);\n","import { getPluginApi } from \"@real-router/core/api\";\nimport {\n createSafeBrowser,\n normalizeBase,\n safelyEncodePath,\n} from \"browser-env\";\n\nimport { defaultOptions, source } from \"./constants\";\nimport { BrowserPlugin } from \"./plugin\";\nimport { extractPath } from \"./url-utils\";\nimport { validateOptions } from \"./validation\";\n\nimport type { BrowserPluginOptions } from \"./types\";\nimport type { PluginFactory, Router } from \"@real-router/core\";\nimport type { Browser, SharedFactoryState } from \"browser-env\";\n\nexport function browserPluginFactory(\n opts?: Partial<BrowserPluginOptions>,\n browser?: Browser,\n): PluginFactory {\n validateOptions(opts);\n\n const options: Required<BrowserPluginOptions> = {\n ...defaultOptions,\n ...opts,\n };\n\n options.base = normalizeBase(options.base);\n\n const resolvedBrowser =\n browser ??\n createSafeBrowser(\n () =>\n safelyEncodePath(\n extractPath(globalThis.location.pathname, options.base),\n ) + globalThis.location.search,\n \"browser-plugin\",\n );\n\n const forceDeactivate = options.forceDeactivate;\n const transitionOptions = { forceDeactivate, source, replace: true as const };\n\n const shared: SharedFactoryState = { removePopStateListener: undefined };\n\n return function browserPlugin(routerBase) {\n const plugin = new BrowserPlugin(\n routerBase as Router,\n getPluginApi(routerBase),\n options,\n resolvedBrowser,\n transitionOptions,\n shared,\n );\n\n return plugin.getPlugin();\n };\n}\n"]}
1
+ {"version":3,"file":"index.js","names":["n","r","a","o","s","c","d","e","p","t","safeParseUrl","#router","#browser","#removeStartInterceptor","#removeExtensions","#lifecycle","createStartInterceptor","createReplaceHistoryState","createPopstateLifecycle","createPopstateHandler","shouldReplaceHistory","createOptionsValidator","normalizeBase","createSafeBrowser","safelyEncodePath"],"sources":["../../../type-guards/dist/esm/index.mjs","../../../browser-env/dist/esm/index.mjs","../../src/constants.ts","../../src/url-utils.ts","../../src/plugin.ts","../../src/validation.ts","../../src/factory.ts"],"sourcesContent":["const e=[`replace`,`reload`,`force`,`forceDeactivate`,`redirected`];function t(t){if(typeof t!=`object`||!t||Array.isArray(t))return!1;let n=t;for(let t of e){let e=n[t];if(e!==void 0&&typeof e!=`boolean`)return!1}let r=n.signal;return!(r!==void 0&&!(r instanceof AbortSignal))}const n=/\\S/,r=/^[A-Z_a-z][\\w-]*(?:\\.[A-Z_a-z][\\w-]*)*$/;function i(e,t){return TypeError(`[router.${e}] ${t}`)}function a(e){return typeof e==`string`?e===``?!0:e.length>1e4?!1:e.startsWith(`@@`)?!0:r.test(e):!1}function o(e,t=new WeakSet){if(e==null)return!0;let n=typeof e;if(n===`string`||n===`boolean`)return!0;if(n===`number`)return Number.isFinite(e);if(n===`function`||n===`symbol`)return!1;if(Array.isArray(e))return t.has(e)?!1:(t.add(e),e.every(e=>o(e,t)));if(n===`object`){if(t.has(e))return!1;t.add(e);let n=Object.getPrototypeOf(e);return n!==null&&n!==Object.prototype?!1:Object.values(e).every(e=>o(e,t))}return!1}function s(e){if(e==null)return!0;let t=typeof e;return t===`string`||t===`boolean`?!0:t===`number`?Number.isFinite(e):!1}function c(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);if(t!==null&&t!==Object.prototype)return!1;let n=!1;for(let t in e){if(!Object.hasOwn(e,t))continue;let r=e[t];if(!s(r)){let e=typeof r;if(e===`function`||e===`symbol`)return!1;n=!0;break}}return n?o(e):!0}function l(e){if(e==null)return!0;let t=typeof e;return t===`string`||t===`boolean`?!0:t===`number`?Number.isFinite(e):Array.isArray(e)?e.every(e=>{let t=typeof e;return t===`string`||t===`boolean`?!0:t===`number`?Number.isFinite(e):!1}):!1}function u(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;for(let t in e){if(!Object.hasOwn(e,t))continue;let n=e[t];if(!l(n))return!1}return!0}function d(e){return a(e.name)&&typeof e.path==`string`&&c(e.params)}function f(e){return typeof e!=`object`||!e?!1:d(e)}function p(e){return!(typeof e!=`object`||!e||!d(e))}function m(e){return typeof e==`string`}function h(e){return typeof e==`boolean`}function g(e,t){return e in t}function _(e){return typeof e==`number`?Number.isFinite(e):typeof e==`string`||typeof e==`boolean`}function v(e,t){if(typeof e!=`string`)throw i(t,`Route name must be a string, got ${typeof e}`);if(e!==``){if(!n.test(e))throw i(t,`Route name cannot contain only whitespace`);if(e.length>1e4)throw i(t,`Route name exceeds maximum length of 10000 characters. This is a technical safety limit.`);if(!e.startsWith(`@@`)&&!r.test(e))throw i(t,`Invalid route name \"${e}\". Each segment must start with a letter or underscore, followed by letters, numbers, underscores, or hyphens. Segments are separated by dots (e.g., \"users.profile\").`)}}function y(e){return e===null?`null`:Array.isArray(e)?`array[${e.length}]`:typeof e==`object`?`constructor`in e&&e.constructor.name!==`Object`?e.constructor.name:`object`:typeof e}function b(e,t){if(!f(e))throw TypeError(`[${t}] Invalid state structure: ${y(e)}. Expected State object with name, params, and path properties.`)}export{y as getTypeDescription,h as isBoolean,t as isNavigationOptions,g as isObjKey,c as isParams,u as isParamsStrict,_ as isPrimitiveValue,a as isRouteName,f as isState,p as isStateStrict,m as isString,v as validateRouteName,b as validateState};\n//# sourceMappingURL=index.mjs.map","import{isStateStrict as e}from\"type-guards\";import{RouterError as t}from\"@real-router/core\";const n=()=>globalThis.window!==void 0&&!!globalThis.history,r=(e,t)=>{globalThis.history.pushState(e,``,t)},i=(e,t)=>{globalThis.history.replaceState(e,``,t)},a=e=>(globalThis.addEventListener(`popstate`,e),()=>{globalThis.removeEventListener(`popstate`,e)}),o=()=>globalThis.location.hash;function s(e){if(!e)return e;let t=e;return t.startsWith(`/`)||(t=`/${t}`),t.endsWith(`/`)&&(t=t.slice(0,-1)),t}const c=e=>{try{return encodeURI(decodeURI(e))}catch(t){return console.warn(`[browser-env] Could not encode path \"${e}\"`,t),e}},l=()=>{},u=e=>{let t=!1;return n=>{t||=(console.warn(`[browser-env] Browser API is running in a non-browser environment (context: \"${e}\"). Method \"${n}\" is a no-op. This is expected for SSR, but may indicate misconfiguration if you expected browser behavior.`),!0)}},d=e=>{let t=u(e);return{pushState:()=>{t(`pushState`)},replaceState:()=>{t(`replaceState`)},addPopstateListener:()=>(t(`addPopstateListener`),l),getHash:()=>(t(`getHash`),``)}};function f(t,n,r){if(e(t.state))return{name:t.state.name,params:t.state.params};let i=n.matchPath(r.getLocation());return i?{name:i.name,params:i.params}:void 0}function p(e,t,n,r){let i={name:e.name,params:e.params,path:e.path};n?r.replaceState(i,t):r.pushState(i,t)}function m(e,t){return n=>{if(n){for(let r of Object.keys(n))if(r in e){let i=n[r],a=typeof e[r],o=typeof i;if(i!==void 0&&o!==a)throw Error(`[${t}] Invalid type for '${r}': expected ${a}, got ${o}`)}}}}function h(e,t){if(n())return{pushState:r,replaceState:i,addPopstateListener:a,getLocation:e,getHash:o};let s=u(t);return{...d(t),getLocation:()=>(s(`getLocation`),``)}}function g(e){let n=!1,r=null;function i(){if(r){let t=r;r=null,console.warn(`[${e.loggerContext}] Processing deferred popstate event`),o(t)}}function a(t){console.error(`[${e.loggerContext}] Critical error in onPopState`,t);try{let t=e.router.getState();if(t){let n=e.buildUrl(t.name,t.params);e.browser.replaceState(t,n)}}catch(t){console.error(`[${e.loggerContext}] Failed to recover from critical error`,t)}}async function o(o){if(n){console.warn(`[${e.loggerContext}] Transition in progress, deferring popstate event`),r=o;return}n=!0;try{let t=f(o,e.api,e.browser);t?await e.router.navigate(t.name,t.params,e.transitionOptions):e.allowNotFound?e.router.navigateToNotFound(e.browser.getLocation()):await e.router.navigateToDefault({...e.transitionOptions,reload:!0,replace:!0})}catch(e){e instanceof t||a(e)}finally{n=!1,i()}}return e=>void o(e)}function _(e){return{onStart:()=>{e.shared.removePopStateListener&&e.shared.removePopStateListener(),e.shared.removePopStateListener=e.browser.addPopstateListener(e.handler)},onStop:()=>{e.shared.removePopStateListener&&(e.shared.removePopStateListener(),e.shared.removePopStateListener=void 0)},teardown:()=>{e.shared.removePopStateListener&&(e.shared.removePopStateListener(),e.shared.removePopStateListener=void 0),e.cleanup()}}}function v(e,t){return e.addInterceptor(`start`,(e,n)=>e(n??t.getLocation()))}function y(e,t,n,r){return(i,a={})=>{let o=e.buildState(i,a);if(!o)throw Error(`[real-router] Cannot replace state: route \"${i}\" is not found`);p(e.makeState(o.name,o.params,t.buildPath(o.name,o.params),{params:o.meta}),r(i,a),!0,n)}}function b(e,t,n){return(e.replace??!n)||!!e.reload&&t.path===n.path}function x(e,t){try{let n=new URL(e,globalThis.location.origin);return[`http:`,`https:`].includes(n.protocol)?n:(console.warn(`[${t}] Invalid URL protocol in ${e}`),null)}catch(n){return console.warn(`[${t}] Could not parse url ${e}`,n),null}}export{a as addPopstateListener,d as createHistoryFallbackBrowser,m as createOptionsValidator,g as createPopstateHandler,_ as createPopstateLifecycle,y as createReplaceHistoryState,h as createSafeBrowser,v as createStartInterceptor,u as createWarnOnce,o as getHash,f as getRouteFromEvent,n as isBrowserEnvironment,s as normalizeBase,r as pushState,i as replaceState,x as safeParseUrl,c as safelyEncodePath,b as shouldReplaceHistory,p as updateBrowserState};\n//# sourceMappingURL=index.mjs.map","// packages/browser-plugin/modules/constants.ts\n\nimport type { BrowserPluginOptions } from \"./types\";\n\nexport const defaultOptions: Required<BrowserPluginOptions> = {\n forceDeactivate: true,\n base: \"\",\n};\n\n/**\n * Source identifier for transitions triggered by browser events.\n * Used to distinguish browser-initiated navigation (back/forward buttons)\n * from programmatic navigation (router.navigate()).\n */\nexport const source = \"popstate\";\n\nexport const LOGGER_CONTEXT = \"browser-plugin\";\n","// packages/browser-plugin/src/url-utils.ts\n\nimport { safeParseUrl } from \"browser-env\";\n\nimport { LOGGER_CONTEXT } from \"./constants\";\n\nexport function extractPath(pathname: string, base: string): string {\n if (base && pathname.startsWith(base)) {\n const stripped = pathname.slice(base.length);\n\n return stripped.startsWith(\"/\") ? stripped : `/${stripped}`;\n }\n\n return pathname;\n}\n\nexport function buildUrl(path: string, base: string): string {\n return base + path;\n}\n\nexport function urlToPath(url: string, base: string): string | null {\n const parsedUrl = safeParseUrl(url, LOGGER_CONTEXT);\n\n return parsedUrl\n ? extractPath(parsedUrl.pathname, base) + parsedUrl.search\n : null;\n}\n","import {\n createPopstateHandler,\n createPopstateLifecycle,\n createStartInterceptor,\n createReplaceHistoryState,\n shouldReplaceHistory,\n updateBrowserState,\n} from \"browser-env\";\n\nimport { buildUrl, urlToPath } from \"./url-utils\";\n\nimport type { BrowserPluginOptions } from \"./types\";\nimport type {\n NavigationOptions,\n Params,\n Router,\n State,\n Plugin,\n} from \"@real-router/core\";\nimport type { PluginApi } from \"@real-router/core/api\";\nimport type { Browser, SharedFactoryState } from \"browser-env\";\n\nexport class BrowserPlugin {\n readonly #router: Router;\n readonly #browser: Browser;\n readonly #removeStartInterceptor: () => void;\n readonly #removeExtensions: () => void;\n readonly #lifecycle: Pick<Plugin, \"onStart\" | \"onStop\" | \"teardown\">;\n\n constructor(\n router: Router,\n api: PluginApi,\n options: Required<BrowserPluginOptions>,\n browser: Browser,\n transitionOptions: {\n source: string;\n replace: true;\n forceDeactivate?: boolean;\n },\n shared: SharedFactoryState,\n ) {\n this.#router = router;\n this.#browser = browser;\n\n this.#removeStartInterceptor = createStartInterceptor(api, browser);\n\n const pluginBuildUrl = (route: string, params?: Params) => {\n const path = router.buildPath(route, params);\n\n return buildUrl(path, options.base);\n };\n\n this.#removeExtensions = api.extendRouter({\n buildUrl: pluginBuildUrl,\n matchUrl: (url: string) => {\n const path = urlToPath(url, options.base);\n\n return path ? api.matchPath(path) : undefined;\n },\n replaceHistoryState: createReplaceHistoryState(\n api,\n router,\n browser,\n pluginBuildUrl,\n ),\n });\n\n const handler = createPopstateHandler({\n router,\n api,\n browser,\n allowNotFound: api.getOptions().allowNotFound,\n transitionOptions,\n loggerContext: \"browser-plugin\",\n buildUrl: (name: string, params?: Params) =>\n router.buildUrl(name, params),\n });\n\n this.#lifecycle = createPopstateLifecycle({\n browser,\n shared,\n handler,\n cleanup: () => {\n this.#removeStartInterceptor();\n this.#removeExtensions();\n },\n });\n }\n\n getPlugin(): Plugin {\n return {\n ...this.#lifecycle,\n\n onTransitionSuccess: (\n toState: State,\n fromState: State | undefined,\n navOptions: NavigationOptions,\n ) => {\n const replaceHistory = shouldReplaceHistory(\n navOptions,\n toState,\n fromState,\n );\n\n const url = this.#router.buildUrl(toState.name, toState.params);\n\n const shouldPreserveHash =\n !fromState || fromState.path === toState.path;\n\n const finalUrl = shouldPreserveHash\n ? url + this.#browser.getHash()\n : url;\n\n updateBrowserState(toState, finalUrl, replaceHistory, this.#browser);\n },\n };\n }\n}\n","import { createOptionsValidator } from \"browser-env\";\n\nimport { LOGGER_CONTEXT, defaultOptions } from \"./constants\";\n\nimport type { BrowserPluginOptions } from \"./types\";\n\nexport const validateOptions = createOptionsValidator<BrowserPluginOptions>(\n defaultOptions,\n LOGGER_CONTEXT,\n);\n","import { getPluginApi } from \"@real-router/core/api\";\nimport {\n createSafeBrowser,\n normalizeBase,\n safelyEncodePath,\n} from \"browser-env\";\n\nimport { defaultOptions, source } from \"./constants\";\nimport { BrowserPlugin } from \"./plugin\";\nimport { extractPath } from \"./url-utils\";\nimport { validateOptions } from \"./validation\";\n\nimport type { BrowserPluginOptions } from \"./types\";\nimport type { PluginFactory, Router } from \"@real-router/core\";\nimport type { Browser, SharedFactoryState } from \"browser-env\";\n\nexport function browserPluginFactory(\n opts?: Partial<BrowserPluginOptions>,\n browser?: Browser,\n): PluginFactory {\n validateOptions(opts);\n\n const options: Required<BrowserPluginOptions> = {\n ...defaultOptions,\n ...opts,\n };\n\n options.base = normalizeBase(options.base);\n\n const resolvedBrowser =\n browser ??\n createSafeBrowser(\n () =>\n safelyEncodePath(\n extractPath(globalThis.location.pathname, options.base),\n ) + globalThis.location.search,\n \"browser-plugin\",\n );\n\n const forceDeactivate = options.forceDeactivate;\n const transitionOptions = { forceDeactivate, source, replace: true as const };\n\n const shared: SharedFactoryState = { removePopStateListener: undefined };\n\n return function browserPlugin(routerBase) {\n const plugin = new BrowserPlugin(\n routerBase as Router,\n getPluginApi(routerBase),\n options,\n resolvedBrowser,\n transitionOptions,\n shared,\n );\n\n return plugin.getPlugin();\n };\n}\n"],"mappings":"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"}
@@ -1,60 +1,75 @@
1
- import { State as State$1, PluginFactory, Params as Params$1 } from '@real-router/core';
1
+ import { Params, PluginFactory, State } from "@real-router/core";
2
2
 
3
+ //#region src/types.d.ts
3
4
  /**
4
5
  * Browser plugin configuration.
5
6
  */
6
7
  interface BrowserPluginOptions {
7
- /**
8
- * Force deactivation of current route even if canDeactivate returns false.
9
- *
10
- * @default true
11
- */
12
- forceDeactivate?: boolean;
13
- /**
14
- * Base path for all routes (e.g., "/app" for hosted at /app/).
15
- *
16
- * @default ""
17
- */
18
- base?: string;
8
+ /**
9
+ * Force deactivation of current route even if canDeactivate returns false.
10
+ *
11
+ * @default true
12
+ */
13
+ forceDeactivate?: boolean;
14
+ /**
15
+ * Base path for all routes (e.g., "/app" for hosted at /app/).
16
+ *
17
+ * @default ""
18
+ */
19
+ base?: string;
19
20
  }
20
-
21
+ //#endregion
22
+ //#region ../browser-env/dist/esm/index.d.mts
23
+ //#region src/types.d.ts
21
24
  interface HistoryBrowser {
22
- pushState: (state: State$1, path: string) => void;
23
- replaceState: (state: State$1, path: string) => void;
24
- addPopstateListener: (fn: (evt: PopStateEvent) => void) => () => void;
25
- getHash: () => string;
25
+ pushState: (state: State, path: string) => void;
26
+ replaceState: (state: State, path: string) => void;
27
+ addPopstateListener: (fn: (evt: PopStateEvent) => void) => () => void;
28
+ getHash: () => string;
26
29
  }
27
30
  interface Browser extends HistoryBrowser {
28
- getLocation: () => string;
31
+ getLocation: () => string;
29
32
  }
30
-
33
+ /**
34
+ * Shared mutable state across plugin instances created by the same factory.
35
+ * Enables cleanup of a previous instance's popstate listener when the factory is reused.
36
+ */
37
+ //#endregion
38
+ //#region src/factory.d.ts
31
39
  declare function browserPluginFactory(opts?: Partial<BrowserPluginOptions>, browser?: Browser): PluginFactory;
32
-
40
+ //#endregion
41
+ //#region ../core-types/dist/esm/index.d.mts
33
42
  type TransitionPhase = "deactivating" | "activating";
34
43
  type TransitionReason = "success" | "blocked" | "cancelled" | "error";
35
44
  interface TransitionMeta {
36
- phase: TransitionPhase;
37
- reason: TransitionReason;
38
- reload?: boolean;
39
- redirected?: boolean;
40
- from?: string;
41
- blocker?: string;
42
- segments: {
43
- deactivated: string[];
44
- activated: string[];
45
- intersection: string;
46
- };
47
- }
48
- interface State<P extends Params = Params> {
49
- name: string;
50
- params: P;
51
- path: string;
52
- transition?: TransitionMeta | undefined;
45
+ phase: TransitionPhase;
46
+ reason: TransitionReason;
47
+ reload?: boolean;
48
+ redirected?: boolean;
49
+ from?: string;
50
+ blocker?: string;
51
+ segments: {
52
+ deactivated: string[];
53
+ activated: string[];
54
+ intersection: string;
55
+ };
53
56
  }
54
- interface Params {
55
- [key: string]: string | string[] | number | number[] | boolean | boolean[] | Params | Params[] | Record<string, string | number | boolean> | null | undefined;
57
+ interface State$1<P extends Params$1 = Params$1> {
58
+ name: string;
59
+ params: P;
60
+ path: string;
61
+ transition?: TransitionMeta | undefined;
56
62
  }
57
-
63
+ interface Params$1 {
64
+ [key: string]: string | string[] | number | number[] | boolean | boolean[] | Params$1 | Params$1[] | Record<string, string | number | boolean> | null | undefined;
65
+ } //#endregion
66
+ //#region src/limits.d.ts
67
+ /**
68
+ * Configuration for router resource limits.
69
+ * Controls maximum allowed values for various router operations to prevent resource exhaustion.
70
+ */
71
+ //#endregion
72
+ //#region ../type-guards/dist/esm/index.d.mts
58
73
  /**
59
74
  * Enhanced type guard for State with deep validation.
60
75
  * Checks not only presence but also types of all required fields.
@@ -67,31 +82,40 @@ interface Params {
67
82
  * isStateStrict({ name: 'home', params: {}, path: '/', meta: { id: 1 } }); // true
68
83
  * isStateStrict({ name: 'home', params: 'invalid', path: '/' }); // false
69
84
  */
70
- declare function isStateStrict<P extends Params = Params>(value: unknown): value is State<P>;
71
-
85
+ declare function isStateStrict<P extends Params$1 = Params$1>(value: unknown): value is State$1<P>; //#endregion
86
+ //#region src/guards/primitives.d.ts
87
+ /**
88
+ * Type guard for string type.
89
+ *
90
+ * @param value - Value to check
91
+ * @returns true if value is a string
92
+ */
93
+ //#endregion
94
+ //#region src/index.d.ts
72
95
  /**
73
96
  * Module augmentation for real-router.
74
97
  * Extends Router interface with browser plugin methods.
75
98
  */
76
99
  declare module "@real-router/core" {
77
- interface Router {
78
- /**
79
- * Builds full URL for a route with base path and hash prefix.
80
- * Added by browser plugin.
81
- */
82
- buildUrl: (name: string, params?: Params$1) => string;
83
- /**
84
- * Matches URL and returns corresponding state.
85
- * Added by browser plugin.
86
- */
87
- matchUrl: (url: string) => State$1 | undefined;
88
- /**
89
- * Replaces current history state without triggering navigation.
90
- * Added by browser plugin.
91
- */
92
- replaceHistoryState: (name: string, params?: Params$1, title?: string) => void;
93
- start(path?: string): Promise<State$1>;
94
- }
100
+ interface Router {
101
+ /**
102
+ * Builds full URL for a route with base path and hash prefix.
103
+ * Added by browser plugin.
104
+ */
105
+ buildUrl: (name: string, params?: Params) => string;
106
+ /**
107
+ * Matches URL and returns corresponding state.
108
+ * Added by browser plugin.
109
+ */
110
+ matchUrl: (url: string) => State | undefined;
111
+ /**
112
+ * Replaces current history state without triggering navigation.
113
+ * Added by browser plugin.
114
+ */
115
+ replaceHistoryState: (name: string, params?: Params, title?: string) => void;
116
+ start(path?: string): Promise<State>;
117
+ }
95
118
  }
96
-
119
+ //#endregion
97
120
  export { type Browser, type BrowserPluginOptions, browserPluginFactory, isStateStrict as isState };
121
+ //# sourceMappingURL=index.d.mts.map
@@ -1 +1,2 @@
1
- import{getPluginApi as t}from"@real-router/core/api";import{RouterError as e}from"@real-router/core";var r=/^[A-Z_a-z][\w-]*(?:\.[A-Z_a-z][\w-]*)*$/;function o(t,e=new WeakSet){if(null==t)return!0;const r=typeof t;if("string"===r||"boolean"===r)return!0;if("number"===r)return Number.isFinite(t);if("function"===r||"symbol"===r)return!1;if(Array.isArray(t))return!e.has(t)&&(e.add(t),t.every(t=>o(t,e)));if("object"===r){if(e.has(t))return!1;e.add(t);const r=Object.getPrototypeOf(t);return(null===r||r===Object.prototype)&&Object.values(t).every(t=>o(t,e))}return!1}function n(t){if(null==t)return!0;const e=typeof t;return"string"===e||"boolean"===e||"number"===e&&Number.isFinite(t)}function a(t){if("object"!=typeof t||null===t||Array.isArray(t))return!1;const e=Object.getPrototypeOf(t);if(null!==e&&e!==Object.prototype)return!1;let r=!1;for(const e in t){if(!Object.hasOwn(t,e))continue;const o=t[e];if(!n(o)){const t=typeof o;if("function"===t||"symbol"===t)return!1;r=!0;break}}return!r||o(t)}function s(t){return"object"==typeof t&&null!==t&&!!function(t){return function(t){return"string"==typeof t&&(""===t||!(t.length>1e4)&&(!!t.startsWith("@@")||r.test(t)))}(t.name)&&"string"==typeof t.path&&a(t.params)}(t)}var i=(t,e)=>{globalThis.history.pushState(t,"",e)},c=(t,e)=>{globalThis.history.replaceState(t,"",e)},l=t=>(globalThis.addEventListener("popstate",t),()=>{globalThis.removeEventListener("popstate",t)}),u=()=>globalThis.location.hash,p=()=>{},h=t=>{let e=!1;return r=>{e||(console.warn(`[browser-env] Browser API is running in a non-browser environment (context: "${t}"). Method "${r}" is a no-op. This is expected for SSR, but may indicate misconfiguration if you expected browser behavior.`),e=!0)}},f=t=>{const e=h(t);return{pushState:()=>{e("pushState")},replaceState:()=>{e("replaceState")},addPopstateListener:()=>(e("addPopstateListener"),p),getHash:()=>(e("getHash"),"")}};function d(t,e,r,o){const n={name:t.name,params:t.params,path:t.path};r?o.replaceState(n,e):o.pushState(n,e)}function m(t){let r=!1,o=null;async function n(a){if(r)return console.warn(`[${t.loggerContext}] Transition in progress, deferring popstate event`),void(o=a);r=!0;try{const e=function(t,e,r){if(s(t.state))return{name:t.state.name,params:t.state.params};const o=e.matchPath(r.getLocation());return o?{name:o.name,params:o.params}:void 0}(a,t.api,t.browser);e?await t.router.navigate(e.name,e.params,t.transitionOptions):t.allowNotFound?t.router.navigateToNotFound(t.browser.getLocation()):await t.router.navigateToDefault({...t.transitionOptions,reload:!0,replace:!0})}catch(r){r instanceof e||function(e){console.error(`[${t.loggerContext}] Critical error in onPopState`,e);try{const e=t.router.getState();if(e){const r=t.buildUrl(e.name,e.params);t.browser.replaceState(e,r)}}catch(e){console.error(`[${t.loggerContext}] Failed to recover from critical error`,e)}}(r)}finally{r=!1,function(){if(o){const e=o;o=null,console.warn(`[${t.loggerContext}] Processing deferred popstate event`),n(e)}}()}}return t=>{n(t)}}function b(t,e,r,o){return(n,a={})=>{const s=t.buildState(n,a);if(!s)throw new Error(`[real-router] Cannot replace state: route "${n}" is not found`);d(t.makeState(s.name,s.params,e.buildPath(s.name,s.params),{params:s.meta}),o(n,a),!0,r)}}var g={forceDeactivate:!0,base:""},v="browser-plugin";function w(t,e){if(e&&t.startsWith(e)){const r=t.slice(e.length);return r.startsWith("/")?r:`/${r}`}return t}var y,S,P=class{#t;#e;#r;#o;#n;constructor(t,e,r,o,n,a){var s;this.#t=t,this.#e=o,this.#r=(s=o,e.addInterceptor("start",(t,e)=>t(e??s.getLocation())));const i=(e,o)=>{return n=t.buildPath(e,o),r.base+n;var n};this.#o=e.extendRouter({buildUrl:i,matchUrl:t=>{const o=function(t,e){const r=function(t,e){try{const r=new URL(t,globalThis.location.origin);return["http:","https:"].includes(r.protocol)?r:(console.warn(`[${e}] Invalid URL protocol in ${t}`),null)}catch(r){return console.warn(`[${e}] Could not parse url ${t}`,r),null}}(t,v);return r?w(r.pathname,e)+r.search:null}(t,r.base);return o?e.matchPath(o):void 0},replaceHistoryState:b(e,t,o,i)});const c=m({router:t,api:e,browser:o,allowNotFound:e.getOptions().allowNotFound,transitionOptions:n,loggerContext:"browser-plugin",buildUrl:(e,r)=>t.buildUrl(e,r)});this.#n=function(t){return{onStart:()=>{t.shared.removePopStateListener&&t.shared.removePopStateListener(),t.shared.removePopStateListener=t.browser.addPopstateListener(t.handler)},onStop:()=>{t.shared.removePopStateListener&&(t.shared.removePopStateListener(),t.shared.removePopStateListener=void 0)},teardown:()=>{t.shared.removePopStateListener&&(t.shared.removePopStateListener(),t.shared.removePopStateListener=void 0),t.cleanup()}}}({browser:o,shared:a,handler:c,cleanup:()=>{this.#r(),this.#o()}})}getPlugin(){return{...this.#n,onTransitionSuccess:(t,e,r)=>{const o=(a=e,((n=r).replace??!a)||!!n.reload&&t.path===a.path);var n,a;const s=this.#t.buildUrl(t.name,t.params);d(t,e&&e.path!==t.path?s:s+this.#e.getHash(),o,this.#e)}}}},L=(y=g,S=v,t=>{if(t)for(const e of Object.keys(t))if(e in y){const r=t[e],o=typeof y[e],n=typeof r;if(void 0!==r&&n!==o)throw new Error(`[${S}] Invalid type for '${e}': expected ${o}, got ${n}`)}});function $(e,r){L(e);const o={...g,...e};o.base=function(t){if(!t)return t;let e=t;return e.startsWith("/")||(e=`/${e}`),e.endsWith("/")&&(e=e.slice(0,-1)),e}(o.base);const n=r??function(t,e){if(void 0!==globalThis.window&&globalThis.history)return{pushState:i,replaceState:c,addPopstateListener:l,getLocation:t,getHash:u};const r=h(e);return{...f(e),getLocation:()=>(r("getLocation"),"")}}(()=>(t=>{try{return encodeURI(decodeURI(t))}catch(e){return console.warn(`[browser-env] Could not encode path "${t}"`,e),t}})(w(globalThis.location.pathname,o.base))+globalThis.location.search,"browser-plugin"),a={forceDeactivate:o.forceDeactivate,source:"popstate",replace:!0},s={removePopStateListener:void 0};return function(e){return new P(e,t(e),o,n,a,s).getPlugin()}}export{$ as browserPluginFactory,s as isState};//# sourceMappingURL=index.mjs.map
1
+ import{getPluginApi as e}from"@real-router/core/api";import{RouterError as t}from"@real-router/core";const n=/^[A-Z_a-z][\w-]*(?:\.[A-Z_a-z][\w-]*)*$/;function r(e){return typeof e==`string`?e===``?!0:e.length>1e4?!1:e.startsWith(`@@`)?!0:n.test(e):!1}function i(e,t=new WeakSet){if(e==null)return!0;let n=typeof e;if(n===`string`||n===`boolean`)return!0;if(n===`number`)return Number.isFinite(e);if(n===`function`||n===`symbol`)return!1;if(Array.isArray(e))return t.has(e)?!1:(t.add(e),e.every(e=>i(e,t)));if(n===`object`){if(t.has(e))return!1;t.add(e);let n=Object.getPrototypeOf(e);return n!==null&&n!==Object.prototype?!1:Object.values(e).every(e=>i(e,t))}return!1}function a(e){if(e==null)return!0;let t=typeof e;return t===`string`||t===`boolean`?!0:t===`number`?Number.isFinite(e):!1}function o(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);if(t!==null&&t!==Object.prototype)return!1;let n=!1;for(let t in e){if(!Object.hasOwn(e,t))continue;let r=e[t];if(!a(r)){let e=typeof r;if(e===`function`||e===`symbol`)return!1;n=!0;break}}return n?i(e):!0}function s(e){return r(e.name)&&typeof e.path==`string`&&o(e.params)}function c(e){return!(typeof e!=`object`||!e||!s(e))}const l=()=>globalThis.window!==void 0&&!!globalThis.history,u=(e,t)=>{globalThis.history.pushState(e,``,t)},d=(e,t)=>{globalThis.history.replaceState(e,``,t)},f=e=>(globalThis.addEventListener(`popstate`,e),()=>{globalThis.removeEventListener(`popstate`,e)}),p=()=>globalThis.location.hash;function m(e){if(!e)return e;let t=e;return t.startsWith(`/`)||(t=`/${t}`),t.endsWith(`/`)&&(t=t.slice(0,-1)),t}const h=e=>{try{return encodeURI(decodeURI(e))}catch(t){return console.warn(`[browser-env] Could not encode path "${e}"`,t),e}},g=()=>{},_=e=>{let t=!1;return n=>{t||=(console.warn(`[browser-env] Browser API is running in a non-browser environment (context: "${e}"). Method "${n}" is a no-op. This is expected for SSR, but may indicate misconfiguration if you expected browser behavior.`),!0)}},v=e=>{let t=_(e);return{pushState:()=>{t(`pushState`)},replaceState:()=>{t(`replaceState`)},addPopstateListener:()=>(t(`addPopstateListener`),g),getHash:()=>(t(`getHash`),``)}};function y(e,t,n){if(c(e.state))return{name:e.state.name,params:e.state.params};let r=t.matchPath(n.getLocation());return r?{name:r.name,params:r.params}:void 0}function b(e,t,n,r){let i={name:e.name,params:e.params,path:e.path};n?r.replaceState(i,t):r.pushState(i,t)}function x(e,t){return n=>{if(n){for(let r of Object.keys(n))if(r in e){let i=n[r],a=typeof e[r],o=typeof i;if(i!==void 0&&o!==a)throw Error(`[${t}] Invalid type for '${r}': expected ${a}, got ${o}`)}}}}function S(e,t){if(l())return{pushState:u,replaceState:d,addPopstateListener:f,getLocation:e,getHash:p};let n=_(t);return{...v(t),getLocation:()=>(n(`getLocation`),``)}}function C(e){let n=!1,r=null;function i(){if(r){let t=r;r=null,console.warn(`[${e.loggerContext}] Processing deferred popstate event`),o(t)}}function a(t){console.error(`[${e.loggerContext}] Critical error in onPopState`,t);try{let t=e.router.getState();if(t){let n=e.buildUrl(t.name,t.params);e.browser.replaceState(t,n)}}catch(t){console.error(`[${e.loggerContext}] Failed to recover from critical error`,t)}}async function o(o){if(n){console.warn(`[${e.loggerContext}] Transition in progress, deferring popstate event`),r=o;return}n=!0;try{let t=y(o,e.api,e.browser);t?await e.router.navigate(t.name,t.params,e.transitionOptions):e.allowNotFound?e.router.navigateToNotFound(e.browser.getLocation()):await e.router.navigateToDefault({...e.transitionOptions,reload:!0,replace:!0})}catch(e){e instanceof t||a(e)}finally{n=!1,i()}}return e=>void o(e)}function w(e){return{onStart:()=>{e.shared.removePopStateListener&&e.shared.removePopStateListener(),e.shared.removePopStateListener=e.browser.addPopstateListener(e.handler)},onStop:()=>{e.shared.removePopStateListener&&(e.shared.removePopStateListener(),e.shared.removePopStateListener=void 0)},teardown:()=>{e.shared.removePopStateListener&&(e.shared.removePopStateListener(),e.shared.removePopStateListener=void 0),e.cleanup()}}}function T(e,t){return e.addInterceptor(`start`,(e,n)=>e(n??t.getLocation()))}function E(e,t,n,r){return(i,a={})=>{let o=e.buildState(i,a);if(!o)throw Error(`[real-router] Cannot replace state: route "${i}" is not found`);b(e.makeState(o.name,o.params,t.buildPath(o.name,o.params),{params:o.meta}),r(i,a),!0,n)}}function D(e,t,n){return(e.replace??!n)||!!e.reload&&t.path===n.path}function O(e,t){try{let n=new URL(e,globalThis.location.origin);return[`http:`,`https:`].includes(n.protocol)?n:(console.warn(`[${t}] Invalid URL protocol in ${e}`),null)}catch(n){return console.warn(`[${t}] Could not parse url ${e}`,n),null}}const k={forceDeactivate:!0,base:``},A=`browser-plugin`;function j(e,t){if(t&&e.startsWith(t)){let n=e.slice(t.length);return n.startsWith(`/`)?n:`/${n}`}return e}function M(e,t){return t+e}function N(e,t){let n=O(e,A);return n?j(n.pathname,t)+n.search:null}var P=class{#e;#t;#n;#r;#i;constructor(e,t,n,r,i,a){this.#e=e,this.#t=r,this.#n=T(t,r);let o=(t,r)=>M(e.buildPath(t,r),n.base);this.#r=t.extendRouter({buildUrl:o,matchUrl:e=>{let r=N(e,n.base);return r?t.matchPath(r):void 0},replaceHistoryState:E(t,e,r,o)}),this.#i=w({browser:r,shared:a,handler:C({router:e,api:t,browser:r,allowNotFound:t.getOptions().allowNotFound,transitionOptions:i,loggerContext:`browser-plugin`,buildUrl:(t,n)=>e.buildUrl(t,n)}),cleanup:()=>{this.#n(),this.#r()}})}getPlugin(){return{...this.#i,onTransitionSuccess:(e,t,n)=>{let r=D(n,e,t),i=this.#e.buildUrl(e.name,e.params);b(e,!t||t.path===e.path?i+this.#t.getHash():i,r,this.#t)}}}};const F=x(k,A);function I(t,n){F(t);let r={...k,...t};r.base=m(r.base);let i=n??S(()=>h(j(globalThis.location.pathname,r.base))+globalThis.location.search,`browser-plugin`),a={forceDeactivate:r.forceDeactivate,source:`popstate`,replace:!0},o={removePopStateListener:void 0};return function(t){return new P(t,e(t),r,i,a,o).getPlugin()}}export{I as browserPluginFactory,c as isState};
2
+ //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/constants.ts","../../src/url-utils.ts","../../src/plugin.ts","../../src/validation.ts","../../src/factory.ts"],"names":["i"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIO,IAAM,cAAA,GAAiD;AAAA,EAC5D,eAAA,EAAiB,IAAA;AAAA,EACjB,IAAA,EAAM;AACR,CAAA;AAOO,IAAM,MAAA,GAAS,UAAA;AAEf,IAAM,cAAA,GAAiB,gBAAA;;;ACVvB,SAAS,WAAA,CAAY,UAAkB,IAAA,EAAsB;AAClE,EAAA,IAAI,IAAA,IAAQ,QAAA,CAAS,UAAA,CAAW,IAAI,CAAA,EAAG;AACrC,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,KAAA,CAAM,IAAA,CAAK,MAAM,CAAA;AAE3C,IAAA,OAAO,SAAS,UAAA,CAAW,GAAG,CAAA,GAAI,QAAA,GAAW,IAAI,QAAQ,CAAA,CAAA;AAAA,EAC3D;AAEA,EAAA,OAAO,QAAA;AACT;AAEO,SAAS,QAAA,CAAS,MAAc,IAAA,EAAsB;AAC3D,EAAA,OAAO,IAAA,GAAO,IAAA;AAChB;AAEO,SAAS,SAAA,CAAU,KAAa,IAAA,EAA6B;AAClE,EAAA,MAAM,SAAA,GAAY,CAAA,CAAa,GAAA,EAAK,cAAc,CAAA;AAElD,EAAA,OAAO,YACH,WAAA,CAAY,SAAA,CAAU,UAAU,IAAI,CAAA,GAAI,UAAU,MAAA,GAClD,IAAA;AACN;;;ACJO,IAAM,gBAAN,MAAoB;AAAA,EAChB,OAAA;AAAA,EACA,QAAA;AAAA,EACA,uBAAA;AAAA,EACA,iBAAA;AAAA,EACA,UAAA;AAAA,EAET,YACE,MAAA,EACA,GAAA,EACA,OAAA,EACA,OAAA,EACA,mBAKA,MAAA,EACA;AACA,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AACf,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA;AAEhB,IAAA,IAAA,CAAK,uBAAA,GAA0B,CAAA,CAAuB,GAAA,EAAK,OAAO,CAAA;AAElE,IAAA,MAAM,cAAA,GAAiB,CAAC,KAAA,EAAe,MAAA,KAAoB;AACzD,MAAA,MAAM,IAAA,GAAO,MAAA,CAAO,SAAA,CAAU,KAAA,EAAO,MAAM,CAAA;AAE3C,MAAA,OAAO,QAAA,CAAS,IAAA,EAAM,OAAA,CAAQ,IAAI,CAAA;AAAA,IACpC,CAAA;AAEA,IAAA,IAAA,CAAK,iBAAA,GAAoB,IAAI,YAAA,CAAa;AAAA,MACxC,QAAA,EAAU,cAAA;AAAA,MACV,QAAA,EAAU,CAAC,GAAA,KAAgB;AACzB,QAAA,MAAM,IAAA,GAAO,SAAA,CAAU,GAAA,EAAK,OAAA,CAAQ,IAAI,CAAA;AAExC,QAAA,OAAO,IAAA,GAAO,GAAA,CAAI,SAAA,CAAU,IAAI,CAAA,GAAI,MAAA;AAAA,MACtC,CAAA;AAAA,MACA,mBAAA,EAAqB,CAAA;AAAA,QACnB,GAAA;AAAA,QACA,MAAA;AAAA,QACA,OAAA;AAAA,QACA;AAAA;AACF,KACD,CAAA;AAED,IAAA,MAAM,UAAU,CAAA,CAAsB;AAAA,MACpC,MAAA;AAAA,MACA,GAAA;AAAA,MACA,OAAA;AAAA,MACA,aAAA,EAAe,GAAA,CAAI,UAAA,EAAW,CAAE,aAAA;AAAA,MAChC,iBAAA;AAAA,MACA,aAAA,EAAe,gBAAA;AAAA,MACf,UAAU,CAAC,IAAA,EAAc,WACvB,MAAA,CAAO,QAAA,CAAS,MAAM,MAAM;AAAA,KAC/B,CAAA;AAED,IAAA,IAAA,CAAK,aAAa,CAAA,CAAwB;AAAA,MACxC,OAAA;AAAA,MACA,MAAA;AAAA,MACA,OAAA;AAAA,MACA,SAAS,MAAM;AACb,QAAA,IAAA,CAAK,uBAAA,EAAwB;AAC7B,QAAA,IAAA,CAAK,iBAAA,EAAkB;AAAA,MACzB;AAAA,KACD,CAAA;AAAA,EACH;AAAA,EAEA,SAAA,GAAoB;AAClB,IAAA,OAAO;AAAA,MACL,GAAG,IAAA,CAAK,UAAA;AAAA,MAER,mBAAA,EAAqB,CACnB,OAAA,EACA,SAAA,EACA,UAAA,KACG;AACH,QAAA,MAAM,cAAA,GAAiB,CAAA;AAAA,UACrB,UAAA;AAAA,UACA,OAAA;AAAA,UACA;AAAA,SACF;AAEA,QAAA,MAAM,MAAM,IAAA,CAAK,OAAA,CAAQ,SAAS,OAAA,CAAQ,IAAA,EAAM,QAAQ,MAAM,CAAA;AAE9D,QAAA,MAAM,kBAAA,GACJ,CAAC,SAAA,IAAa,SAAA,CAAU,SAAS,OAAA,CAAQ,IAAA;AAE3C,QAAA,MAAM,WAAW,kBAAA,GACb,GAAA,GAAM,IAAA,CAAK,QAAA,CAAS,SAAQ,GAC5B,GAAA;AAEJ,QAAA,CAAA,CAAmB,OAAA,EAAS,QAAA,EAAU,cAAA,EAAgB,IAAA,CAAK,QAAQ,CAAA;AAAA,MACrE;AAAA,KACF;AAAA,EACF;AACF,CAAA;;;AC/GO,IAAM,eAAA,GAAkB,CAAA;AAAA,EAC7B,cAAA;AAAA,EACA;AACF,CAAA;;;ACOO,SAAS,oBAAA,CACd,MACA,OAAA,EACe;AACf,EAAA,eAAA,CAAgB,IAAI,CAAA;AAEpB,EAAA,MAAM,OAAA,GAA0C;AAAA,IAC9C,GAAG,cAAA;AAAA,IACH,GAAG;AAAA,GACL;AAEA,EAAA,OAAA,CAAQ,IAAA,GAAOA,EAAAA,CAAc,OAAA,CAAQ,IAAI,CAAA;AAEzC,EAAA,MAAM,kBACJ,OAAA,IACA,CAAA;AAAA,IACE,MACE,CAAA;AAAA,MACE,WAAA,CAAY,UAAA,CAAW,QAAA,CAAS,QAAA,EAAU,QAAQ,IAAI;AAAA,KACxD,GAAI,WAAW,QAAA,CAAS,MAAA;AAAA,IAC1B;AAAA,GACF;AAEF,EAAA,MAAM,kBAAkB,OAAA,CAAQ,eAAA;AAChC,EAAA,MAAM,iBAAA,GAAoB,EAAE,eAAA,EAAiB,MAAA,EAAQ,SAAS,IAAA,EAAc;AAE5E,EAAA,MAAM,MAAA,GAA6B,EAAE,sBAAA,EAAwB,MAAA,EAAU;AAEvE,EAAA,OAAO,SAAS,cAAc,UAAA,EAAY;AACxC,IAAA,MAAM,SAAS,IAAI,aAAA;AAAA,MACjB,UAAA;AAAA,MACA,aAAa,UAAU,CAAA;AAAA,MACvB,OAAA;AAAA,MACA,eAAA;AAAA,MACA,iBAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,OAAO,OAAO,SAAA,EAAU;AAAA,EAC1B,CAAA;AACF","file":"index.mjs","sourcesContent":["// packages/browser-plugin/modules/constants.ts\n\nimport type { BrowserPluginOptions } from \"./types\";\n\nexport const defaultOptions: Required<BrowserPluginOptions> = {\n forceDeactivate: true,\n base: \"\",\n};\n\n/**\n * Source identifier for transitions triggered by browser events.\n * Used to distinguish browser-initiated navigation (back/forward buttons)\n * from programmatic navigation (router.navigate()).\n */\nexport const source = \"popstate\";\n\nexport const LOGGER_CONTEXT = \"browser-plugin\";\n","// packages/browser-plugin/src/url-utils.ts\n\nimport { safeParseUrl } from \"browser-env\";\n\nimport { LOGGER_CONTEXT } from \"./constants\";\n\nexport function extractPath(pathname: string, base: string): string {\n if (base && pathname.startsWith(base)) {\n const stripped = pathname.slice(base.length);\n\n return stripped.startsWith(\"/\") ? stripped : `/${stripped}`;\n }\n\n return pathname;\n}\n\nexport function buildUrl(path: string, base: string): string {\n return base + path;\n}\n\nexport function urlToPath(url: string, base: string): string | null {\n const parsedUrl = safeParseUrl(url, LOGGER_CONTEXT);\n\n return parsedUrl\n ? extractPath(parsedUrl.pathname, base) + parsedUrl.search\n : null;\n}\n","import {\n createPopstateHandler,\n createPopstateLifecycle,\n createStartInterceptor,\n createReplaceHistoryState,\n shouldReplaceHistory,\n updateBrowserState,\n} from \"browser-env\";\n\nimport { buildUrl, urlToPath } from \"./url-utils\";\n\nimport type { BrowserPluginOptions } from \"./types\";\nimport type {\n NavigationOptions,\n Params,\n Router,\n State,\n Plugin,\n} from \"@real-router/core\";\nimport type { PluginApi } from \"@real-router/core/api\";\nimport type { Browser, SharedFactoryState } from \"browser-env\";\n\nexport class BrowserPlugin {\n readonly #router: Router;\n readonly #browser: Browser;\n readonly #removeStartInterceptor: () => void;\n readonly #removeExtensions: () => void;\n readonly #lifecycle: Pick<Plugin, \"onStart\" | \"onStop\" | \"teardown\">;\n\n constructor(\n router: Router,\n api: PluginApi,\n options: Required<BrowserPluginOptions>,\n browser: Browser,\n transitionOptions: {\n source: string;\n replace: true;\n forceDeactivate?: boolean;\n },\n shared: SharedFactoryState,\n ) {\n this.#router = router;\n this.#browser = browser;\n\n this.#removeStartInterceptor = createStartInterceptor(api, browser);\n\n const pluginBuildUrl = (route: string, params?: Params) => {\n const path = router.buildPath(route, params);\n\n return buildUrl(path, options.base);\n };\n\n this.#removeExtensions = api.extendRouter({\n buildUrl: pluginBuildUrl,\n matchUrl: (url: string) => {\n const path = urlToPath(url, options.base);\n\n return path ? api.matchPath(path) : undefined;\n },\n replaceHistoryState: createReplaceHistoryState(\n api,\n router,\n browser,\n pluginBuildUrl,\n ),\n });\n\n const handler = createPopstateHandler({\n router,\n api,\n browser,\n allowNotFound: api.getOptions().allowNotFound,\n transitionOptions,\n loggerContext: \"browser-plugin\",\n buildUrl: (name: string, params?: Params) =>\n router.buildUrl(name, params),\n });\n\n this.#lifecycle = createPopstateLifecycle({\n browser,\n shared,\n handler,\n cleanup: () => {\n this.#removeStartInterceptor();\n this.#removeExtensions();\n },\n });\n }\n\n getPlugin(): Plugin {\n return {\n ...this.#lifecycle,\n\n onTransitionSuccess: (\n toState: State,\n fromState: State | undefined,\n navOptions: NavigationOptions,\n ) => {\n const replaceHistory = shouldReplaceHistory(\n navOptions,\n toState,\n fromState,\n );\n\n const url = this.#router.buildUrl(toState.name, toState.params);\n\n const shouldPreserveHash =\n !fromState || fromState.path === toState.path;\n\n const finalUrl = shouldPreserveHash\n ? url + this.#browser.getHash()\n : url;\n\n updateBrowserState(toState, finalUrl, replaceHistory, this.#browser);\n },\n };\n }\n}\n","import { createOptionsValidator } from \"browser-env\";\n\nimport { LOGGER_CONTEXT, defaultOptions } from \"./constants\";\n\nimport type { BrowserPluginOptions } from \"./types\";\n\nexport const validateOptions = createOptionsValidator<BrowserPluginOptions>(\n defaultOptions,\n LOGGER_CONTEXT,\n);\n","import { getPluginApi } from \"@real-router/core/api\";\nimport {\n createSafeBrowser,\n normalizeBase,\n safelyEncodePath,\n} from \"browser-env\";\n\nimport { defaultOptions, source } from \"./constants\";\nimport { BrowserPlugin } from \"./plugin\";\nimport { extractPath } from \"./url-utils\";\nimport { validateOptions } from \"./validation\";\n\nimport type { BrowserPluginOptions } from \"./types\";\nimport type { PluginFactory, Router } from \"@real-router/core\";\nimport type { Browser, SharedFactoryState } from \"browser-env\";\n\nexport function browserPluginFactory(\n opts?: Partial<BrowserPluginOptions>,\n browser?: Browser,\n): PluginFactory {\n validateOptions(opts);\n\n const options: Required<BrowserPluginOptions> = {\n ...defaultOptions,\n ...opts,\n };\n\n options.base = normalizeBase(options.base);\n\n const resolvedBrowser =\n browser ??\n createSafeBrowser(\n () =>\n safelyEncodePath(\n extractPath(globalThis.location.pathname, options.base),\n ) + globalThis.location.search,\n \"browser-plugin\",\n );\n\n const forceDeactivate = options.forceDeactivate;\n const transitionOptions = { forceDeactivate, source, replace: true as const };\n\n const shared: SharedFactoryState = { removePopStateListener: undefined };\n\n return function browserPlugin(routerBase) {\n const plugin = new BrowserPlugin(\n routerBase as Router,\n getPluginApi(routerBase),\n options,\n resolvedBrowser,\n transitionOptions,\n shared,\n );\n\n return plugin.getPlugin();\n };\n}\n"]}
1
+ {"version":3,"file":"index.mjs","names":["n","r","a","o","s","c","d","e","p","t","safeParseUrl","#router","#browser","#removeStartInterceptor","#removeExtensions","#lifecycle","createStartInterceptor","createReplaceHistoryState","createPopstateLifecycle","createPopstateHandler","shouldReplaceHistory","createOptionsValidator","normalizeBase","createSafeBrowser","safelyEncodePath"],"sources":["../../../type-guards/dist/esm/index.mjs","../../../browser-env/dist/esm/index.mjs","../../src/constants.ts","../../src/url-utils.ts","../../src/plugin.ts","../../src/validation.ts","../../src/factory.ts"],"sourcesContent":["const e=[`replace`,`reload`,`force`,`forceDeactivate`,`redirected`];function t(t){if(typeof t!=`object`||!t||Array.isArray(t))return!1;let n=t;for(let t of e){let e=n[t];if(e!==void 0&&typeof e!=`boolean`)return!1}let r=n.signal;return!(r!==void 0&&!(r instanceof AbortSignal))}const n=/\\S/,r=/^[A-Z_a-z][\\w-]*(?:\\.[A-Z_a-z][\\w-]*)*$/;function i(e,t){return TypeError(`[router.${e}] ${t}`)}function a(e){return typeof e==`string`?e===``?!0:e.length>1e4?!1:e.startsWith(`@@`)?!0:r.test(e):!1}function o(e,t=new WeakSet){if(e==null)return!0;let n=typeof e;if(n===`string`||n===`boolean`)return!0;if(n===`number`)return Number.isFinite(e);if(n===`function`||n===`symbol`)return!1;if(Array.isArray(e))return t.has(e)?!1:(t.add(e),e.every(e=>o(e,t)));if(n===`object`){if(t.has(e))return!1;t.add(e);let n=Object.getPrototypeOf(e);return n!==null&&n!==Object.prototype?!1:Object.values(e).every(e=>o(e,t))}return!1}function s(e){if(e==null)return!0;let t=typeof e;return t===`string`||t===`boolean`?!0:t===`number`?Number.isFinite(e):!1}function c(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);if(t!==null&&t!==Object.prototype)return!1;let n=!1;for(let t in e){if(!Object.hasOwn(e,t))continue;let r=e[t];if(!s(r)){let e=typeof r;if(e===`function`||e===`symbol`)return!1;n=!0;break}}return n?o(e):!0}function l(e){if(e==null)return!0;let t=typeof e;return t===`string`||t===`boolean`?!0:t===`number`?Number.isFinite(e):Array.isArray(e)?e.every(e=>{let t=typeof e;return t===`string`||t===`boolean`?!0:t===`number`?Number.isFinite(e):!1}):!1}function u(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;for(let t in e){if(!Object.hasOwn(e,t))continue;let n=e[t];if(!l(n))return!1}return!0}function d(e){return a(e.name)&&typeof e.path==`string`&&c(e.params)}function f(e){return typeof e!=`object`||!e?!1:d(e)}function p(e){return!(typeof e!=`object`||!e||!d(e))}function m(e){return typeof e==`string`}function h(e){return typeof e==`boolean`}function g(e,t){return e in t}function _(e){return typeof e==`number`?Number.isFinite(e):typeof e==`string`||typeof e==`boolean`}function v(e,t){if(typeof e!=`string`)throw i(t,`Route name must be a string, got ${typeof e}`);if(e!==``){if(!n.test(e))throw i(t,`Route name cannot contain only whitespace`);if(e.length>1e4)throw i(t,`Route name exceeds maximum length of 10000 characters. This is a technical safety limit.`);if(!e.startsWith(`@@`)&&!r.test(e))throw i(t,`Invalid route name \"${e}\". Each segment must start with a letter or underscore, followed by letters, numbers, underscores, or hyphens. Segments are separated by dots (e.g., \"users.profile\").`)}}function y(e){return e===null?`null`:Array.isArray(e)?`array[${e.length}]`:typeof e==`object`?`constructor`in e&&e.constructor.name!==`Object`?e.constructor.name:`object`:typeof e}function b(e,t){if(!f(e))throw TypeError(`[${t}] Invalid state structure: ${y(e)}. Expected State object with name, params, and path properties.`)}export{y as getTypeDescription,h as isBoolean,t as isNavigationOptions,g as isObjKey,c as isParams,u as isParamsStrict,_ as isPrimitiveValue,a as isRouteName,f as isState,p as isStateStrict,m as isString,v as validateRouteName,b as validateState};\n//# sourceMappingURL=index.mjs.map","import{isStateStrict as e}from\"type-guards\";import{RouterError as t}from\"@real-router/core\";const n=()=>globalThis.window!==void 0&&!!globalThis.history,r=(e,t)=>{globalThis.history.pushState(e,``,t)},i=(e,t)=>{globalThis.history.replaceState(e,``,t)},a=e=>(globalThis.addEventListener(`popstate`,e),()=>{globalThis.removeEventListener(`popstate`,e)}),o=()=>globalThis.location.hash;function s(e){if(!e)return e;let t=e;return t.startsWith(`/`)||(t=`/${t}`),t.endsWith(`/`)&&(t=t.slice(0,-1)),t}const c=e=>{try{return encodeURI(decodeURI(e))}catch(t){return console.warn(`[browser-env] Could not encode path \"${e}\"`,t),e}},l=()=>{},u=e=>{let t=!1;return n=>{t||=(console.warn(`[browser-env] Browser API is running in a non-browser environment (context: \"${e}\"). Method \"${n}\" is a no-op. This is expected for SSR, but may indicate misconfiguration if you expected browser behavior.`),!0)}},d=e=>{let t=u(e);return{pushState:()=>{t(`pushState`)},replaceState:()=>{t(`replaceState`)},addPopstateListener:()=>(t(`addPopstateListener`),l),getHash:()=>(t(`getHash`),``)}};function f(t,n,r){if(e(t.state))return{name:t.state.name,params:t.state.params};let i=n.matchPath(r.getLocation());return i?{name:i.name,params:i.params}:void 0}function p(e,t,n,r){let i={name:e.name,params:e.params,path:e.path};n?r.replaceState(i,t):r.pushState(i,t)}function m(e,t){return n=>{if(n){for(let r of Object.keys(n))if(r in e){let i=n[r],a=typeof e[r],o=typeof i;if(i!==void 0&&o!==a)throw Error(`[${t}] Invalid type for '${r}': expected ${a}, got ${o}`)}}}}function h(e,t){if(n())return{pushState:r,replaceState:i,addPopstateListener:a,getLocation:e,getHash:o};let s=u(t);return{...d(t),getLocation:()=>(s(`getLocation`),``)}}function g(e){let n=!1,r=null;function i(){if(r){let t=r;r=null,console.warn(`[${e.loggerContext}] Processing deferred popstate event`),o(t)}}function a(t){console.error(`[${e.loggerContext}] Critical error in onPopState`,t);try{let t=e.router.getState();if(t){let n=e.buildUrl(t.name,t.params);e.browser.replaceState(t,n)}}catch(t){console.error(`[${e.loggerContext}] Failed to recover from critical error`,t)}}async function o(o){if(n){console.warn(`[${e.loggerContext}] Transition in progress, deferring popstate event`),r=o;return}n=!0;try{let t=f(o,e.api,e.browser);t?await e.router.navigate(t.name,t.params,e.transitionOptions):e.allowNotFound?e.router.navigateToNotFound(e.browser.getLocation()):await e.router.navigateToDefault({...e.transitionOptions,reload:!0,replace:!0})}catch(e){e instanceof t||a(e)}finally{n=!1,i()}}return e=>void o(e)}function _(e){return{onStart:()=>{e.shared.removePopStateListener&&e.shared.removePopStateListener(),e.shared.removePopStateListener=e.browser.addPopstateListener(e.handler)},onStop:()=>{e.shared.removePopStateListener&&(e.shared.removePopStateListener(),e.shared.removePopStateListener=void 0)},teardown:()=>{e.shared.removePopStateListener&&(e.shared.removePopStateListener(),e.shared.removePopStateListener=void 0),e.cleanup()}}}function v(e,t){return e.addInterceptor(`start`,(e,n)=>e(n??t.getLocation()))}function y(e,t,n,r){return(i,a={})=>{let o=e.buildState(i,a);if(!o)throw Error(`[real-router] Cannot replace state: route \"${i}\" is not found`);p(e.makeState(o.name,o.params,t.buildPath(o.name,o.params),{params:o.meta}),r(i,a),!0,n)}}function b(e,t,n){return(e.replace??!n)||!!e.reload&&t.path===n.path}function x(e,t){try{let n=new URL(e,globalThis.location.origin);return[`http:`,`https:`].includes(n.protocol)?n:(console.warn(`[${t}] Invalid URL protocol in ${e}`),null)}catch(n){return console.warn(`[${t}] Could not parse url ${e}`,n),null}}export{a as addPopstateListener,d as createHistoryFallbackBrowser,m as createOptionsValidator,g as createPopstateHandler,_ as createPopstateLifecycle,y as createReplaceHistoryState,h as createSafeBrowser,v as createStartInterceptor,u as createWarnOnce,o as getHash,f as getRouteFromEvent,n as isBrowserEnvironment,s as normalizeBase,r as pushState,i as replaceState,x as safeParseUrl,c as safelyEncodePath,b as shouldReplaceHistory,p as updateBrowserState};\n//# sourceMappingURL=index.mjs.map","// packages/browser-plugin/modules/constants.ts\n\nimport type { BrowserPluginOptions } from \"./types\";\n\nexport const defaultOptions: Required<BrowserPluginOptions> = {\n forceDeactivate: true,\n base: \"\",\n};\n\n/**\n * Source identifier for transitions triggered by browser events.\n * Used to distinguish browser-initiated navigation (back/forward buttons)\n * from programmatic navigation (router.navigate()).\n */\nexport const source = \"popstate\";\n\nexport const LOGGER_CONTEXT = \"browser-plugin\";\n","// packages/browser-plugin/src/url-utils.ts\n\nimport { safeParseUrl } from \"browser-env\";\n\nimport { LOGGER_CONTEXT } from \"./constants\";\n\nexport function extractPath(pathname: string, base: string): string {\n if (base && pathname.startsWith(base)) {\n const stripped = pathname.slice(base.length);\n\n return stripped.startsWith(\"/\") ? stripped : `/${stripped}`;\n }\n\n return pathname;\n}\n\nexport function buildUrl(path: string, base: string): string {\n return base + path;\n}\n\nexport function urlToPath(url: string, base: string): string | null {\n const parsedUrl = safeParseUrl(url, LOGGER_CONTEXT);\n\n return parsedUrl\n ? extractPath(parsedUrl.pathname, base) + parsedUrl.search\n : null;\n}\n","import {\n createPopstateHandler,\n createPopstateLifecycle,\n createStartInterceptor,\n createReplaceHistoryState,\n shouldReplaceHistory,\n updateBrowserState,\n} from \"browser-env\";\n\nimport { buildUrl, urlToPath } from \"./url-utils\";\n\nimport type { BrowserPluginOptions } from \"./types\";\nimport type {\n NavigationOptions,\n Params,\n Router,\n State,\n Plugin,\n} from \"@real-router/core\";\nimport type { PluginApi } from \"@real-router/core/api\";\nimport type { Browser, SharedFactoryState } from \"browser-env\";\n\nexport class BrowserPlugin {\n readonly #router: Router;\n readonly #browser: Browser;\n readonly #removeStartInterceptor: () => void;\n readonly #removeExtensions: () => void;\n readonly #lifecycle: Pick<Plugin, \"onStart\" | \"onStop\" | \"teardown\">;\n\n constructor(\n router: Router,\n api: PluginApi,\n options: Required<BrowserPluginOptions>,\n browser: Browser,\n transitionOptions: {\n source: string;\n replace: true;\n forceDeactivate?: boolean;\n },\n shared: SharedFactoryState,\n ) {\n this.#router = router;\n this.#browser = browser;\n\n this.#removeStartInterceptor = createStartInterceptor(api, browser);\n\n const pluginBuildUrl = (route: string, params?: Params) => {\n const path = router.buildPath(route, params);\n\n return buildUrl(path, options.base);\n };\n\n this.#removeExtensions = api.extendRouter({\n buildUrl: pluginBuildUrl,\n matchUrl: (url: string) => {\n const path = urlToPath(url, options.base);\n\n return path ? api.matchPath(path) : undefined;\n },\n replaceHistoryState: createReplaceHistoryState(\n api,\n router,\n browser,\n pluginBuildUrl,\n ),\n });\n\n const handler = createPopstateHandler({\n router,\n api,\n browser,\n allowNotFound: api.getOptions().allowNotFound,\n transitionOptions,\n loggerContext: \"browser-plugin\",\n buildUrl: (name: string, params?: Params) =>\n router.buildUrl(name, params),\n });\n\n this.#lifecycle = createPopstateLifecycle({\n browser,\n shared,\n handler,\n cleanup: () => {\n this.#removeStartInterceptor();\n this.#removeExtensions();\n },\n });\n }\n\n getPlugin(): Plugin {\n return {\n ...this.#lifecycle,\n\n onTransitionSuccess: (\n toState: State,\n fromState: State | undefined,\n navOptions: NavigationOptions,\n ) => {\n const replaceHistory = shouldReplaceHistory(\n navOptions,\n toState,\n fromState,\n );\n\n const url = this.#router.buildUrl(toState.name, toState.params);\n\n const shouldPreserveHash =\n !fromState || fromState.path === toState.path;\n\n const finalUrl = shouldPreserveHash\n ? url + this.#browser.getHash()\n : url;\n\n updateBrowserState(toState, finalUrl, replaceHistory, this.#browser);\n },\n };\n }\n}\n","import { createOptionsValidator } from \"browser-env\";\n\nimport { LOGGER_CONTEXT, defaultOptions } from \"./constants\";\n\nimport type { BrowserPluginOptions } from \"./types\";\n\nexport const validateOptions = createOptionsValidator<BrowserPluginOptions>(\n defaultOptions,\n LOGGER_CONTEXT,\n);\n","import { getPluginApi } from \"@real-router/core/api\";\nimport {\n createSafeBrowser,\n normalizeBase,\n safelyEncodePath,\n} from \"browser-env\";\n\nimport { defaultOptions, source } from \"./constants\";\nimport { BrowserPlugin } from \"./plugin\";\nimport { extractPath } from \"./url-utils\";\nimport { validateOptions } from \"./validation\";\n\nimport type { BrowserPluginOptions } from \"./types\";\nimport type { PluginFactory, Router } from \"@real-router/core\";\nimport type { Browser, SharedFactoryState } from \"browser-env\";\n\nexport function browserPluginFactory(\n opts?: Partial<BrowserPluginOptions>,\n browser?: Browser,\n): PluginFactory {\n validateOptions(opts);\n\n const options: Required<BrowserPluginOptions> = {\n ...defaultOptions,\n ...opts,\n };\n\n options.base = normalizeBase(options.base);\n\n const resolvedBrowser =\n browser ??\n createSafeBrowser(\n () =>\n safelyEncodePath(\n extractPath(globalThis.location.pathname, options.base),\n ) + globalThis.location.search,\n \"browser-plugin\",\n );\n\n const forceDeactivate = options.forceDeactivate;\n const transitionOptions = { forceDeactivate, source, replace: true as const };\n\n const shared: SharedFactoryState = { removePopStateListener: undefined };\n\n return function browserPlugin(routerBase) {\n const plugin = new BrowserPlugin(\n routerBase as Router,\n getPluginApi(routerBase),\n options,\n resolvedBrowser,\n transitionOptions,\n shared,\n );\n\n return plugin.getPlugin();\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@real-router/browser-plugin",
3
- "version": "0.11.0",
3
+ "version": "0.11.2",
4
4
  "type": "commonjs",
5
5
  "description": "Browser integration plugin with History API, hash routing, and popstate support",
6
6
  "main": "./dist/cjs/index.js",
@@ -45,23 +45,23 @@
45
45
  },
46
46
  "sideEffects": false,
47
47
  "dependencies": {
48
- "@real-router/core": "^0.41.0"
48
+ "@real-router/core": "^0.43.0"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@testing-library/jest-dom": "6.9.1",
52
52
  "jsdom": "28.1.0",
53
- "browser-env": "^0.2.1",
54
- "type-guards": "^0.4.1"
53
+ "browser-env": "^0.2.3",
54
+ "type-guards": "^0.4.3"
55
55
  },
56
56
  "scripts": {
57
57
  "test": "vitest",
58
58
  "test:stress": "vitest --config vitest.config.stress.mts --run",
59
59
  "test:properties": "vitest --config vitest.config.properties.mts --run",
60
- "build": "tsup",
60
+ "build": "tsdown --config-loader unrun",
61
61
  "type-check": "tsc --noEmit",
62
62
  "lint": "eslint --cache --ext .ts src/ tests/ --fix --max-warnings 0",
63
63
  "lint:package": "publint",
64
64
  "lint:types": "attw --pack .",
65
- "build:dist-only": "tsup"
65
+ "build:dist-only": "tsdown --config-loader unrun"
66
66
  }
67
67
  }
@@ -1 +0,0 @@
1
- {"inputs":{"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.21.0_typescript@6.0.2_yaml@2.8.3/node_modules/tsup/assets/cjs_shims.js":{"bytes":569,"imports":[],"format":"esm"},"../type-guards/dist/esm/index.mjs":{"bytes":3269,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.21.0_typescript@6.0.2_yaml@2.8.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"../browser-env/dist/esm/index.mjs":{"bytes":4128,"imports":[{"path":"../type-guards/dist/esm/index.mjs","kind":"import-statement","original":"type-guards"},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.21.0_typescript@6.0.2_yaml@2.8.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/constants.ts":{"bytes":493,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.21.0_typescript@6.0.2_yaml@2.8.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/url-utils.ts":{"bytes":703,"imports":[{"path":"../browser-env/dist/esm/index.mjs","kind":"import-statement","original":"browser-env"},{"path":"src/constants.ts","kind":"import-statement","original":"./constants"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.21.0_typescript@6.0.2_yaml@2.8.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/plugin.ts":{"bytes":2920,"imports":[{"path":"../browser-env/dist/esm/index.mjs","kind":"import-statement","original":"browser-env"},{"path":"src/url-utils.ts","kind":"import-statement","original":"./url-utils"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.21.0_typescript@6.0.2_yaml@2.8.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/validation.ts":{"bytes":288,"imports":[{"path":"../browser-env/dist/esm/index.mjs","kind":"import-statement","original":"browser-env"},{"path":"src/constants.ts","kind":"import-statement","original":"./constants"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.21.0_typescript@6.0.2_yaml@2.8.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/factory.ts":{"bytes":1517,"imports":[{"path":"@real-router/core/api","kind":"import-statement","external":true},{"path":"../browser-env/dist/esm/index.mjs","kind":"import-statement","original":"browser-env"},{"path":"src/constants.ts","kind":"import-statement","original":"./constants"},{"path":"src/plugin.ts","kind":"import-statement","original":"./plugin"},{"path":"src/url-utils.ts","kind":"import-statement","original":"./url-utils"},{"path":"src/validation.ts","kind":"import-statement","original":"./validation"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.21.0_typescript@6.0.2_yaml@2.8.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":1311,"imports":[{"path":"src/factory.ts","kind":"import-statement","original":"./factory"},{"path":"../type-guards/dist/esm/index.mjs","kind":"import-statement","original":"type-guards"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.21.0_typescript@6.0.2_yaml@2.8.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"}},"outputs":{"dist/cjs/index.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":8850},"dist/cjs/index.js":{"imports":[{"path":"@real-router/core/api","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true}],"exports":["browserPluginFactory","isState"],"entryPoint":"src/index.ts","inputs":{"src/factory.ts":{"bytesInOutput":829},"../type-guards/dist/esm/index.mjs":{"bytesInOutput":1569},"../browser-env/dist/esm/index.mjs":{"bytesInOutput":4725},"src/constants.ts":{"bytesInOutput":126},"src/url-utils.ts":{"bytesInOutput":442},"src/plugin.ts":{"bytesInOutput":1766},"src/validation.ts":{"bytesInOutput":63},"src/index.ts":{"bytesInOutput":0}},"bytes":9766}}}
@@ -1 +0,0 @@
1
- {"inputs":{"../type-guards/dist/esm/index.mjs":{"bytes":3269,"imports":[],"format":"esm"},"../browser-env/dist/esm/index.mjs":{"bytes":4128,"imports":[{"path":"../type-guards/dist/esm/index.mjs","kind":"import-statement","original":"type-guards"},{"path":"@real-router/core","kind":"import-statement","external":true}],"format":"esm"},"src/constants.ts":{"bytes":493,"imports":[],"format":"esm"},"src/url-utils.ts":{"bytes":703,"imports":[{"path":"../browser-env/dist/esm/index.mjs","kind":"import-statement","original":"browser-env"},{"path":"src/constants.ts","kind":"import-statement","original":"./constants"}],"format":"esm"},"src/plugin.ts":{"bytes":2920,"imports":[{"path":"../browser-env/dist/esm/index.mjs","kind":"import-statement","original":"browser-env"},{"path":"src/url-utils.ts","kind":"import-statement","original":"./url-utils"}],"format":"esm"},"src/validation.ts":{"bytes":288,"imports":[{"path":"../browser-env/dist/esm/index.mjs","kind":"import-statement","original":"browser-env"},{"path":"src/constants.ts","kind":"import-statement","original":"./constants"}],"format":"esm"},"src/factory.ts":{"bytes":1517,"imports":[{"path":"@real-router/core/api","kind":"import-statement","external":true},{"path":"../browser-env/dist/esm/index.mjs","kind":"import-statement","original":"browser-env"},{"path":"src/constants.ts","kind":"import-statement","original":"./constants"},{"path":"src/plugin.ts","kind":"import-statement","original":"./plugin"},{"path":"src/url-utils.ts","kind":"import-statement","original":"./url-utils"},{"path":"src/validation.ts","kind":"import-statement","original":"./validation"}],"format":"esm"},"src/index.ts":{"bytes":1311,"imports":[{"path":"src/factory.ts","kind":"import-statement","original":"./factory"},{"path":"../type-guards/dist/esm/index.mjs","kind":"import-statement","original":"type-guards"}],"format":"esm"}},"outputs":{"dist/esm/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":8850},"dist/esm/index.mjs":{"imports":[{"path":"@real-router/core/api","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true}],"exports":["browserPluginFactory","isState"],"entryPoint":"src/index.ts","inputs":{"src/factory.ts":{"bytesInOutput":829},"../type-guards/dist/esm/index.mjs":{"bytesInOutput":1569},"../browser-env/dist/esm/index.mjs":{"bytesInOutput":4725},"src/constants.ts":{"bytesInOutput":126},"src/url-utils.ts":{"bytesInOutput":442},"src/plugin.ts":{"bytesInOutput":1766},"src/validation.ts":{"bytesInOutput":63},"src/index.ts":{"bytesInOutput":0}},"bytes":9766}}}