@real-router/browser-plugin 0.17.4 → 0.17.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@real-router/core/api`),t=require(`@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.replaceAll(/\/+/g,`/`);return t.startsWith(`/`)||(t=`/${t}`),t.length>1&&t.endsWith(`/`)&&(t=t.slice(0,-1)),t===`/`?``: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`),``)}},f=/^[A-Z_a-z][\w-]*(?:\.[A-Z_a-z][\w-]*)*$/;function p(e){return typeof e==`string`?e===``?!0:e.length>1e4?!1:e.startsWith(`@@`)?!0:f.test(e):!1}function m(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=>m(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=>m(e,t))}return!1}function h(e){if(e==null)return!0;let t=typeof e;return t===`string`||t===`boolean`?!0:t===`number`?Number.isFinite(e):!1}function g(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(!h(r)){let e=typeof r;if(e===`function`||e===`symbol`)return!1;n=!0;break}}return n?m(e):!0}function _(e){return p(e.name)&&typeof e.path==`string`&&g(e.params)}function v(e){return!(typeof e!=`object`||!e||!_(e))}function y(e,t,n){return v(e.state)?t.makeState(e.state.name,e.state.params,e.state.path):t.matchPath(n.getLocation())}function b(){let e={name:``,params:{},path:``};return(t,n,r,i)=>{e.name=t.name,e.params=t.params,e.path=t.path,r?i.replaceState(e,n):i.pushState(e,n)}}function x(e,t,n){return r=>{if(r)for(let i of Object.keys(r)){if(!(i in e))continue;let a=r[i];if(a===void 0)continue;let o=typeof e[i],s=typeof a;if(s!==o)throw Error(`[${t}] Invalid type for '${i}': expected ${o}, got ${s}`);let c=n?.[i];if(c){let e=c.validate(a);if(e!==null)throw Error(`[${t}] Invalid '${i}': ${e}`)}}}}const S=/[\u0000-\u001F\u007F]/,C={validate:e=>S.test(e)?`must not contain control characters`:e.split(`/`).includes(`..`)?`must not contain '..' segments`:null};function w(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 T(e,t){if(!e.getCurrentHash)return{};let n=e.getCurrentHash();return n!==(e.getCurrentContextHash?e.getCurrentContextHash():``)&&e.router.getState()?.path===t?{hash:n,force:!0,hashChange:!0}:{hash:n}}function E(e){let n=!1,r=null;function i(){if(r){let t=r;r=null,console.warn(`[${e.loggerContext}] Processing deferred popstate event`),s(t)}}function a(){let t=e.router.getState();if(!t)return;let n=t.context?.url?.hash,r=e.buildUrl(t.name,t.params,n?{hash:n}:void 0);e.browser.replaceState(t,r)}function o(t){console.error(`[${e.loggerContext}] Critical error in onPopState`,t);try{a()}catch(t){console.error(`[${e.loggerContext}] Failed to recover from critical error`,t)}}async function s(s){if(n){console.warn(`[${e.loggerContext}] Transition in progress, deferring popstate event`),r=s;return}n=!0;try{let n=y(s,e.api,e.browser);if(n)await e.api.navigateToState(n,{...e.transitionOptions,...T(e,n.path)});else if(e.allowNotFound)e.router.navigateToNotFound(e.browser.getLocation());else{let n=new t.RouterError(t.errorCodes.ROUTE_NOT_FOUND,{path:e.browser.getLocation()});e.api.emitTransitionError(n),a()}}catch(e){if(e instanceof t.RouterError)try{a()}catch{}else o(e)}finally{n=!1,i()}}return e=>void s(e)}function D(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 O(e){return encodeURI(e).replaceAll(`#`,`%23`)}function k(e){try{return decodeURIComponent(e)}catch{return e}}function A(e){let t=e;for(;t.startsWith(`#`);)t=t.slice(1);return k(t)}function j(e){let t=e.getHash();return t?k(t.startsWith(`#`)?t.slice(1):t):``}function M(e){let t=e,n=t.indexOf(`://`);if(n!==-1){let e=n+3,r=t.length;for(let n=e;n<t.length;n++){let e=t[n];if(e===`/`||e===`?`||e===`#`){r=n;break}}t=r===t.length?`/`:t.slice(r),(t.startsWith(`?`)||t.startsWith(`#`))&&(t=`/${t}`)}let r=t.indexOf(`#`),i=r===-1?``:t.slice(r),a=r===-1?t:t.slice(0,r),o=a.indexOf(`?`),s=o===-1?``:a.slice(o);return{pathname:o===-1?a:a.slice(0,o),search:s,hash:i}}function N(e,t){if(!e)return`/`;if(t&&(e===t||e.startsWith(`${t}/`))){let n=e.slice(t.length);return n.startsWith(`/`)?n:`/${n}`}return e.startsWith(`/`)?e:`/${e}`}function P(e,t){return e?t?e===`/`?t:e.startsWith(`/`)?`${t}${e}`:`${t}/${e}`:e.startsWith(`/`)?e:`/${e}`:t}function F(e,t){let n=M(e);return N(n.pathname,t)+n.search}function I(e,t){return e.addInterceptor(`start`,(e,n)=>e(n??t.getLocation()))}function L(e,t){return(n,r,i)=>{let a=P(e.buildPath(n,r),t);if(i?.hash===void 0)return a;let o=A(i.hash);return o?`${a}#${O(o)}`:a}}function R(e,t,n,r,i=!0){let a={name:``,params:{},path:``};return(o,s={},c)=>{let l=e.buildState(o,s);if(!l)throw Error(`[real-router] Cannot replace state: route "${o}" is not found`);let u=e.makeState(l.name,l.params,t.buildPath(l.name,l.params),{params:l.meta}),d;if(c?.hash!==void 0){let e=A(c.hash);d=e?`#${O(e)}`:``}else d=i?n.getHash():``;let f=r(o,s)+d;a.name=u.name,a.params=u.params,a.path=u.path,n.replaceState(a,f)}}function z(e,t,n){return e.replace===!0?!0:n?!!e.reload&&t.path===n.path:e.replace!==!1}const B={forceDeactivate:!0,base:``},V=`popstate`,H=`browser-plugin`,U=x(B,H,{base:C}),W=Object.freeze({source:`popstate`,direction:`back`}),G=Object.freeze({source:`navigate`,direction:`forward`});function K(t,n){U(t);let r={...B,...t};r.base=s(r.base);let i=n??q(r.base),a={forceDeactivate:r.forceDeactivate,source:V,replace:!0},o={removePopStateListener:void 0};return function(t){return J(t,(0,e.getPluginApi)(t),r,i,a,o)}}function q(e){let t=`\0`,n=``,r=``;return w(()=>{let{pathname:i,search:a}=globalThis.location;return i===t&&a===n?r:(t=i,n=a,r=c(N(i,e))+a,r)},`browser-plugin`)}function J(e,t,n,r,i,a){let o=t.claimContextNamespace(`browser`),s=t.claimContextNamespace(`url`),c=b(),l=I(t,r),u=L(e,n.base),d=t.extendRouter({buildUrl:u,matchUrl:e=>t.matchPath(F(e,n.base))??void 0,replaceHistoryState:R(t,e,r,u)});return{...D({browser:r,shared:a,handler:E({router:e,api:t,browser:r,allowNotFound:t.getOptions().allowNotFound,transitionOptions:i,loggerContext:H,buildUrl:u,getCurrentHash:()=>j(r),getCurrentContextHash:()=>(e.getState()?.context)?.url?.hash??``}),cleanup:()=>{l(),d(),o.release(),s.release()}}),onTransitionSuccess:(e,t,i)=>{let a=z(i,e,t),l=j(r),u=(t?.context)?.url?.hash??``,d=i.hash===void 0?l:A(i.hash);s.write(e,Object.freeze({hash:d,hashChanged:i.hashChange??d!==u}));let f=P(e.path,n.base);c(e,d?`${f}#${O(d)}`:f,a,r);let p=i.source===V;o.write(e,p?W:G)}}}exports.browserPluginFactory=K,exports.isState=v;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@real-router/core/api"),t=require("@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.replaceAll(/\/+/g,`/`);return t.startsWith(`/`)||(t=`/${t}`),t.length>1&&t.endsWith(`/`)&&(t=t.slice(0,-1)),t===`/`?``: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`),``)}},f=/^[A-Z_a-z][\w-]*(?:\.[A-Z_a-z][\w-]*)*$/;function p(e){return typeof e==`string`?e===``?!0:e.length>1e4?!1:e.startsWith(`@@`)?!0:f.test(e):!1}function m(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=>m(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=>m(e,t))}return!1}function h(e){if(e==null)return!0;let t=typeof e;return t===`string`||t===`boolean`?!0:t===`number`?Number.isFinite(e):!1}function g(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(!h(r)){let e=typeof r;if(e===`function`||e===`symbol`)return!1;n=!0;break}}return n?m(e):!0}function _(e){return p(e.name)&&typeof e.path==`string`&&g(e.params)}function v(e){return!(typeof e!=`object`||!e||!_(e))}function y(e,t,n){return v(e.state)?t.makeState(e.state.name,e.state.params,e.state.path):t.matchPath(n.getLocation())}function b(){let e={name:``,params:{},path:``};return(t,n,r,i)=>{e.name=t.name,e.params=t.params,e.path=t.path,r?i.replaceState(e,n):i.pushState(e,n)}}function x(e,t,n){return r=>{if(r)for(let i of Object.keys(r)){if(!(i in e))continue;let a=r[i];if(a===void 0)continue;let o=typeof e[i],s=typeof a;if(s!==o)throw Error(`[${t}] Invalid type for '${i}': expected ${o}, got ${s}`);let c=n?.[i];if(c){let e=c.validate(a);if(e!==null)throw Error(`[${t}] Invalid '${i}': ${e}`)}}}}const S=/[\u0000-\u001F\u007F]/,C={validate:e=>S.test(e)?`must not contain control characters`:e.split(`/`).includes(`..`)?`must not contain '..' segments`:null};function w(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 T(e,t){if(!e.getCurrentHash)return{};let n=e.getCurrentHash();return n!==(e.getCurrentContextHash?e.getCurrentContextHash():``)&&e.router.getState()?.path===t?{hash:n,force:!0,hashChange:!0}:{hash:n}}function E(e){let n=!1,r=null;function i(){if(r){let t=r;r=null,console.warn(`[${e.loggerContext}] Processing deferred popstate event`),s(t)}}function a(){let t=e.router.getState();if(!t)return;let n=t.context?.url?.hash,r=e.buildUrl(t.name,t.params,n?{hash:n}:void 0);e.browser.replaceState(t,r)}function o(t){console.error(`[${e.loggerContext}] Critical error in onPopState`,t);try{a()}catch(t){console.error(`[${e.loggerContext}] Failed to recover from critical error`,t)}}async function s(s){if(n){console.warn(`[${e.loggerContext}] Transition in progress, deferring popstate event`),r=s;return}n=!0;try{let n=y(s,e.api,e.browser);if(n)await e.api.navigateToState(n,{...e.transitionOptions,...T(e,n.path)});else if(e.allowNotFound)e.router.navigateToNotFound(e.browser.getLocation());else{let n=new t.RouterError(t.errorCodes.ROUTE_NOT_FOUND,{path:e.browser.getLocation()});e.api.emitTransitionError(n),a()}}catch(e){if(e instanceof t.RouterError)try{a()}catch{}else o(e)}finally{n=!1,i()}}return e=>void s(e)}function D(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 O(e){return encodeURI(e).replaceAll(`#`,`%23`)}function k(e){try{return decodeURIComponent(e)}catch{return e}}function A(e){let t=e;for(;t.startsWith(`#`);)t=t.slice(1);return k(t)}function j(e){let t=e.getHash();return t?k(t.startsWith(`#`)?t.slice(1):t):``}function M(e){let t=e,n=t.indexOf(`://`);if(n!==-1){let e=n+3,r=t.length;for(let n=e;n<t.length;n++){let e=t[n];if(e===`/`||e===`?`||e===`#`){r=n;break}}t=r===t.length?`/`:t.slice(r),(t.startsWith(`?`)||t.startsWith(`#`))&&(t=`/${t}`)}let r=t.indexOf(`#`),i=r===-1?``:t.slice(r),a=r===-1?t:t.slice(0,r),o=a.indexOf(`?`),s=o===-1?``:a.slice(o);return{pathname:o===-1?a:a.slice(0,o),search:s,hash:i}}function N(e,t){if(!e)return`/`;if(t&&(e===t||e.startsWith(`${t}/`))){let n=e.slice(t.length);return n.startsWith(`/`)?n:`/${n}`}return e.startsWith(`/`)?e:`/${e}`}function P(e,t){return e?t?e===`/`?t:e.startsWith(`/`)?`${t}${e}`:`${t}/${e}`:e.startsWith(`/`)?e:`/${e}`:t}function F(e,t){let n=M(e);return N(n.pathname,t)+n.search}function I(e,t){return e.addInterceptor(`start`,(e,n)=>e(n??t.getLocation()))}function L(e,t){return(n,r,i)=>{let a=P(e.buildPath(n,r),t);if(i?.hash===void 0)return a;let o=A(i.hash);return o?`${a}#${O(o)}`:a}}function R(e,t,n,r,i=!0){let a={name:``,params:{},path:``};return(o,s={},c)=>{let l=e.buildState(o,s);if(!l)throw Error(`[real-router] Cannot replace state: route "${o}" is not found`);let u=e.makeState(l.name,l.params,t.buildPath(l.name,l.params),{params:l.meta}),d;if(c?.hash!==void 0){let e=A(c.hash);d=e?`#${O(e)}`:``}else d=i?n.getHash():``;let f=r(o,s)+d;a.name=u.name,a.params=u.params,a.path=u.path,n.replaceState(a,f)}}function z(e,t,n){return e.replace===!0?!0:n?!!e.reload&&t.path===n.path:e.replace!==!1}const B={forceDeactivate:!0,base:``},V=`popstate`,H=`browser-plugin`,U=x(B,H,{base:C}),W=Object.freeze({source:`popstate`,direction:`back`}),G=Object.freeze({source:`navigate`,direction:`forward`});function K(t,n){U(t);let r={...B,...t};r.base=s(r.base);let i=n??q(r.base),a={forceDeactivate:r.forceDeactivate,source:V,replace:!0},o={removePopStateListener:void 0};return function(t){return J(t,(0,e.getPluginApi)(t),r,i,a,o)}}function q(e){let t=`\0`,n=``,r=``;return w(()=>{let{pathname:i,search:a}=globalThis.location;return i===t&&a===n?r:(t=i,n=a,r=c(N(i,e))+a,r)},`browser-plugin`)}function J(e,t,n,r,i,a){let o=t.claimContextNamespace(`browser`),s=t.claimContextNamespace(`url`),c=b(),l=I(t,r),u=L(e,n.base),d=t.extendRouter({buildUrl:u,matchUrl:e=>t.matchPath(F(e,n.base))??void 0,replaceHistoryState:R(t,e,r,u)});return{...D({browser:r,shared:a,handler:E({router:e,api:t,browser:r,allowNotFound:t.getOptions().allowNotFound,transitionOptions:i,loggerContext:H,buildUrl:u,getCurrentHash:()=>j(r),getCurrentContextHash:()=>(e.getState()?.context)?.url?.hash??``}),cleanup:()=>{l(),d(),o.release(),s.release()}}),onTransitionSuccess:(e,t,i)=>{let a=z(i,e,t),l=j(r),u=(t?.context)?.url?.hash??``,d=i.hash===void 0?l:A(i.hash);s.write(e,Object.freeze({hash:d,hashChanged:i.hashChange??d!==u}));let f=P(e.path,n.base);c(e,d?`${f}#${O(d)}`:f,a,r);let p=i.source===V;o.write(e,p?W:G)}}}exports.browserPluginFactory=K,exports.isState=v;
2
2
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@real-router/browser-plugin",
3
- "version": "0.17.4",
3
+ "version": "0.17.5",
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,12 +45,12 @@
45
45
  },
46
46
  "sideEffects": false,
47
47
  "dependencies": {
48
- "@real-router/core": "^0.54.1",
48
+ "@real-router/core": "^0.55.0",
49
49
  "@real-router/types": "^0.35.0"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@testing-library/jest-dom": "6.9.1",
53
- "jsdom": "28.1.0",
53
+ "jsdom": "29.1.1",
54
54
  "type-guards": "^0.4.9"
55
55
  },
56
56
  "scripts": {