@real-router/lifecycle-plugin 0.4.7 → 0.5.1

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 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/types.ts","../../src/factory.ts","../../src/index.ts"],"mappings":";;;;;;AAOA;;KAAY,aAAA,IACV,OAAA,EAAS,KAAA,EACT,SAAA,EAAW,KAAK;;;;;;KAQN,oBAAA,sBACW,qBAAA,GAAsB,qBAAA,KAE3C,MAAA,EAAQ,MAAA,CAAO,YAAA,GACf,aAAA,mBAAgC,YAAA,EAAc,GAAA,EAAK,CAAA,KAAM,YAAA,CAAa,CAAA,MACnE,aAAA;;;iBC6CW,sBAAA,CAAA,GAA0B,aAAa;;;;AD5DvD;;;;YEGY,KAAA,sBAA2B,mBAAA;IFFrC;IEIE,OAAA,GAAU,oBAAA,CAAqB,YAAA;IFHjC;IEKE,MAAA,GAAS,oBAAA,CAAqB,YAAA;IFLJ;IEO1B,OAAA,GAAU,oBAAA,CAAqB,YAAA;IFCH;;;;;IEK5B,UAAA,GAAa,oBAAA,CAAqB,YAAA;EAAA;AAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/types.ts","../../src/factory.ts","../../src/index.ts"],"mappings":";;;;;;AAOA;;KAAY,aAAA,IACV,OAAA,EAAS,KAAA,EACT,SAAA,EAAW,KAAK;;;;;;KAQN,oBAAA,sBACW,qBAAA,GAAsB,qBAAA,KAE3C,MAAA,EAAQ,MAAA,CAAO,YAAA,GACf,aAAA,mBAAgC,YAAA,EAAc,GAAA,EAAK,CAAA,KAAM,YAAA,CAAa,CAAA,MACnE,aAAA;;;iBCyFW,sBAAA,IAA0B,aAAa;;;;ADxGvD;;;;YEGY,KAAA,sBAA2B,mBAAA;IFFrC;IEIE,OAAA,GAAU,oBAAA,CAAqB,YAAA;IFHjC;IEKE,MAAA,GAAS,oBAAA,CAAqB,YAAA;IFLJ;IEO1B,OAAA,GAAU,oBAAA,CAAqB,YAAA;IFCH;;;;;IEK5B,UAAA,GAAa,oBAAA,CAAqB,YAAA;EAAA;AAAA"}
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");function t(...t){let[n,r]=t,i=(0,e.getPluginApi)(n),a=new Map;function o(e,t){let o=`${e}:${t}`,s=i.getRouteConfig(t),c=typeof s?.[e]==`function`?s[e]:void 0;if(!c){a.delete(o);return}let l=a.get(o);if(l?.factory===c)return l.hook;let u=c(n,r);return a.set(o,{hook:u,factory:c}),u}return{onTransitionLeaveApprove:(e,t)=>{t&&e.name!==t.name&&o(`onLeave`,t.name)?.(e,t)},onTransitionSuccess:(e,t)=>{e.name===t?.name?o(`onStay`,e.name)?.(e,t):o(`onEnter`,e.name)?.(e,t),o(`onNavigate`,e.name)?.(e,t)}}}function n(){return t}exports.lifecyclePluginFactory=n;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@real-router/core/api");const t=[`onEnter`,`onStay`,`onLeave`,`onNavigate`];function n(...n){let[r,i]=n,a=(0,e.getPluginApi)(r),o=new Map,s=e=>{for(let n of t)o.delete(`${n}:${e}`)},c=(0,e.getRoutesApi)(r).subscribeChanges(e=>{switch(e.op){case`remove`:for(let t of e.removedSubtree)s(t.name);break;case`replace`:for(let t of e.removed)s(t.name);break;case`clear`:o.clear();break}});function l(e,t){let n=`${e}:${t}`,s=a.getRouteConfig(t),c=typeof s?.[e]==`function`?s[e]:void 0;if(!c){o.delete(n);return}let l=o.get(n);if(l?.factory===c)return l.hook;let u=c(r,i);return o.set(n,{hook:u,factory:c}),u}return{onTransitionLeaveApprove:(e,t)=>{t&&e.name!==t.name&&l(`onLeave`,t.name)?.(e,t)},onTransitionSuccess:(e,t)=>{e.name===t?.name?l(`onStay`,e.name)?.(e,t):l(`onEnter`,e.name)?.(e,t),l(`onNavigate`,e.name)?.(e,t)},teardown:()=>{c()}}}function r(){return n}exports.lifecyclePluginFactory=r;
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/factory.ts"],"sourcesContent":["import { getPluginApi } from \"@real-router/core/api\";\n\nimport type { LifecycleHook, LifecycleHookFactory } from \"./types\";\nimport type { PluginFactory, State } from \"@real-router/core\";\n\nfunction createPlugin(\n ...args: Parameters<PluginFactory>\n): ReturnType<PluginFactory> {\n const [router, getDependency] = args;\n const api = getPluginApi(router);\n const compiledHooks = new Map<\n string,\n { hook: LifecycleHook; factory: LifecycleHookFactory }\n >();\n\n function compileHook(\n hookName: \"onEnter\" | \"onStay\" | \"onLeave\" | \"onNavigate\",\n routeName: string,\n ): LifecycleHook | undefined {\n const key = `${hookName}:${routeName}`;\n const config = api.getRouteConfig(routeName);\n const factory =\n typeof config?.[hookName] === \"function\"\n ? (config[hookName] as LifecycleHookFactory)\n : undefined;\n\n if (!factory) {\n compiledHooks.delete(key);\n\n return undefined;\n }\n\n const cached = compiledHooks.get(key);\n\n if (cached?.factory === factory) {\n return cached.hook;\n }\n\n const hook = factory(router, getDependency);\n\n compiledHooks.set(key, { hook, factory });\n\n return hook;\n }\n\n return {\n onTransitionLeaveApprove: (\n toState: State,\n fromState: State | undefined,\n ) => {\n if (fromState && toState.name !== fromState.name) {\n compileHook(\"onLeave\", fromState.name)?.(toState, fromState);\n }\n },\n\n onTransitionSuccess: (toState: State, fromState: State | undefined) => {\n if (toState.name === fromState?.name) {\n compileHook(\"onStay\", toState.name)?.(toState, fromState);\n } else {\n compileHook(\"onEnter\", toState.name)?.(toState, fromState);\n }\n\n compileHook(\"onNavigate\", toState.name)?.(toState, fromState);\n },\n };\n}\n\nexport function lifecyclePluginFactory(): PluginFactory {\n return createPlugin;\n}\n"],"mappings":"0GAKA,SAAS,EACP,GAAG,EACwB,CAC3B,GAAM,CAAC,EAAQ,GAAiB,EAC1B,GAAA,EAAA,EAAA,cAAmB,CAAM,EACzB,EAAgB,IAAI,IAK1B,SAAS,EACP,EACA,EAC2B,CAC3B,IAAM,EAAM,GAAG,EAAS,GAAG,IACrB,EAAS,EAAI,eAAe,CAAS,EACrC,EACJ,OAAO,IAAS,IAAc,WACzB,EAAO,GACR,IAAA,GAEN,GAAI,CAAC,EAAS,CACZ,EAAc,OAAO,CAAG,EAExB,MACF,CAEA,IAAM,EAAS,EAAc,IAAI,CAAG,EAEpC,GAAI,GAAQ,UAAY,EACtB,OAAO,EAAO,KAGhB,IAAM,EAAO,EAAQ,EAAQ,CAAa,EAI1C,OAFA,EAAc,IAAI,EAAK,CAAE,OAAM,SAAQ,CAAC,EAEjC,CACT,CAEA,MAAO,CACL,0BACE,EACA,IACG,CACC,GAAa,EAAQ,OAAS,EAAU,MAC1C,EAAY,UAAW,EAAU,IAAI,IAAI,EAAS,CAAS,CAE/D,EAEA,qBAAsB,EAAgB,IAAiC,CACjE,EAAQ,OAAS,GAAW,KAC9B,EAAY,SAAU,EAAQ,IAAI,IAAI,EAAS,CAAS,EAExD,EAAY,UAAW,EAAQ,IAAI,IAAI,EAAS,CAAS,EAG3D,EAAY,aAAc,EAAQ,IAAI,IAAI,EAAS,CAAS,CAC9D,CACF,CACF,CAEA,SAAgB,GAAwC,CACtD,OAAO,CACT"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/factory.ts"],"sourcesContent":["import { getPluginApi, getRoutesApi } from \"@real-router/core/api\";\n\nimport type { LifecycleHook, LifecycleHookFactory } from \"./types\";\nimport type { PluginFactory, State, TreeChangedEvent } from \"@real-router/core\";\n\nconst HOOK_NAMES = [\"onEnter\", \"onStay\", \"onLeave\", \"onNavigate\"] as const;\n\nfunction createPlugin(\n ...args: Parameters<PluginFactory>\n): ReturnType<PluginFactory> {\n const [router, getDependency] = args;\n const api = getPluginApi(router);\n const compiledHooks = new Map<\n string,\n { hook: LifecycleHook; factory: LifecycleHookFactory }\n >();\n\n // Drop compiled hooks for routes removed from the tree. `compileHook` can\n // never reach them again (no navigation to a removed route), so the entries\n // would be dead memory until teardown. `add`/`update` need no handling —\n // `compileHook` already revalidates lazily via the cached `factory` reference.\n const forgetRoute = (routeName: string): void => {\n for (const hookName of HOOK_NAMES) {\n compiledHooks.delete(`${hookName}:${routeName}`);\n }\n };\n\n const onTreeChanged = (event: TreeChangedEvent): void => {\n switch (event.op) {\n case \"remove\": {\n for (const route of event.removedSubtree) {\n forgetRoute(route.name);\n }\n\n break;\n }\n case \"replace\": {\n for (const route of event.removed) {\n forgetRoute(route.name);\n }\n\n break;\n }\n case \"clear\": {\n compiledHooks.clear();\n\n break;\n }\n // \"add\" / \"update\": lazy factory-reference revalidation handles these.\n }\n };\n\n const removeChangesSubscription =\n getRoutesApi(router).subscribeChanges(onTreeChanged);\n\n function compileHook(\n hookName: \"onEnter\" | \"onStay\" | \"onLeave\" | \"onNavigate\",\n routeName: string,\n ): LifecycleHook | undefined {\n const key = `${hookName}:${routeName}`;\n const config = api.getRouteConfig(routeName);\n const factory =\n typeof config?.[hookName] === \"function\"\n ? (config[hookName] as LifecycleHookFactory)\n : undefined;\n\n if (!factory) {\n compiledHooks.delete(key);\n\n return undefined;\n }\n\n const cached = compiledHooks.get(key);\n\n if (cached?.factory === factory) {\n return cached.hook;\n }\n\n const hook = factory(router, getDependency);\n\n compiledHooks.set(key, { hook, factory });\n\n return hook;\n }\n\n return {\n onTransitionLeaveApprove: (\n toState: State,\n fromState: State | undefined,\n ) => {\n if (fromState && toState.name !== fromState.name) {\n compileHook(\"onLeave\", fromState.name)?.(toState, fromState);\n }\n },\n\n onTransitionSuccess: (toState: State, fromState: State | undefined) => {\n if (toState.name === fromState?.name) {\n compileHook(\"onStay\", toState.name)?.(toState, fromState);\n } else {\n compileHook(\"onEnter\", toState.name)?.(toState, fromState);\n }\n\n compileHook(\"onNavigate\", toState.name)?.(toState, fromState);\n },\n\n teardown: () => {\n removeChangesSubscription();\n },\n };\n}\n\nexport function lifecyclePluginFactory(): PluginFactory {\n return createPlugin;\n}\n"],"mappings":"0GAKA,MAAM,EAAa,CAAC,UAAW,SAAU,UAAW,YAAY,EAEhE,SAAS,EACP,GAAG,EACwB,CAC3B,GAAM,CAAC,EAAQ,GAAiB,EAC1B,GAAA,EAAA,EAAA,aAAA,CAAmB,CAAM,EACzB,EAAgB,IAAI,IASpB,EAAe,GAA4B,CAC/C,IAAK,IAAM,KAAY,EACrB,EAAc,OAAO,GAAG,EAAS,GAAG,GAAW,CAEnD,EA2BM,GAAA,EAAA,EAAA,aAAA,CACS,CAAM,CAAC,CAAC,iBA1BA,GAAkC,CACvD,OAAQ,EAAM,GAAd,CACE,IAAK,SACH,IAAK,IAAM,KAAS,EAAM,eACxB,EAAY,EAAM,IAAI,EAGxB,MAEF,IAAK,UACH,IAAK,IAAM,KAAS,EAAM,QACxB,EAAY,EAAM,IAAI,EAGxB,MAEF,IAAK,QACH,EAAc,MAAM,EAEpB,KAGJ,CACF,CAGqD,EAErD,SAAS,EACP,EACA,EAC2B,CAC3B,IAAM,EAAM,GAAG,EAAS,GAAG,IACrB,EAAS,EAAI,eAAe,CAAS,EACrC,EACJ,OAAO,IAAS,IAAc,WACzB,EAAO,GACR,IAAA,GAEN,GAAI,CAAC,EAAS,CACZ,EAAc,OAAO,CAAG,EAExB,MACF,CAEA,IAAM,EAAS,EAAc,IAAI,CAAG,EAEpC,GAAI,GAAQ,UAAY,EACtB,OAAO,EAAO,KAGhB,IAAM,EAAO,EAAQ,EAAQ,CAAa,EAI1C,OAFA,EAAc,IAAI,EAAK,CAAE,OAAM,SAAQ,CAAC,EAEjC,CACT,CAEA,MAAO,CACL,0BACE,EACA,IACG,CACC,GAAa,EAAQ,OAAS,EAAU,MAC1C,EAAY,UAAW,EAAU,IAAI,CAAC,GAAG,EAAS,CAAS,CAE/D,EAEA,qBAAsB,EAAgB,IAAiC,CACjE,EAAQ,OAAS,GAAW,KAC9B,EAAY,SAAU,EAAQ,IAAI,CAAC,GAAG,EAAS,CAAS,EAExD,EAAY,UAAW,EAAQ,IAAI,CAAC,GAAG,EAAS,CAAS,EAG3D,EAAY,aAAc,EAAQ,IAAI,CAAC,GAAG,EAAS,CAAS,CAC9D,EAEA,aAAgB,CACd,EAA0B,CAC5B,CACF,CACF,CAEA,SAAgB,GAAwC,CACtD,OAAO,CACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/types.ts","../../src/factory.ts","../../src/index.ts"],"mappings":";;;;;;AAOA;;KAAY,aAAA,IACV,OAAA,EAAS,KAAA,EACT,SAAA,EAAW,KAAK;;;;;;KAQN,oBAAA,sBACW,qBAAA,GAAsB,qBAAA,KAE3C,MAAA,EAAQ,MAAA,CAAO,YAAA,GACf,aAAA,mBAAgC,YAAA,EAAc,GAAA,EAAK,CAAA,KAAM,YAAA,CAAa,CAAA,MACnE,aAAA;;;iBC6CW,sBAAA,CAAA,GAA0B,aAAa;;;;AD5DvD;;;;YEGY,KAAA,sBAA2B,mBAAA;IFFrC;IEIE,OAAA,GAAU,oBAAA,CAAqB,YAAA;IFHjC;IEKE,MAAA,GAAS,oBAAA,CAAqB,YAAA;IFLJ;IEO1B,OAAA,GAAU,oBAAA,CAAqB,YAAA;IFCH;;;;;IEK5B,UAAA,GAAa,oBAAA,CAAqB,YAAA;EAAA;AAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/types.ts","../../src/factory.ts","../../src/index.ts"],"mappings":";;;;;;AAOA;;KAAY,aAAA,IACV,OAAA,EAAS,KAAA,EACT,SAAA,EAAW,KAAK;;;;;;KAQN,oBAAA,sBACW,qBAAA,GAAsB,qBAAA,KAE3C,MAAA,EAAQ,MAAA,CAAO,YAAA,GACf,aAAA,mBAAgC,YAAA,EAAc,GAAA,EAAK,CAAA,KAAM,YAAA,CAAa,CAAA,MACnE,aAAA;;;iBCyFW,sBAAA,IAA0B,aAAa;;;;ADxGvD;;;;YEGY,KAAA,sBAA2B,mBAAA;IFFrC;IEIE,OAAA,GAAU,oBAAA,CAAqB,YAAA;IFHjC;IEKE,MAAA,GAAS,oBAAA,CAAqB,YAAA;IFLJ;IEO1B,OAAA,GAAU,oBAAA,CAAqB,YAAA;IFCH;;;;;IEK5B,UAAA,GAAa,oBAAA,CAAqB,YAAA;EAAA;AAAA"}
@@ -1,2 +1,2 @@
1
- import{getPluginApi as e}from"@real-router/core/api";function t(...t){let[n,r]=t,i=e(n),a=new Map;function o(e,t){let o=`${e}:${t}`,s=i.getRouteConfig(t),c=typeof s?.[e]==`function`?s[e]:void 0;if(!c){a.delete(o);return}let l=a.get(o);if(l?.factory===c)return l.hook;let u=c(n,r);return a.set(o,{hook:u,factory:c}),u}return{onTransitionLeaveApprove:(e,t)=>{t&&e.name!==t.name&&o(`onLeave`,t.name)?.(e,t)},onTransitionSuccess:(e,t)=>{e.name===t?.name?o(`onStay`,e.name)?.(e,t):o(`onEnter`,e.name)?.(e,t),o(`onNavigate`,e.name)?.(e,t)}}}function n(){return t}export{n as lifecyclePluginFactory};
1
+ import{getPluginApi as e,getRoutesApi as t}from"@real-router/core/api";const n=[`onEnter`,`onStay`,`onLeave`,`onNavigate`];function r(...r){let[i,a]=r,o=e(i),s=new Map,c=e=>{for(let t of n)s.delete(`${t}:${e}`)},l=t(i).subscribeChanges(e=>{switch(e.op){case`remove`:for(let t of e.removedSubtree)c(t.name);break;case`replace`:for(let t of e.removed)c(t.name);break;case`clear`:s.clear();break}});function u(e,t){let n=`${e}:${t}`,r=o.getRouteConfig(t),c=typeof r?.[e]==`function`?r[e]:void 0;if(!c){s.delete(n);return}let l=s.get(n);if(l?.factory===c)return l.hook;let u=c(i,a);return s.set(n,{hook:u,factory:c}),u}return{onTransitionLeaveApprove:(e,t)=>{t&&e.name!==t.name&&u(`onLeave`,t.name)?.(e,t)},onTransitionSuccess:(e,t)=>{e.name===t?.name?u(`onStay`,e.name)?.(e,t):u(`onEnter`,e.name)?.(e,t),u(`onNavigate`,e.name)?.(e,t)},teardown:()=>{l()}}}function i(){return r}export{i as lifecyclePluginFactory};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/factory.ts"],"sourcesContent":["import { getPluginApi } from \"@real-router/core/api\";\n\nimport type { LifecycleHook, LifecycleHookFactory } from \"./types\";\nimport type { PluginFactory, State } from \"@real-router/core\";\n\nfunction createPlugin(\n ...args: Parameters<PluginFactory>\n): ReturnType<PluginFactory> {\n const [router, getDependency] = args;\n const api = getPluginApi(router);\n const compiledHooks = new Map<\n string,\n { hook: LifecycleHook; factory: LifecycleHookFactory }\n >();\n\n function compileHook(\n hookName: \"onEnter\" | \"onStay\" | \"onLeave\" | \"onNavigate\",\n routeName: string,\n ): LifecycleHook | undefined {\n const key = `${hookName}:${routeName}`;\n const config = api.getRouteConfig(routeName);\n const factory =\n typeof config?.[hookName] === \"function\"\n ? (config[hookName] as LifecycleHookFactory)\n : undefined;\n\n if (!factory) {\n compiledHooks.delete(key);\n\n return undefined;\n }\n\n const cached = compiledHooks.get(key);\n\n if (cached?.factory === factory) {\n return cached.hook;\n }\n\n const hook = factory(router, getDependency);\n\n compiledHooks.set(key, { hook, factory });\n\n return hook;\n }\n\n return {\n onTransitionLeaveApprove: (\n toState: State,\n fromState: State | undefined,\n ) => {\n if (fromState && toState.name !== fromState.name) {\n compileHook(\"onLeave\", fromState.name)?.(toState, fromState);\n }\n },\n\n onTransitionSuccess: (toState: State, fromState: State | undefined) => {\n if (toState.name === fromState?.name) {\n compileHook(\"onStay\", toState.name)?.(toState, fromState);\n } else {\n compileHook(\"onEnter\", toState.name)?.(toState, fromState);\n }\n\n compileHook(\"onNavigate\", toState.name)?.(toState, fromState);\n },\n };\n}\n\nexport function lifecyclePluginFactory(): PluginFactory {\n return createPlugin;\n}\n"],"mappings":"qDAKA,SAAS,EACP,GAAG,EACwB,CAC3B,GAAM,CAAC,EAAQ,GAAiB,EAC1B,EAAM,EAAa,CAAM,EACzB,EAAgB,IAAI,IAK1B,SAAS,EACP,EACA,EAC2B,CAC3B,IAAM,EAAM,GAAG,EAAS,GAAG,IACrB,EAAS,EAAI,eAAe,CAAS,EACrC,EACJ,OAAO,IAAS,IAAc,WACzB,EAAO,GACR,IAAA,GAEN,GAAI,CAAC,EAAS,CACZ,EAAc,OAAO,CAAG,EAExB,MACF,CAEA,IAAM,EAAS,EAAc,IAAI,CAAG,EAEpC,GAAI,GAAQ,UAAY,EACtB,OAAO,EAAO,KAGhB,IAAM,EAAO,EAAQ,EAAQ,CAAa,EAI1C,OAFA,EAAc,IAAI,EAAK,CAAE,OAAM,SAAQ,CAAC,EAEjC,CACT,CAEA,MAAO,CACL,0BACE,EACA,IACG,CACC,GAAa,EAAQ,OAAS,EAAU,MAC1C,EAAY,UAAW,EAAU,IAAI,IAAI,EAAS,CAAS,CAE/D,EAEA,qBAAsB,EAAgB,IAAiC,CACjE,EAAQ,OAAS,GAAW,KAC9B,EAAY,SAAU,EAAQ,IAAI,IAAI,EAAS,CAAS,EAExD,EAAY,UAAW,EAAQ,IAAI,IAAI,EAAS,CAAS,EAG3D,EAAY,aAAc,EAAQ,IAAI,IAAI,EAAS,CAAS,CAC9D,CACF,CACF,CAEA,SAAgB,GAAwC,CACtD,OAAO,CACT"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/factory.ts"],"sourcesContent":["import { getPluginApi, getRoutesApi } from \"@real-router/core/api\";\n\nimport type { LifecycleHook, LifecycleHookFactory } from \"./types\";\nimport type { PluginFactory, State, TreeChangedEvent } from \"@real-router/core\";\n\nconst HOOK_NAMES = [\"onEnter\", \"onStay\", \"onLeave\", \"onNavigate\"] as const;\n\nfunction createPlugin(\n ...args: Parameters<PluginFactory>\n): ReturnType<PluginFactory> {\n const [router, getDependency] = args;\n const api = getPluginApi(router);\n const compiledHooks = new Map<\n string,\n { hook: LifecycleHook; factory: LifecycleHookFactory }\n >();\n\n // Drop compiled hooks for routes removed from the tree. `compileHook` can\n // never reach them again (no navigation to a removed route), so the entries\n // would be dead memory until teardown. `add`/`update` need no handling —\n // `compileHook` already revalidates lazily via the cached `factory` reference.\n const forgetRoute = (routeName: string): void => {\n for (const hookName of HOOK_NAMES) {\n compiledHooks.delete(`${hookName}:${routeName}`);\n }\n };\n\n const onTreeChanged = (event: TreeChangedEvent): void => {\n switch (event.op) {\n case \"remove\": {\n for (const route of event.removedSubtree) {\n forgetRoute(route.name);\n }\n\n break;\n }\n case \"replace\": {\n for (const route of event.removed) {\n forgetRoute(route.name);\n }\n\n break;\n }\n case \"clear\": {\n compiledHooks.clear();\n\n break;\n }\n // \"add\" / \"update\": lazy factory-reference revalidation handles these.\n }\n };\n\n const removeChangesSubscription =\n getRoutesApi(router).subscribeChanges(onTreeChanged);\n\n function compileHook(\n hookName: \"onEnter\" | \"onStay\" | \"onLeave\" | \"onNavigate\",\n routeName: string,\n ): LifecycleHook | undefined {\n const key = `${hookName}:${routeName}`;\n const config = api.getRouteConfig(routeName);\n const factory =\n typeof config?.[hookName] === \"function\"\n ? (config[hookName] as LifecycleHookFactory)\n : undefined;\n\n if (!factory) {\n compiledHooks.delete(key);\n\n return undefined;\n }\n\n const cached = compiledHooks.get(key);\n\n if (cached?.factory === factory) {\n return cached.hook;\n }\n\n const hook = factory(router, getDependency);\n\n compiledHooks.set(key, { hook, factory });\n\n return hook;\n }\n\n return {\n onTransitionLeaveApprove: (\n toState: State,\n fromState: State | undefined,\n ) => {\n if (fromState && toState.name !== fromState.name) {\n compileHook(\"onLeave\", fromState.name)?.(toState, fromState);\n }\n },\n\n onTransitionSuccess: (toState: State, fromState: State | undefined) => {\n if (toState.name === fromState?.name) {\n compileHook(\"onStay\", toState.name)?.(toState, fromState);\n } else {\n compileHook(\"onEnter\", toState.name)?.(toState, fromState);\n }\n\n compileHook(\"onNavigate\", toState.name)?.(toState, fromState);\n },\n\n teardown: () => {\n removeChangesSubscription();\n },\n };\n}\n\nexport function lifecyclePluginFactory(): PluginFactory {\n return createPlugin;\n}\n"],"mappings":"uEAKA,MAAM,EAAa,CAAC,UAAW,SAAU,UAAW,YAAY,EAEhE,SAAS,EACP,GAAG,EACwB,CAC3B,GAAM,CAAC,EAAQ,GAAiB,EAC1B,EAAM,EAAa,CAAM,EACzB,EAAgB,IAAI,IASpB,EAAe,GAA4B,CAC/C,IAAK,IAAM,KAAY,EACrB,EAAc,OAAO,GAAG,EAAS,GAAG,GAAW,CAEnD,EA2BM,EACJ,EAAa,CAAM,CAAC,CAAC,iBA1BA,GAAkC,CACvD,OAAQ,EAAM,GAAd,CACE,IAAK,SACH,IAAK,IAAM,KAAS,EAAM,eACxB,EAAY,EAAM,IAAI,EAGxB,MAEF,IAAK,UACH,IAAK,IAAM,KAAS,EAAM,QACxB,EAAY,EAAM,IAAI,EAGxB,MAEF,IAAK,QACH,EAAc,MAAM,EAEpB,KAGJ,CACF,CAGqD,EAErD,SAAS,EACP,EACA,EAC2B,CAC3B,IAAM,EAAM,GAAG,EAAS,GAAG,IACrB,EAAS,EAAI,eAAe,CAAS,EACrC,EACJ,OAAO,IAAS,IAAc,WACzB,EAAO,GACR,IAAA,GAEN,GAAI,CAAC,EAAS,CACZ,EAAc,OAAO,CAAG,EAExB,MACF,CAEA,IAAM,EAAS,EAAc,IAAI,CAAG,EAEpC,GAAI,GAAQ,UAAY,EACtB,OAAO,EAAO,KAGhB,IAAM,EAAO,EAAQ,EAAQ,CAAa,EAI1C,OAFA,EAAc,IAAI,EAAK,CAAE,OAAM,SAAQ,CAAC,EAEjC,CACT,CAEA,MAAO,CACL,0BACE,EACA,IACG,CACC,GAAa,EAAQ,OAAS,EAAU,MAC1C,EAAY,UAAW,EAAU,IAAI,CAAC,GAAG,EAAS,CAAS,CAE/D,EAEA,qBAAsB,EAAgB,IAAiC,CACjE,EAAQ,OAAS,GAAW,KAC9B,EAAY,SAAU,EAAQ,IAAI,CAAC,GAAG,EAAS,CAAS,EAExD,EAAY,UAAW,EAAQ,IAAI,CAAC,GAAG,EAAS,CAAS,EAG3D,EAAY,aAAc,EAAQ,IAAI,CAAC,GAAG,EAAS,CAAS,CAC9D,EAEA,aAAgB,CACd,EAA0B,CAC5B,CACF,CACF,CAEA,SAAgB,GAAwC,CACtD,OAAO,CACT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@real-router/lifecycle-plugin",
3
- "version": "0.4.7",
3
+ "version": "0.5.1",
4
4
  "type": "commonjs",
5
5
  "description": "Route-level lifecycle hooks: onEnter, onStay, onLeave",
6
6
  "main": "./dist/cjs/index.js",
@@ -18,8 +18,7 @@
18
18
  }
19
19
  },
20
20
  "files": [
21
- "dist",
22
- "src"
21
+ "dist"
23
22
  ],
24
23
  "repository": {
25
24
  "type": "git",
@@ -45,8 +44,8 @@
45
44
  "homepage": "https://github.com/greydragon888/real-router",
46
45
  "sideEffects": false,
47
46
  "dependencies": {
48
- "@real-router/core": "^0.55.0",
49
- "@real-router/types": "^0.35.0"
47
+ "@real-router/core": "^0.57.0",
48
+ "@real-router/types": "^0.36.0"
50
49
  },
51
50
  "scripts": {
52
51
  "test": "vitest run",
package/src/factory.ts DELETED
@@ -1,70 +0,0 @@
1
- import { getPluginApi } from "@real-router/core/api";
2
-
3
- import type { LifecycleHook, LifecycleHookFactory } from "./types";
4
- import type { PluginFactory, State } from "@real-router/core";
5
-
6
- function createPlugin(
7
- ...args: Parameters<PluginFactory>
8
- ): ReturnType<PluginFactory> {
9
- const [router, getDependency] = args;
10
- const api = getPluginApi(router);
11
- const compiledHooks = new Map<
12
- string,
13
- { hook: LifecycleHook; factory: LifecycleHookFactory }
14
- >();
15
-
16
- function compileHook(
17
- hookName: "onEnter" | "onStay" | "onLeave" | "onNavigate",
18
- routeName: string,
19
- ): LifecycleHook | undefined {
20
- const key = `${hookName}:${routeName}`;
21
- const config = api.getRouteConfig(routeName);
22
- const factory =
23
- typeof config?.[hookName] === "function"
24
- ? (config[hookName] as LifecycleHookFactory)
25
- : undefined;
26
-
27
- if (!factory) {
28
- compiledHooks.delete(key);
29
-
30
- return undefined;
31
- }
32
-
33
- const cached = compiledHooks.get(key);
34
-
35
- if (cached?.factory === factory) {
36
- return cached.hook;
37
- }
38
-
39
- const hook = factory(router, getDependency);
40
-
41
- compiledHooks.set(key, { hook, factory });
42
-
43
- return hook;
44
- }
45
-
46
- return {
47
- onTransitionLeaveApprove: (
48
- toState: State,
49
- fromState: State | undefined,
50
- ) => {
51
- if (fromState && toState.name !== fromState.name) {
52
- compileHook("onLeave", fromState.name)?.(toState, fromState);
53
- }
54
- },
55
-
56
- onTransitionSuccess: (toState: State, fromState: State | undefined) => {
57
- if (toState.name === fromState?.name) {
58
- compileHook("onStay", toState.name)?.(toState, fromState);
59
- } else {
60
- compileHook("onEnter", toState.name)?.(toState, fromState);
61
- }
62
-
63
- compileHook("onNavigate", toState.name)?.(toState, fromState);
64
- },
65
- };
66
- }
67
-
68
- export function lifecyclePluginFactory(): PluginFactory {
69
- return createPlugin;
70
- }
package/src/index.ts DELETED
@@ -1,27 +0,0 @@
1
- import type { LifecycleHookFactory } from "./types";
2
- import type { DefaultDependencies } from "@real-router/core";
3
-
4
- export { lifecyclePluginFactory } from "./factory";
5
-
6
- /**
7
- * Module augmentation for real-router.
8
- * Extends Route interface with lifecycle hook factories.
9
- */
10
- declare module "@real-router/core" {
11
- interface Route<Dependencies extends DefaultDependencies> {
12
- /** Factory that returns a hook called when this route segment is newly activated (entered). */
13
- onEnter?: LifecycleHookFactory<Dependencies>;
14
- /** Factory that returns a hook called when this route segment stays active but params changed. */
15
- onStay?: LifecycleHookFactory<Dependencies>;
16
- /** Factory that returns a hook called when this route segment is deactivated (left). */
17
- onLeave?: LifecycleHookFactory<Dependencies>;
18
- /**
19
- * Factory that returns a hook called on every successful navigation to this route
20
- * (both entry and param-change). Acts as a fallback when `onEnter` or `onStay`
21
- * is not defined for the corresponding case.
22
- */
23
- onNavigate?: LifecycleHookFactory<Dependencies>;
24
- }
25
- }
26
-
27
- export type { LifecycleHook, LifecycleHookFactory } from "./types";
package/src/types.ts DELETED
@@ -1,23 +0,0 @@
1
- import type { State } from "@real-router/core";
2
- import type { DefaultDependencies, Router } from "@real-router/types";
3
-
4
- /**
5
- * Lifecycle hook callback for route transitions.
6
- * Fire-and-forget: return values are ignored, errors propagate to EventEmitter (logged to stderr).
7
- */
8
- export type LifecycleHook = (
9
- toState: State,
10
- fromState: State | undefined,
11
- ) => void;
12
-
13
- /**
14
- * Factory function for creating lifecycle hooks.
15
- * Receives the router instance and a dependency getter (same pattern as GuardFnFactory).
16
- * Factory runs once at first invocation; the returned hook is cached per route.
17
- */
18
- export type LifecycleHookFactory<
19
- Dependencies extends DefaultDependencies = DefaultDependencies,
20
- > = (
21
- router: Router<Dependencies>,
22
- getDependency: <K extends keyof Dependencies>(key: K) => Dependencies[K],
23
- ) => LifecycleHook;