@real-router/logger-plugin 0.3.6 → 0.3.7

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,5 +1,6 @@
1
- import { PluginFactory } from '@real-router/core';
1
+ import { PluginFactory } from "@real-router/core";
2
2
 
3
+ //#region src/types.d.ts
3
4
  /**
4
5
  * Logging level for router events.
5
6
  * Controls which events are logged to the console.
@@ -9,59 +10,61 @@ type LogLevel = "all" | "transitions" | "errors" | "none";
9
10
  * Configuration options for the logger-plugin.
10
11
  */
11
12
  interface LoggerPluginConfig {
12
- /**
13
- * Use Performance API to create marks and measures.
14
- * Enables integration with browser DevTools Performance tab.
15
- *
16
- * Creates marks:
17
- * - `router:transition-start:{from}→{to}`
18
- * - `router:transition-end:{from}→{to}` (success)
19
- * - `router:transition-cancel:{from}→{to}` (cancelled)
20
- * - `router:transition-error:{from}→{to}` (error)
21
- *
22
- * Creates measures:
23
- * - `router:transition:{from}→{to}` (success)
24
- * - `router:transition-cancelled:{from}→{to}` (cancelled)
25
- * - `router:transition-failed:{from}→{to}` (error)
26
- *
27
- * @default false
28
- */
29
- usePerformanceMarks?: boolean;
30
- /**
31
- * Logging level - controls what router events to log.
32
- *
33
- * - 'all': Log all router events (default)
34
- * - 'transitions': Log only transition-related events
35
- * - 'errors': Log only transition errors
36
- * - 'none': Disable all logging
37
- *
38
- * @default 'all'
39
- */
40
- level?: LogLevel;
41
- /**
42
- * Show execution time in milliseconds for transitions.
43
- * Helps identify slow route changes.
44
- *
45
- * @default true
46
- */
47
- showTiming?: boolean;
48
- /**
49
- * Show diff of changed route parameters between transitions.
50
- * Only applies when navigating within the same route.
51
- * Helps identify which parameters changed during navigation.
52
- *
53
- * @default true
54
- */
55
- showParamsDiff?: boolean;
56
- /**
57
- * Custom context name for console.
58
- * Useful when running multiple routers.
59
- *
60
- * @default 'logger-plugin'
61
- */
62
- context?: string;
13
+ /**
14
+ * Use Performance API to create marks and measures.
15
+ * Enables integration with browser DevTools Performance tab.
16
+ *
17
+ * Creates marks:
18
+ * - `router:transition-start:{from}→{to}`
19
+ * - `router:transition-end:{from}→{to}` (success)
20
+ * - `router:transition-cancel:{from}→{to}` (cancelled)
21
+ * - `router:transition-error:{from}→{to}` (error)
22
+ *
23
+ * Creates measures:
24
+ * - `router:transition:{from}→{to}` (success)
25
+ * - `router:transition-cancelled:{from}→{to}` (cancelled)
26
+ * - `router:transition-failed:{from}→{to}` (error)
27
+ *
28
+ * @default false
29
+ */
30
+ usePerformanceMarks?: boolean;
31
+ /**
32
+ * Logging level - controls what router events to log.
33
+ *
34
+ * - 'all': Log all router events (default)
35
+ * - 'transitions': Log only transition-related events
36
+ * - 'errors': Log only transition errors
37
+ * - 'none': Disable all logging
38
+ *
39
+ * @default 'all'
40
+ */
41
+ level?: LogLevel;
42
+ /**
43
+ * Show execution time in milliseconds for transitions.
44
+ * Helps identify slow route changes.
45
+ *
46
+ * @default true
47
+ */
48
+ showTiming?: boolean;
49
+ /**
50
+ * Show diff of changed route parameters between transitions.
51
+ * Only applies when navigating within the same route.
52
+ * Helps identify which parameters changed during navigation.
53
+ *
54
+ * @default true
55
+ */
56
+ showParamsDiff?: boolean;
57
+ /**
58
+ * Custom context name for console.
59
+ * Useful when running multiple routers.
60
+ *
61
+ * @default 'logger-plugin'
62
+ */
63
+ context?: string;
63
64
  }
64
-
65
+ //#endregion
66
+ //#region src/factory.d.ts
65
67
  declare function loggerPluginFactory(options?: Partial<LoggerPluginConfig>): PluginFactory;
66
-
68
+ //#endregion
67
69
  export { type LogLevel, type LoggerPluginConfig, loggerPluginFactory };
70
+ //# sourceMappingURL=index.d.ts.map
package/dist/cjs/index.js CHANGED
@@ -1 +1,2 @@
1
- "use strict";var t="logger-plugin",e=`[@real-router/${t}]`,r={level:"all",usePerformanceMarks:!1,showParamsDiff:!0,showTiming:!0,context:t},o=t=>t?.name??"(none)",n=(t,e)=>{if(null===t)return"";const r=e()-t;return!Number.isFinite(r)||r<0?" (?)":r<.1?` (${(1e3*r).toFixed(2)}μs)`:` (${r.toFixed(2)}ms)`},i=0,s=0,a="undefined"!=typeof performance&&"function"==typeof performance.now?()=>performance.now():()=>{const t=Date.now();return t<i&&(s+=i-t),i=t,t+s},l=()=>a(),f=class{#t;#e;#r;#o;#n;#i;#s;#a;#l;#f;#h=null;#c="";#u="";constructor(t){this.#t="all"===t.level,this.#e="none"!==t.level&&"errors"!==t.level,this.#r="none"!==t.level,this.#o=this.#e&&t.showParamsDiff,this.#n=t.showTiming,this.#i=t.usePerformanceMarks,this.#s=`[${t.context}]`,this.#a=t.context,this.#l=(t=>{let e=!1;return{open(r){t&&!e&&(console.group(r),e=!0)},close(){t&&e&&(console.groupEnd(),e=!1)},isOpen:()=>e}})("undefined"!=typeof console&&"function"==typeof console.group&&"function"==typeof console.groupEnd),this.#f=((t,e)=>{const r=t&&"undefined"!=typeof performance&&"function"==typeof performance.mark&&"function"==typeof performance.measure;return{mark(t){r&&performance.mark(t)},measure(t,o,n){if(r)try{performance.measure(t,o,n)}catch(r){console.warn(`[${e}] Failed to create performance measure: ${t}`,r)}}}})(t.usePerformanceMarks,t.context)}getPlugin(){return{onStart:()=>{this.#f.mark("router:start"),this.#t&&console.log(`${this.#s} Router started`)},onStop:()=>{this.#l.close(),this.#f.mark("router:stop"),this.#f.measure("router:lifetime","router:start","router:stop"),this.#t&&console.log(`${this.#s} Router stopped`)},onTransitionStart:(t,e)=>{this.#l.open("Router transition"),this.#h=this.#n?l():null;const r=o(e),n=o(t);this.#i&&(this.#c=((t,e)=>`${t}→${e}`)(r,n),this.#u=`router:transition-start:${this.#c}`,this.#f.mark(this.#u)),this.#e&&(console.log(`${this.#s} Transition: ${r} → ${n}`,{from:e,to:t}),this.#m(t,e))},onTransitionSuccess:(t,e)=>{if(this.#i){const t=this.#c,e=`router:transition-end:${t}`;this.#f.mark(e),this.#f.measure(`router:transition:${t}`,this.#u,e)}if(this.#e){const r=this.#n?n(this.#h,l):"";console.log(`${this.#s} Transition success${r}`,{to:t,from:e})}this.#p()},onTransitionCancel:(t,e)=>{if(this.#i){const t=this.#c,e=`router:transition-cancel:${t}`;this.#f.mark(e),this.#f.measure(`router:transition-cancelled:${t}`,this.#u,e)}if(this.#e){const r=this.#n?n(this.#h,l):"";console.warn(`${this.#s} Transition cancelled${r}`,{to:t,from:e})}this.#p()},onTransitionError:(t,e,r)=>{if(this.#i){const t=this.#c,e=`router:transition-error:${t}`;this.#f.mark(e),this.#f.measure(`router:transition-failed:${t}`,this.#u,e)}if(this.#r){const o=this.#n?n(this.#h,l):"";console.error(`${this.#s} Transition error: ${r.code}${o}`,{error:r,stack:r.stack,to:t,from:e})}this.#p()},teardown:()=>{this.#p()}}}#m(t,e){if(!this.#o||!e)return;if(t.name!==e.name)return;const r=((t,e)=>{const r={},o={},n={};let i=!1;for(const o in t)o in e?t[o]!==e[o]&&(r[o]={from:t[o],to:e[o]},i=!0):(n[o]=t[o],i=!0);for(const r in e)r in t||(o[r]=e[r],i=!0);return i?{changed:r,added:o,removed:n}:null})(e.params,t.params);r&&((t,e)=>{const r=[],o=Object.entries(t.changed);if(o.length>0){const t=[];for(const[e,{from:r,to:n}]of o)t.push(`${e}: ${JSON.stringify(r)} → ${JSON.stringify(n)}`);r.push(`Changed: { ${t.join(", ")} }`)}Object.keys(t.added).length>0&&r.push(`Added: ${JSON.stringify(t.added)}`),Object.keys(t.removed).length>0&&r.push(`Removed: ${JSON.stringify(t.removed)}`),console.log(`[${e}] ${r.join(", ")}`)})(r,this.#a)}#p(){this.#l.close(),this.#c="",this.#u="",this.#h=null}},h=new Set(["all","transitions","errors","none"]);exports.loggerPluginFactory=function(t){!function(t){if(void 0!==t){if(null===t||"object"!=typeof t)throw new TypeError(`${e} Options must be an object`);if(void 0!==t.level&&!h.has(t.level))throw new TypeError(`${e} Invalid level: "${t.level}". Expected: ${[...h].join(", ")}`);if(void 0!==t.context&&("string"!=typeof t.context||0===t.context.length))throw new TypeError(`${e} Option "context" must be a non-empty string`);if(void 0!==t.showTiming&&"boolean"!=typeof t.showTiming)throw new TypeError(`${e} Option "showTiming" must be a boolean`);if(void 0!==t.showParamsDiff&&"boolean"!=typeof t.showParamsDiff)throw new TypeError(`${e} Option "showParamsDiff" must be a boolean`);if(void 0!==t.usePerformanceMarks&&"boolean"!=typeof t.usePerformanceMarks)throw new TypeError(`${e} Option "usePerformanceMarks" must be a boolean`)}}(t);const o={...r,...t};return()=>new f(o).getPlugin()};//# sourceMappingURL=index.js.map
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=`logger-plugin`,t=`[@real-router/${e}]`,n={level:`all`,usePerformanceMarks:!1,showParamsDiff:!0,showTiming:!0,context:e},r=()=>typeof console<`u`&&typeof console.group==`function`&&typeof console.groupEnd==`function`,i=e=>{let t=!1;return{open(n){!e||t||(console.group(n),t=!0)},close(){!e||!t||(console.groupEnd(),t=!1)},isOpen(){return t}}},a=e=>e?.name??`(none)`,o=(e,t)=>{if(e===null)return``;let n=t()-e;return!Number.isFinite(n)||n<0?` (?)`:n<.1?` (${(n*1e3).toFixed(2)}μs)`:` (${n.toFixed(2)}ms)`},s=(e,t)=>`${e}→${t}`,c=(e,t)=>{let n={},r={},i={},a=!1;for(let r in e)r in t?e[r]!==t[r]&&(n[r]={from:e[r],to:t[r]},a=!0):(i[r]=e[r],a=!0);for(let n in t)n in e||(r[n]=t[n],a=!0);return a?{changed:n,added:r,removed:i}:null},l=(e,t)=>{let n=[],r=Object.entries(e.changed);if(r.length>0){let e=[];for(let[t,{from:n,to:i}]of r)e.push(`${t}: ${JSON.stringify(n)} → ${JSON.stringify(i)}`);n.push(`Changed: { ${e.join(`, `)} }`)}Object.keys(e.added).length>0&&n.push(`Added: ${JSON.stringify(e.added)}`),Object.keys(e.removed).length>0&&n.push(`Removed: ${JSON.stringify(e.removed)}`),console.log(`[${t}] ${n.join(`, `)}`)},u=()=>typeof performance<`u`&&typeof performance.mark==`function`&&typeof performance.measure==`function`,d=(e,t)=>{let n=e&&u();return{mark(e){n&&performance.mark(e)},measure(e,r,i){if(n)try{performance.measure(e,r,i)}catch(n){console.warn(`[${t}] Failed to create performance measure: ${e}`,n)}}}};let f=0,p=0;function m(){return()=>{let e=Date.now();return e<f&&(p+=f-e),f=e,e+p}}const h=typeof performance<`u`&&typeof performance.now==`function`?()=>performance.now():m(),g=()=>h();var _=class{#e;#t;#n;#r;#i;#a;#o;#s;#c;#l;#u=null;#d=``;#f=``;constructor(e){this.#e=e.level===`all`,this.#t=e.level!==`none`&&e.level!==`errors`,this.#n=e.level!==`none`,this.#r=this.#t&&e.showParamsDiff,this.#i=e.showTiming,this.#a=e.usePerformanceMarks,this.#o=`[${e.context}]`,this.#s=e.context,this.#c=i(r()),this.#l=d(e.usePerformanceMarks,e.context)}getPlugin(){return{onStart:()=>{this.#l.mark(`router:start`),this.#e&&console.log(`${this.#o} Router started`)},onStop:()=>{this.#c.close(),this.#l.mark(`router:stop`),this.#l.measure(`router:lifetime`,`router:start`,`router:stop`),this.#e&&console.log(`${this.#o} Router stopped`)},onTransitionStart:(e,t)=>{this.#c.open(`Router transition`),this.#u=this.#i?g():null;let n=a(t),r=a(e);this.#a&&(this.#d=s(n,r),this.#f=`router:transition-start:${this.#d}`,this.#l.mark(this.#f)),this.#t&&(console.log(`${this.#o} Transition: ${n} → ${r}`,{from:t,to:e}),this.#p(e,t))},onTransitionSuccess:(e,t)=>{if(this.#a){let e=this.#d,t=`router:transition-end:${e}`;this.#l.mark(t),this.#l.measure(`router:transition:${e}`,this.#f,t)}if(this.#t){let n=this.#i?o(this.#u,g):``;console.log(`${this.#o} Transition success${n}`,{to:e,from:t})}this.#m()},onTransitionCancel:(e,t)=>{if(this.#a){let e=this.#d,t=`router:transition-cancel:${e}`;this.#l.mark(t),this.#l.measure(`router:transition-cancelled:${e}`,this.#f,t)}if(this.#t){let n=this.#i?o(this.#u,g):``;console.warn(`${this.#o} Transition cancelled${n}`,{to:e,from:t})}this.#m()},onTransitionError:(e,t,n)=>{if(this.#a){let e=this.#d,t=`router:transition-error:${e}`;this.#l.mark(t),this.#l.measure(`router:transition-failed:${e}`,this.#f,t)}if(this.#n){let r=this.#i?o(this.#u,g):``;console.error(`${this.#o} Transition error: ${n.code}${r}`,{error:n,stack:n.stack,to:e,from:t})}this.#m()},teardown:()=>{this.#m()}}}#p(e,t){if(!this.#r||!t||e.name!==t.name)return;let n=c(t.params,e.params);n&&l(n,this.#s)}#m(){this.#c.close(),this.#d=``,this.#f=``,this.#u=null}};const v=new Set([`all`,`transitions`,`errors`,`none`]);function y(e){if(e!==void 0){if(typeof e!=`object`||!e)throw TypeError(`${t} Options must be an object`);if(e.level!==void 0&&!v.has(e.level))throw TypeError(`${t} Invalid level: "${e.level}". Expected: ${[...v].join(`, `)}`);if(e.context!==void 0&&(typeof e.context!=`string`||e.context.length===0))throw TypeError(`${t} Option "context" must be a non-empty string`);if(e.showTiming!==void 0&&typeof e.showTiming!=`boolean`)throw TypeError(`${t} Option "showTiming" must be a boolean`);if(e.showParamsDiff!==void 0&&typeof e.showParamsDiff!=`boolean`)throw TypeError(`${t} Option "showParamsDiff" must be a boolean`);if(e.usePerformanceMarks!==void 0&&typeof e.usePerformanceMarks!=`boolean`)throw TypeError(`${t} Option "usePerformanceMarks" must be a boolean`)}}function b(e){y(e);let t={...n,...e};return()=>new _(t).getPlugin()}exports.loggerPluginFactory=b;
2
+ //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/constants.ts","../../src/internal/console-groups.ts","../../src/internal/formatting.ts","../../src/internal/params-diff.ts","../../src/internal/performance-marks.ts","../../src/internal/timing.ts","../../src/plugin.ts","../../src/validation.ts","../../src/factory.ts"],"names":["now"],"mappings":"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","file":"index.js","sourcesContent":["// packages/logger-plugin/src/constants.ts\n\nimport type { LoggerPluginConfig } from \"./types\";\n\nexport const LOGGER_CONTEXT = \"logger-plugin\";\n\nexport const ERROR_PREFIX = `[@real-router/${LOGGER_CONTEXT}]`;\n\nexport const DEFAULT_CONFIG: Required<LoggerPluginConfig> = {\n level: \"all\",\n usePerformanceMarks: false,\n showParamsDiff: true,\n showTiming: true,\n context: LOGGER_CONTEXT,\n};\n","// packages/logger-plugin/src/internal/console-groups.ts\n\n/**\n * Checks if console.group is supported in the current environment.\n */\nexport const supportsConsoleGroups = (): boolean => {\n return (\n typeof console !== \"undefined\" &&\n typeof console.group === \"function\" &&\n typeof console.groupEnd === \"function\"\n );\n};\n\n/**\n * Manager for handling console groups\n */\nexport interface GroupManager {\n /**\n * Opens a group if it's not already open\n */\n open: (label: string) => void;\n /**\n * Closes a group if it's open\n */\n close: () => void;\n /**\n * Checks if a group is currently open\n */\n isOpen: () => boolean;\n}\n\n/**\n * Creates a manager for handling console groups.\n * Prevents duplicate group opening.\n *\n * @param enabled - Whether groups are supported in the environment\n * @returns Object with open and close methods\n */\nexport const createGroupManager = (enabled: boolean): GroupManager => {\n let isOpened = false;\n\n return {\n /**\n * Opens a group if it's not already open.\n */\n open(label: string): void {\n if (!enabled || isOpened) {\n return;\n }\n\n console.group(label);\n isOpened = true;\n },\n\n /**\n * Closes a group if it's open.\n */\n close(): void {\n if (!enabled || !isOpened) {\n return;\n }\n\n console.groupEnd();\n isOpened = false;\n },\n\n /**\n * Checks if a group is currently open.\n */\n isOpen(): boolean {\n return isOpened;\n },\n };\n};\n","// packages/logger-plugin/src/internal/formatting.ts\n\nimport type { State } from \"@real-router/core\";\n\n/**\n * Formats route name for logging output.\n * Handles undefined/null.\n */\nexport const formatRouteName = (state?: State): string => {\n return state?.name ?? \"(none)\";\n};\n\n/**\n * Formats execution time information.\n * Uses adaptive units:\n * - Microseconds (μs) for <0.1ms\n * - Milliseconds (ms) for ≥0.1ms\n *\n * @param startTime - Start time or null\n * @param now - Function to get current time\n * @returns String with time or empty string\n */\nexport const formatTiming = (\n startTime: number | null,\n now: () => number,\n): string => {\n if (startTime === null) {\n return \"\";\n }\n\n const durationMs = now() - startTime;\n\n if (!Number.isFinite(durationMs) || durationMs < 0) {\n return \" (?)\";\n }\n\n if (durationMs < 0.1) {\n const durationMks = (durationMs * 1000).toFixed(2);\n\n return ` (${durationMks}μs)`;\n } else {\n const duration = durationMs.toFixed(2);\n\n return ` (${duration}ms)`;\n }\n};\n\n/**\n * Creates a label for Performance API from route names.\n */\nexport const createTransitionLabel = (\n fromRoute: string,\n toRoute: string,\n): string => {\n return `${fromRoute}→${toRoute}`;\n};\n","// packages/logger-plugin/src/internal/params-diff.ts\n\nimport type { Params } from \"@real-router/core\";\n\nexport interface ParamsDiff {\n changed: Record<string, { from: unknown; to: unknown }>;\n added: Record<string, unknown>;\n removed: Record<string, unknown>;\n}\n\n/**\n * Calculates differences between two parameter objects.\n * Performs only shallow comparison.\n *\n * @param fromParams - Previous parameters\n * @param toParams - New parameters\n * @returns Object with differences or null if there are no changes\n */\nexport const getParamsDiff = (\n fromParams: Params,\n toParams: Params,\n): ParamsDiff | null => {\n const changed: ParamsDiff[\"changed\"] = {};\n const added: ParamsDiff[\"added\"] = {};\n const removed: ParamsDiff[\"removed\"] = {};\n\n // Track if any changes found to avoid iterating through objects at the end.\n // This is a performance optimization: instead of calling Object.keys().length\n // three times to check if objects are empty, we set this flag when we find\n // any change and check it once at the end.\n let hasChanges = false;\n\n // Find changed and removed\n for (const key in fromParams) {\n if (!(key in toParams)) {\n removed[key] = fromParams[key];\n hasChanges = true;\n } else if (fromParams[key] !== toParams[key]) {\n changed[key] = { from: fromParams[key], to: toParams[key] };\n hasChanges = true;\n }\n }\n\n // Find added\n for (const key in toParams) {\n if (!(key in fromParams)) {\n added[key] = toParams[key];\n hasChanges = true;\n }\n }\n\n // Return null if there are no changes\n if (!hasChanges) {\n return null;\n }\n\n return { changed, added, removed };\n};\n\n/**\n * Formats and logs parameter differences.\n *\n * @param diff - Object with differences\n * @param context - Context for console\n */\nexport const logParamsDiff = (diff: ParamsDiff, context: string): void => {\n const parts: string[] = [];\n\n // Cache entries to avoid double iteration\n const changedEntries = Object.entries(diff.changed);\n\n if (changedEntries.length > 0) {\n const items: string[] = [];\n\n for (const [key, { from, to }] of changedEntries) {\n items.push(`${key}: ${JSON.stringify(from)} → ${JSON.stringify(to)}`);\n }\n\n parts.push(`Changed: { ${items.join(\", \")} }`);\n }\n\n if (Object.keys(diff.added).length > 0) {\n parts.push(`Added: ${JSON.stringify(diff.added)}`);\n }\n\n if (Object.keys(diff.removed).length > 0) {\n parts.push(`Removed: ${JSON.stringify(diff.removed)}`);\n }\n\n console.log(`[${context}] ${parts.join(\", \")}`);\n};\n","// packages/logger-plugin/src/internal/performance-marks.ts\n\n/**\n * Checks if Performance API is supported in the current environment.\n */\nexport const supportsPerformanceAPI = (): boolean => {\n return (\n typeof performance !== \"undefined\" &&\n typeof performance.mark === \"function\" &&\n typeof performance.measure === \"function\"\n );\n};\n\n/**\n * Performance tracker interface with mark and measure methods.\n */\nexport interface PerformanceTracker {\n mark: (name: string) => void;\n measure: (measureName: string, startMark: string, endMark: string) => void;\n}\n\n/**\n * Creates a tracker for working with the Performance API.\n * Ignores calls if the API is unavailable.\n *\n * @param enabled - Whether the functionality is enabled (from config)\n * @param context - Context for error logging\n * @returns Object with mark and measure methods\n */\nexport const createPerformanceTracker = (\n enabled: boolean,\n context: string,\n): PerformanceTracker => {\n const isSupported = enabled && supportsPerformanceAPI();\n\n return {\n /**\n * Creates a performance mark with the specified name.\n */\n mark(name: string): void {\n if (!isSupported) {\n return;\n }\n\n performance.mark(name);\n },\n\n /**\n * Creates a performance measure between two marks.\n * Logs a warning if the marks don't exist.\n */\n measure(measureName: string, startMark: string, endMark: string): void {\n if (!isSupported) {\n return;\n }\n\n try {\n performance.measure(measureName, startMark, endMark);\n } catch (error) {\n console.warn(\n `[${context}] Failed to create performance measure: ${measureName}`,\n error,\n );\n }\n },\n };\n};\n","// packages/logger-plugin/src/internal/timing.ts\n\n/**\n * Function that returns high-resolution timestamp in milliseconds.\n */\ntype TimeProvider = () => number;\n\n/**\n * State for Date.now() monotonic emulation\n */\nlet lastTimestamp = 0;\nlet timeOffset = 0;\n\n/**\n * Creates monotonic Date.now() wrapper that ensures time never goes backwards.\n *\n * @returns Time provider function with monotonic guarantee\n */\nfunction createMonotonicDateNow(): TimeProvider {\n // eslint-disable-next-line unicorn/consistent-function-scoping -- closure over module-level lastTimestamp/timeOffset\n return (): number => {\n const current: number = Date.now();\n\n if (current < lastTimestamp) {\n timeOffset += lastTimestamp - current;\n }\n\n lastTimestamp = current;\n\n return current + timeOffset;\n };\n}\n\n/**\n * Initialize time provider based on environment.\n * Uses performance.now() in modern environments (Node.js 16+, all browsers),\n * falls back to monotonic Date.now() wrapper for edge cases.\n */\nconst nowFn: TimeProvider =\n typeof performance !== \"undefined\" && typeof performance.now === \"function\"\n ? (): number => performance.now()\n : createMonotonicDateNow();\n\n/**\n * Returns high-resolution monotonic timestamp.\n *\n * Uses performance.now() in modern environments (Node.js 16+, all browsers).\n * Falls back to monotonic Date.now() wrapper (~1ms precision) for edge cases.\n *\n * @returns Timestamp in milliseconds\n */\nexport const now = (): number => nowFn();\n","// packages/logger-plugin/src/plugin.ts\n\nimport {\n createGroupManager,\n supportsConsoleGroups,\n} from \"./internal/console-groups\";\nimport {\n formatRouteName,\n formatTiming,\n createTransitionLabel,\n} from \"./internal/formatting\";\nimport { getParamsDiff, logParamsDiff } from \"./internal/params-diff\";\nimport { createPerformanceTracker } from \"./internal/performance-marks\";\nimport { now } from \"./internal/timing\";\n\nimport type { GroupManager } from \"./internal/console-groups\";\nimport type { PerformanceTracker } from \"./internal/performance-marks\";\nimport type { LoggerPluginConfig } from \"./types\";\nimport type { Plugin, RouterError, State } from \"@real-router/core\";\n\nexport class LoggerPlugin {\n readonly #logLifecycle: boolean;\n readonly #logTransition: boolean;\n readonly #logError: boolean;\n\n readonly #shouldLogParams: boolean;\n readonly #shouldShowTiming: boolean;\n readonly #usePerf: boolean;\n\n readonly #prefix: string;\n readonly #context: string;\n\n readonly #groups: GroupManager;\n readonly #perf: PerformanceTracker;\n\n // Transition state\n #transitionStartTime: number | null = null;\n #transitionLabel = \"\";\n #startMarkName = \"\";\n\n constructor(config: Required<LoggerPluginConfig>) {\n this.#logLifecycle = config.level === \"all\";\n this.#logTransition = config.level !== \"none\" && config.level !== \"errors\";\n this.#logError = config.level !== \"none\";\n\n this.#shouldLogParams = this.#logTransition && config.showParamsDiff;\n this.#shouldShowTiming = config.showTiming;\n this.#usePerf = config.usePerformanceMarks;\n\n this.#prefix = `[${config.context}]`;\n this.#context = config.context;\n\n this.#groups = createGroupManager(supportsConsoleGroups());\n this.#perf = createPerformanceTracker(\n config.usePerformanceMarks,\n config.context,\n );\n }\n\n getPlugin(): Plugin {\n return {\n onStart: () => {\n this.#perf.mark(\"router:start\");\n\n if (this.#logLifecycle) {\n console.log(`${this.#prefix} Router started`);\n }\n },\n\n onStop: () => {\n this.#groups.close();\n\n this.#perf.mark(\"router:stop\");\n this.#perf.measure(\"router:lifetime\", \"router:start\", \"router:stop\");\n\n if (this.#logLifecycle) {\n console.log(`${this.#prefix} Router stopped`);\n }\n },\n\n onTransitionStart: (toState: State, fromState?: State) => {\n this.#groups.open(\"Router transition\");\n this.#transitionStartTime = this.#shouldShowTiming ? now() : null;\n\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n\n if (this.#usePerf) {\n this.#transitionLabel = createTransitionLabel(fromRoute, toRoute);\n this.#startMarkName = `router:transition-start:${this.#transitionLabel}`;\n this.#perf.mark(this.#startMarkName);\n }\n\n if (this.#logTransition) {\n console.log(`${this.#prefix} Transition: ${fromRoute} → ${toRoute}`, {\n from: fromState,\n to: toState,\n });\n\n this.#logParamsIfNeeded(toState, fromState);\n }\n },\n\n onTransitionSuccess: (toState: State, fromState?: State) => {\n if (this.#usePerf) {\n const label = this.#transitionLabel;\n const endMark = `router:transition-end:${label}`;\n\n this.#perf.mark(endMark);\n this.#perf.measure(\n `router:transition:${label}`,\n this.#startMarkName,\n endMark,\n );\n }\n\n if (this.#logTransition) {\n const timing = this.#shouldShowTiming\n ? formatTiming(this.#transitionStartTime, now)\n : \"\";\n\n console.log(`${this.#prefix} Transition success${timing}`, {\n to: toState,\n from: fromState,\n });\n }\n\n this.#resetTransitionState();\n },\n\n onTransitionCancel: (toState: State, fromState?: State) => {\n if (this.#usePerf) {\n const label = this.#transitionLabel;\n const cancelMark = `router:transition-cancel:${label}`;\n\n this.#perf.mark(cancelMark);\n this.#perf.measure(\n `router:transition-cancelled:${label}`,\n this.#startMarkName,\n cancelMark,\n );\n }\n\n if (this.#logTransition) {\n const timing = this.#shouldShowTiming\n ? formatTiming(this.#transitionStartTime, now)\n : \"\";\n\n console.warn(`${this.#prefix} Transition cancelled${timing}`, {\n to: toState,\n from: fromState,\n });\n }\n\n this.#resetTransitionState();\n },\n\n onTransitionError: (\n toState: State | undefined,\n fromState: State | undefined,\n err: RouterError,\n ) => {\n if (this.#usePerf) {\n const label = this.#transitionLabel;\n const errorMark = `router:transition-error:${label}`;\n\n this.#perf.mark(errorMark);\n this.#perf.measure(\n `router:transition-failed:${label}`,\n this.#startMarkName,\n errorMark,\n );\n }\n\n if (this.#logError) {\n const timing = this.#shouldShowTiming\n ? formatTiming(this.#transitionStartTime, now)\n : \"\";\n\n console.error(\n `${this.#prefix} Transition error: ${err.code}${timing}`,\n {\n error: err,\n stack: err.stack,\n to: toState,\n from: fromState,\n },\n );\n }\n\n this.#resetTransitionState();\n },\n\n teardown: () => {\n this.#resetTransitionState();\n },\n };\n }\n\n #logParamsIfNeeded(toState: State, fromState?: State): void {\n if (!this.#shouldLogParams || !fromState) {\n return;\n }\n\n if (toState.name !== fromState.name) {\n return;\n }\n\n const diff = getParamsDiff(fromState.params, toState.params);\n\n if (diff) {\n logParamsDiff(diff, this.#context);\n }\n }\n\n #resetTransitionState(): void {\n this.#groups.close();\n this.#transitionLabel = \"\";\n this.#startMarkName = \"\";\n this.#transitionStartTime = null;\n }\n}\n","// packages/logger-plugin/src/validation.ts\n\nimport { ERROR_PREFIX } from \"./constants\";\n\nimport type { LoggerPluginConfig } from \"./types\";\n\nconst VALID_LEVELS = new Set([\"all\", \"transitions\", \"errors\", \"none\"]);\n\nexport function validateOptions(options?: Partial<LoggerPluginConfig>): void {\n if (options === undefined) {\n return;\n }\n\n // Runtime defense: typeof null === \"object\", so check identity first.\n // TypeScript excludes null from the parameter type, but JS callers may pass it.\n if (options === (null as never) || typeof options !== \"object\") {\n throw new TypeError(`${ERROR_PREFIX} Options must be an object`);\n }\n\n if (options.level !== undefined && !VALID_LEVELS.has(options.level)) {\n throw new TypeError(\n `${ERROR_PREFIX} Invalid level: \"${options.level}\". Expected: ${[...VALID_LEVELS].join(\", \")}`,\n );\n }\n\n if (\n options.context !== undefined &&\n (typeof options.context !== \"string\" || options.context.length === 0)\n ) {\n throw new TypeError(\n `${ERROR_PREFIX} Option \"context\" must be a non-empty string`,\n );\n }\n\n if (\n options.showTiming !== undefined &&\n typeof options.showTiming !== \"boolean\"\n ) {\n throw new TypeError(\n `${ERROR_PREFIX} Option \"showTiming\" must be a boolean`,\n );\n }\n\n if (\n options.showParamsDiff !== undefined &&\n typeof options.showParamsDiff !== \"boolean\"\n ) {\n throw new TypeError(\n `${ERROR_PREFIX} Option \"showParamsDiff\" must be a boolean`,\n );\n }\n\n if (\n options.usePerformanceMarks !== undefined &&\n typeof options.usePerformanceMarks !== \"boolean\"\n ) {\n throw new TypeError(\n `${ERROR_PREFIX} Option \"usePerformanceMarks\" must be a boolean`,\n );\n }\n}\n","// packages/logger-plugin/src/factory.ts\n\nimport { DEFAULT_CONFIG } from \"./constants\";\nimport { LoggerPlugin } from \"./plugin\";\nimport { validateOptions } from \"./validation\";\n\nimport type { LoggerPluginConfig } from \"./types\";\nimport type { PluginFactory } from \"@real-router/core\";\n\nexport function loggerPluginFactory(\n options?: Partial<LoggerPluginConfig>,\n): PluginFactory {\n validateOptions(options);\n\n const config: Required<LoggerPluginConfig> = {\n ...DEFAULT_CONFIG,\n ...options,\n };\n\n return () => new LoggerPlugin(config).getPlugin();\n}\n"]}
1
+ {"version":3,"file":"index.js","names":["#logLifecycle","#logTransition","#logError","#shouldLogParams","#shouldShowTiming","#usePerf","#prefix","#context","#groups","#perf","#transitionStartTime","#transitionLabel","#startMarkName","#logParamsIfNeeded","#resetTransitionState"],"sources":["../../src/constants.ts","../../src/internal/console-groups.ts","../../src/internal/formatting.ts","../../src/internal/params-diff.ts","../../src/internal/performance-marks.ts","../../src/internal/timing.ts","../../src/plugin.ts","../../src/validation.ts","../../src/factory.ts"],"sourcesContent":["// packages/logger-plugin/src/constants.ts\n\nimport type { LoggerPluginConfig } from \"./types\";\n\nexport const LOGGER_CONTEXT = \"logger-plugin\";\n\nexport const ERROR_PREFIX = `[@real-router/${LOGGER_CONTEXT}]`;\n\nexport const DEFAULT_CONFIG: Required<LoggerPluginConfig> = {\n level: \"all\",\n usePerformanceMarks: false,\n showParamsDiff: true,\n showTiming: true,\n context: LOGGER_CONTEXT,\n};\n","// packages/logger-plugin/src/internal/console-groups.ts\n\n/**\n * Checks if console.group is supported in the current environment.\n */\nexport const supportsConsoleGroups = (): boolean => {\n return (\n typeof console !== \"undefined\" &&\n typeof console.group === \"function\" &&\n typeof console.groupEnd === \"function\"\n );\n};\n\n/**\n * Manager for handling console groups\n */\nexport interface GroupManager {\n /**\n * Opens a group if it's not already open\n */\n open: (label: string) => void;\n /**\n * Closes a group if it's open\n */\n close: () => void;\n /**\n * Checks if a group is currently open\n */\n isOpen: () => boolean;\n}\n\n/**\n * Creates a manager for handling console groups.\n * Prevents duplicate group opening.\n *\n * @param enabled - Whether groups are supported in the environment\n * @returns Object with open and close methods\n */\nexport const createGroupManager = (enabled: boolean): GroupManager => {\n let isOpened = false;\n\n return {\n /**\n * Opens a group if it's not already open.\n */\n open(label: string): void {\n if (!enabled || isOpened) {\n return;\n }\n\n console.group(label);\n isOpened = true;\n },\n\n /**\n * Closes a group if it's open.\n */\n close(): void {\n if (!enabled || !isOpened) {\n return;\n }\n\n console.groupEnd();\n isOpened = false;\n },\n\n /**\n * Checks if a group is currently open.\n */\n isOpen(): boolean {\n return isOpened;\n },\n };\n};\n","// packages/logger-plugin/src/internal/formatting.ts\n\nimport type { State } from \"@real-router/core\";\n\n/**\n * Formats route name for logging output.\n * Handles undefined/null.\n */\nexport const formatRouteName = (state?: State): string => {\n return state?.name ?? \"(none)\";\n};\n\n/**\n * Formats execution time information.\n * Uses adaptive units:\n * - Microseconds (μs) for <0.1ms\n * - Milliseconds (ms) for ≥0.1ms\n *\n * @param startTime - Start time or null\n * @param now - Function to get current time\n * @returns String with time or empty string\n */\nexport const formatTiming = (\n startTime: number | null,\n now: () => number,\n): string => {\n if (startTime === null) {\n return \"\";\n }\n\n const durationMs = now() - startTime;\n\n if (!Number.isFinite(durationMs) || durationMs < 0) {\n return \" (?)\";\n }\n\n if (durationMs < 0.1) {\n const durationMks = (durationMs * 1000).toFixed(2);\n\n return ` (${durationMks}μs)`;\n } else {\n const duration = durationMs.toFixed(2);\n\n return ` (${duration}ms)`;\n }\n};\n\n/**\n * Creates a label for Performance API from route names.\n */\nexport const createTransitionLabel = (\n fromRoute: string,\n toRoute: string,\n): string => {\n return `${fromRoute}→${toRoute}`;\n};\n","// packages/logger-plugin/src/internal/params-diff.ts\n\nimport type { Params } from \"@real-router/core\";\n\nexport interface ParamsDiff {\n changed: Record<string, { from: unknown; to: unknown }>;\n added: Record<string, unknown>;\n removed: Record<string, unknown>;\n}\n\n/**\n * Calculates differences between two parameter objects.\n * Performs only shallow comparison.\n *\n * @param fromParams - Previous parameters\n * @param toParams - New parameters\n * @returns Object with differences or null if there are no changes\n */\nexport const getParamsDiff = (\n fromParams: Params,\n toParams: Params,\n): ParamsDiff | null => {\n const changed: ParamsDiff[\"changed\"] = {};\n const added: ParamsDiff[\"added\"] = {};\n const removed: ParamsDiff[\"removed\"] = {};\n\n // Track if any changes found to avoid iterating through objects at the end.\n // This is a performance optimization: instead of calling Object.keys().length\n // three times to check if objects are empty, we set this flag when we find\n // any change and check it once at the end.\n let hasChanges = false;\n\n // Find changed and removed\n for (const key in fromParams) {\n if (!(key in toParams)) {\n removed[key] = fromParams[key];\n hasChanges = true;\n } else if (fromParams[key] !== toParams[key]) {\n changed[key] = { from: fromParams[key], to: toParams[key] };\n hasChanges = true;\n }\n }\n\n // Find added\n for (const key in toParams) {\n if (!(key in fromParams)) {\n added[key] = toParams[key];\n hasChanges = true;\n }\n }\n\n // Return null if there are no changes\n if (!hasChanges) {\n return null;\n }\n\n return { changed, added, removed };\n};\n\n/**\n * Formats and logs parameter differences.\n *\n * @param diff - Object with differences\n * @param context - Context for console\n */\nexport const logParamsDiff = (diff: ParamsDiff, context: string): void => {\n const parts: string[] = [];\n\n // Cache entries to avoid double iteration\n const changedEntries = Object.entries(diff.changed);\n\n if (changedEntries.length > 0) {\n const items: string[] = [];\n\n for (const [key, { from, to }] of changedEntries) {\n items.push(`${key}: ${JSON.stringify(from)} → ${JSON.stringify(to)}`);\n }\n\n parts.push(`Changed: { ${items.join(\", \")} }`);\n }\n\n if (Object.keys(diff.added).length > 0) {\n parts.push(`Added: ${JSON.stringify(diff.added)}`);\n }\n\n if (Object.keys(diff.removed).length > 0) {\n parts.push(`Removed: ${JSON.stringify(diff.removed)}`);\n }\n\n console.log(`[${context}] ${parts.join(\", \")}`);\n};\n","// packages/logger-plugin/src/internal/performance-marks.ts\n\n/**\n * Checks if Performance API is supported in the current environment.\n */\nexport const supportsPerformanceAPI = (): boolean => {\n return (\n typeof performance !== \"undefined\" &&\n typeof performance.mark === \"function\" &&\n typeof performance.measure === \"function\"\n );\n};\n\n/**\n * Performance tracker interface with mark and measure methods.\n */\nexport interface PerformanceTracker {\n mark: (name: string) => void;\n measure: (measureName: string, startMark: string, endMark: string) => void;\n}\n\n/**\n * Creates a tracker for working with the Performance API.\n * Ignores calls if the API is unavailable.\n *\n * @param enabled - Whether the functionality is enabled (from config)\n * @param context - Context for error logging\n * @returns Object with mark and measure methods\n */\nexport const createPerformanceTracker = (\n enabled: boolean,\n context: string,\n): PerformanceTracker => {\n const isSupported = enabled && supportsPerformanceAPI();\n\n return {\n /**\n * Creates a performance mark with the specified name.\n */\n mark(name: string): void {\n if (!isSupported) {\n return;\n }\n\n performance.mark(name);\n },\n\n /**\n * Creates a performance measure between two marks.\n * Logs a warning if the marks don't exist.\n */\n measure(measureName: string, startMark: string, endMark: string): void {\n if (!isSupported) {\n return;\n }\n\n try {\n performance.measure(measureName, startMark, endMark);\n } catch (error) {\n console.warn(\n `[${context}] Failed to create performance measure: ${measureName}`,\n error,\n );\n }\n },\n };\n};\n","// packages/logger-plugin/src/internal/timing.ts\n\n/**\n * Function that returns high-resolution timestamp in milliseconds.\n */\ntype TimeProvider = () => number;\n\n/**\n * State for Date.now() monotonic emulation\n */\nlet lastTimestamp = 0;\nlet timeOffset = 0;\n\n/**\n * Creates monotonic Date.now() wrapper that ensures time never goes backwards.\n *\n * @returns Time provider function with monotonic guarantee\n */\nfunction createMonotonicDateNow(): TimeProvider {\n // eslint-disable-next-line unicorn/consistent-function-scoping -- closure over module-level lastTimestamp/timeOffset\n return (): number => {\n const current: number = Date.now();\n\n if (current < lastTimestamp) {\n timeOffset += lastTimestamp - current;\n }\n\n lastTimestamp = current;\n\n return current + timeOffset;\n };\n}\n\n/**\n * Initialize time provider based on environment.\n * Uses performance.now() in modern environments (Node.js 16+, all browsers),\n * falls back to monotonic Date.now() wrapper for edge cases.\n */\nconst nowFn: TimeProvider =\n typeof performance !== \"undefined\" && typeof performance.now === \"function\"\n ? (): number => performance.now()\n : createMonotonicDateNow();\n\n/**\n * Returns high-resolution monotonic timestamp.\n *\n * Uses performance.now() in modern environments (Node.js 16+, all browsers).\n * Falls back to monotonic Date.now() wrapper (~1ms precision) for edge cases.\n *\n * @returns Timestamp in milliseconds\n */\nexport const now = (): number => nowFn();\n","// packages/logger-plugin/src/plugin.ts\n\nimport {\n createGroupManager,\n supportsConsoleGroups,\n} from \"./internal/console-groups\";\nimport {\n formatRouteName,\n formatTiming,\n createTransitionLabel,\n} from \"./internal/formatting\";\nimport { getParamsDiff, logParamsDiff } from \"./internal/params-diff\";\nimport { createPerformanceTracker } from \"./internal/performance-marks\";\nimport { now } from \"./internal/timing\";\n\nimport type { GroupManager } from \"./internal/console-groups\";\nimport type { PerformanceTracker } from \"./internal/performance-marks\";\nimport type { LoggerPluginConfig } from \"./types\";\nimport type { Plugin, RouterError, State } from \"@real-router/core\";\n\nexport class LoggerPlugin {\n readonly #logLifecycle: boolean;\n readonly #logTransition: boolean;\n readonly #logError: boolean;\n\n readonly #shouldLogParams: boolean;\n readonly #shouldShowTiming: boolean;\n readonly #usePerf: boolean;\n\n readonly #prefix: string;\n readonly #context: string;\n\n readonly #groups: GroupManager;\n readonly #perf: PerformanceTracker;\n\n // Transition state\n #transitionStartTime: number | null = null;\n #transitionLabel = \"\";\n #startMarkName = \"\";\n\n constructor(config: Required<LoggerPluginConfig>) {\n this.#logLifecycle = config.level === \"all\";\n this.#logTransition = config.level !== \"none\" && config.level !== \"errors\";\n this.#logError = config.level !== \"none\";\n\n this.#shouldLogParams = this.#logTransition && config.showParamsDiff;\n this.#shouldShowTiming = config.showTiming;\n this.#usePerf = config.usePerformanceMarks;\n\n this.#prefix = `[${config.context}]`;\n this.#context = config.context;\n\n this.#groups = createGroupManager(supportsConsoleGroups());\n this.#perf = createPerformanceTracker(\n config.usePerformanceMarks,\n config.context,\n );\n }\n\n getPlugin(): Plugin {\n return {\n onStart: () => {\n this.#perf.mark(\"router:start\");\n\n if (this.#logLifecycle) {\n console.log(`${this.#prefix} Router started`);\n }\n },\n\n onStop: () => {\n this.#groups.close();\n\n this.#perf.mark(\"router:stop\");\n this.#perf.measure(\"router:lifetime\", \"router:start\", \"router:stop\");\n\n if (this.#logLifecycle) {\n console.log(`${this.#prefix} Router stopped`);\n }\n },\n\n onTransitionStart: (toState: State, fromState?: State) => {\n this.#groups.open(\"Router transition\");\n this.#transitionStartTime = this.#shouldShowTiming ? now() : null;\n\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n\n if (this.#usePerf) {\n this.#transitionLabel = createTransitionLabel(fromRoute, toRoute);\n this.#startMarkName = `router:transition-start:${this.#transitionLabel}`;\n this.#perf.mark(this.#startMarkName);\n }\n\n if (this.#logTransition) {\n console.log(`${this.#prefix} Transition: ${fromRoute} → ${toRoute}`, {\n from: fromState,\n to: toState,\n });\n\n this.#logParamsIfNeeded(toState, fromState);\n }\n },\n\n onTransitionSuccess: (toState: State, fromState?: State) => {\n if (this.#usePerf) {\n const label = this.#transitionLabel;\n const endMark = `router:transition-end:${label}`;\n\n this.#perf.mark(endMark);\n this.#perf.measure(\n `router:transition:${label}`,\n this.#startMarkName,\n endMark,\n );\n }\n\n if (this.#logTransition) {\n const timing = this.#shouldShowTiming\n ? formatTiming(this.#transitionStartTime, now)\n : \"\";\n\n console.log(`${this.#prefix} Transition success${timing}`, {\n to: toState,\n from: fromState,\n });\n }\n\n this.#resetTransitionState();\n },\n\n onTransitionCancel: (toState: State, fromState?: State) => {\n if (this.#usePerf) {\n const label = this.#transitionLabel;\n const cancelMark = `router:transition-cancel:${label}`;\n\n this.#perf.mark(cancelMark);\n this.#perf.measure(\n `router:transition-cancelled:${label}`,\n this.#startMarkName,\n cancelMark,\n );\n }\n\n if (this.#logTransition) {\n const timing = this.#shouldShowTiming\n ? formatTiming(this.#transitionStartTime, now)\n : \"\";\n\n console.warn(`${this.#prefix} Transition cancelled${timing}`, {\n to: toState,\n from: fromState,\n });\n }\n\n this.#resetTransitionState();\n },\n\n onTransitionError: (\n toState: State | undefined,\n fromState: State | undefined,\n err: RouterError,\n ) => {\n if (this.#usePerf) {\n const label = this.#transitionLabel;\n const errorMark = `router:transition-error:${label}`;\n\n this.#perf.mark(errorMark);\n this.#perf.measure(\n `router:transition-failed:${label}`,\n this.#startMarkName,\n errorMark,\n );\n }\n\n if (this.#logError) {\n const timing = this.#shouldShowTiming\n ? formatTiming(this.#transitionStartTime, now)\n : \"\";\n\n console.error(\n `${this.#prefix} Transition error: ${err.code}${timing}`,\n {\n error: err,\n stack: err.stack,\n to: toState,\n from: fromState,\n },\n );\n }\n\n this.#resetTransitionState();\n },\n\n teardown: () => {\n this.#resetTransitionState();\n },\n };\n }\n\n #logParamsIfNeeded(toState: State, fromState?: State): void {\n if (!this.#shouldLogParams || !fromState) {\n return;\n }\n\n if (toState.name !== fromState.name) {\n return;\n }\n\n const diff = getParamsDiff(fromState.params, toState.params);\n\n if (diff) {\n logParamsDiff(diff, this.#context);\n }\n }\n\n #resetTransitionState(): void {\n this.#groups.close();\n this.#transitionLabel = \"\";\n this.#startMarkName = \"\";\n this.#transitionStartTime = null;\n }\n}\n","// packages/logger-plugin/src/validation.ts\n\nimport { ERROR_PREFIX } from \"./constants\";\n\nimport type { LoggerPluginConfig } from \"./types\";\n\nconst VALID_LEVELS = new Set([\"all\", \"transitions\", \"errors\", \"none\"]);\n\nexport function validateOptions(options?: Partial<LoggerPluginConfig>): void {\n if (options === undefined) {\n return;\n }\n\n // Runtime defense: typeof null === \"object\", so check identity first.\n // TypeScript excludes null from the parameter type, but JS callers may pass it.\n if (options === (null as never) || typeof options !== \"object\") {\n throw new TypeError(`${ERROR_PREFIX} Options must be an object`);\n }\n\n if (options.level !== undefined && !VALID_LEVELS.has(options.level)) {\n throw new TypeError(\n `${ERROR_PREFIX} Invalid level: \"${options.level}\". Expected: ${[...VALID_LEVELS].join(\", \")}`,\n );\n }\n\n if (\n options.context !== undefined &&\n (typeof options.context !== \"string\" || options.context.length === 0)\n ) {\n throw new TypeError(\n `${ERROR_PREFIX} Option \"context\" must be a non-empty string`,\n );\n }\n\n if (\n options.showTiming !== undefined &&\n typeof options.showTiming !== \"boolean\"\n ) {\n throw new TypeError(\n `${ERROR_PREFIX} Option \"showTiming\" must be a boolean`,\n );\n }\n\n if (\n options.showParamsDiff !== undefined &&\n typeof options.showParamsDiff !== \"boolean\"\n ) {\n throw new TypeError(\n `${ERROR_PREFIX} Option \"showParamsDiff\" must be a boolean`,\n );\n }\n\n if (\n options.usePerformanceMarks !== undefined &&\n typeof options.usePerformanceMarks !== \"boolean\"\n ) {\n throw new TypeError(\n `${ERROR_PREFIX} Option \"usePerformanceMarks\" must be a boolean`,\n );\n }\n}\n","// packages/logger-plugin/src/factory.ts\n\nimport { DEFAULT_CONFIG } from \"./constants\";\nimport { LoggerPlugin } from \"./plugin\";\nimport { validateOptions } from \"./validation\";\n\nimport type { LoggerPluginConfig } from \"./types\";\nimport type { PluginFactory } from \"@real-router/core\";\n\nexport function loggerPluginFactory(\n options?: Partial<LoggerPluginConfig>,\n): PluginFactory {\n validateOptions(options);\n\n const config: Required<LoggerPluginConfig> = {\n ...DEFAULT_CONFIG,\n ...options,\n };\n\n return () => new LoggerPlugin(config).getPlugin();\n}\n"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
- import { PluginFactory } from '@real-router/core';
1
+ import { PluginFactory } from "@real-router/core";
2
2
 
3
+ //#region src/types.d.ts
3
4
  /**
4
5
  * Logging level for router events.
5
6
  * Controls which events are logged to the console.
@@ -9,59 +10,61 @@ type LogLevel = "all" | "transitions" | "errors" | "none";
9
10
  * Configuration options for the logger-plugin.
10
11
  */
11
12
  interface LoggerPluginConfig {
12
- /**
13
- * Use Performance API to create marks and measures.
14
- * Enables integration with browser DevTools Performance tab.
15
- *
16
- * Creates marks:
17
- * - `router:transition-start:{from}→{to}`
18
- * - `router:transition-end:{from}→{to}` (success)
19
- * - `router:transition-cancel:{from}→{to}` (cancelled)
20
- * - `router:transition-error:{from}→{to}` (error)
21
- *
22
- * Creates measures:
23
- * - `router:transition:{from}→{to}` (success)
24
- * - `router:transition-cancelled:{from}→{to}` (cancelled)
25
- * - `router:transition-failed:{from}→{to}` (error)
26
- *
27
- * @default false
28
- */
29
- usePerformanceMarks?: boolean;
30
- /**
31
- * Logging level - controls what router events to log.
32
- *
33
- * - 'all': Log all router events (default)
34
- * - 'transitions': Log only transition-related events
35
- * - 'errors': Log only transition errors
36
- * - 'none': Disable all logging
37
- *
38
- * @default 'all'
39
- */
40
- level?: LogLevel;
41
- /**
42
- * Show execution time in milliseconds for transitions.
43
- * Helps identify slow route changes.
44
- *
45
- * @default true
46
- */
47
- showTiming?: boolean;
48
- /**
49
- * Show diff of changed route parameters between transitions.
50
- * Only applies when navigating within the same route.
51
- * Helps identify which parameters changed during navigation.
52
- *
53
- * @default true
54
- */
55
- showParamsDiff?: boolean;
56
- /**
57
- * Custom context name for console.
58
- * Useful when running multiple routers.
59
- *
60
- * @default 'logger-plugin'
61
- */
62
- context?: string;
13
+ /**
14
+ * Use Performance API to create marks and measures.
15
+ * Enables integration with browser DevTools Performance tab.
16
+ *
17
+ * Creates marks:
18
+ * - `router:transition-start:{from}→{to}`
19
+ * - `router:transition-end:{from}→{to}` (success)
20
+ * - `router:transition-cancel:{from}→{to}` (cancelled)
21
+ * - `router:transition-error:{from}→{to}` (error)
22
+ *
23
+ * Creates measures:
24
+ * - `router:transition:{from}→{to}` (success)
25
+ * - `router:transition-cancelled:{from}→{to}` (cancelled)
26
+ * - `router:transition-failed:{from}→{to}` (error)
27
+ *
28
+ * @default false
29
+ */
30
+ usePerformanceMarks?: boolean;
31
+ /**
32
+ * Logging level - controls what router events to log.
33
+ *
34
+ * - 'all': Log all router events (default)
35
+ * - 'transitions': Log only transition-related events
36
+ * - 'errors': Log only transition errors
37
+ * - 'none': Disable all logging
38
+ *
39
+ * @default 'all'
40
+ */
41
+ level?: LogLevel;
42
+ /**
43
+ * Show execution time in milliseconds for transitions.
44
+ * Helps identify slow route changes.
45
+ *
46
+ * @default true
47
+ */
48
+ showTiming?: boolean;
49
+ /**
50
+ * Show diff of changed route parameters between transitions.
51
+ * Only applies when navigating within the same route.
52
+ * Helps identify which parameters changed during navigation.
53
+ *
54
+ * @default true
55
+ */
56
+ showParamsDiff?: boolean;
57
+ /**
58
+ * Custom context name for console.
59
+ * Useful when running multiple routers.
60
+ *
61
+ * @default 'logger-plugin'
62
+ */
63
+ context?: string;
63
64
  }
64
-
65
+ //#endregion
66
+ //#region src/factory.d.ts
65
67
  declare function loggerPluginFactory(options?: Partial<LoggerPluginConfig>): PluginFactory;
66
-
68
+ //#endregion
67
69
  export { type LogLevel, type LoggerPluginConfig, loggerPluginFactory };
70
+ //# sourceMappingURL=index.d.mts.map
@@ -1 +1,2 @@
1
- var t="logger-plugin",e=`[@real-router/${t}]`,o={level:"all",usePerformanceMarks:!1,showParamsDiff:!0,showTiming:!0,context:t},r=t=>t?.name??"(none)",n=(t,e)=>{if(null===t)return"";const o=e()-t;return!Number.isFinite(o)||o<0?" (?)":o<.1?` (${(1e3*o).toFixed(2)}μs)`:` (${o.toFixed(2)}ms)`},i=0,s=0,a="undefined"!=typeof performance&&"function"==typeof performance.now?()=>performance.now():()=>{const t=Date.now();return t<i&&(s+=i-t),i=t,t+s},l=()=>a(),f=class{#t;#e;#o;#r;#n;#i;#s;#a;#l;#f;#h=null;#c="";#u="";constructor(t){this.#t="all"===t.level,this.#e="none"!==t.level&&"errors"!==t.level,this.#o="none"!==t.level,this.#r=this.#e&&t.showParamsDiff,this.#n=t.showTiming,this.#i=t.usePerformanceMarks,this.#s=`[${t.context}]`,this.#a=t.context,this.#l=(t=>{let e=!1;return{open(o){t&&!e&&(console.group(o),e=!0)},close(){t&&e&&(console.groupEnd(),e=!1)},isOpen:()=>e}})("undefined"!=typeof console&&"function"==typeof console.group&&"function"==typeof console.groupEnd),this.#f=((t,e)=>{const o=t&&"undefined"!=typeof performance&&"function"==typeof performance.mark&&"function"==typeof performance.measure;return{mark(t){o&&performance.mark(t)},measure(t,r,n){if(o)try{performance.measure(t,r,n)}catch(o){console.warn(`[${e}] Failed to create performance measure: ${t}`,o)}}}})(t.usePerformanceMarks,t.context)}getPlugin(){return{onStart:()=>{this.#f.mark("router:start"),this.#t&&console.log(`${this.#s} Router started`)},onStop:()=>{this.#l.close(),this.#f.mark("router:stop"),this.#f.measure("router:lifetime","router:start","router:stop"),this.#t&&console.log(`${this.#s} Router stopped`)},onTransitionStart:(t,e)=>{this.#l.open("Router transition"),this.#h=this.#n?l():null;const o=r(e),n=r(t);this.#i&&(this.#c=((t,e)=>`${t}→${e}`)(o,n),this.#u=`router:transition-start:${this.#c}`,this.#f.mark(this.#u)),this.#e&&(console.log(`${this.#s} Transition: ${o} → ${n}`,{from:e,to:t}),this.#m(t,e))},onTransitionSuccess:(t,e)=>{if(this.#i){const t=this.#c,e=`router:transition-end:${t}`;this.#f.mark(e),this.#f.measure(`router:transition:${t}`,this.#u,e)}if(this.#e){const o=this.#n?n(this.#h,l):"";console.log(`${this.#s} Transition success${o}`,{to:t,from:e})}this.#p()},onTransitionCancel:(t,e)=>{if(this.#i){const t=this.#c,e=`router:transition-cancel:${t}`;this.#f.mark(e),this.#f.measure(`router:transition-cancelled:${t}`,this.#u,e)}if(this.#e){const o=this.#n?n(this.#h,l):"";console.warn(`${this.#s} Transition cancelled${o}`,{to:t,from:e})}this.#p()},onTransitionError:(t,e,o)=>{if(this.#i){const t=this.#c,e=`router:transition-error:${t}`;this.#f.mark(e),this.#f.measure(`router:transition-failed:${t}`,this.#u,e)}if(this.#o){const r=this.#n?n(this.#h,l):"";console.error(`${this.#s} Transition error: ${o.code}${r}`,{error:o,stack:o.stack,to:t,from:e})}this.#p()},teardown:()=>{this.#p()}}}#m(t,e){if(!this.#r||!e)return;if(t.name!==e.name)return;const o=((t,e)=>{const o={},r={},n={};let i=!1;for(const r in t)r in e?t[r]!==e[r]&&(o[r]={from:t[r],to:e[r]},i=!0):(n[r]=t[r],i=!0);for(const o in e)o in t||(r[o]=e[o],i=!0);return i?{changed:o,added:r,removed:n}:null})(e.params,t.params);o&&((t,e)=>{const o=[],r=Object.entries(t.changed);if(r.length>0){const t=[];for(const[e,{from:o,to:n}]of r)t.push(`${e}: ${JSON.stringify(o)} → ${JSON.stringify(n)}`);o.push(`Changed: { ${t.join(", ")} }`)}Object.keys(t.added).length>0&&o.push(`Added: ${JSON.stringify(t.added)}`),Object.keys(t.removed).length>0&&o.push(`Removed: ${JSON.stringify(t.removed)}`),console.log(`[${e}] ${o.join(", ")}`)})(o,this.#a)}#p(){this.#l.close(),this.#c="",this.#u="",this.#h=null}},h=new Set(["all","transitions","errors","none"]);function c(t){!function(t){if(void 0!==t){if(null===t||"object"!=typeof t)throw new TypeError(`${e} Options must be an object`);if(void 0!==t.level&&!h.has(t.level))throw new TypeError(`${e} Invalid level: "${t.level}". Expected: ${[...h].join(", ")}`);if(void 0!==t.context&&("string"!=typeof t.context||0===t.context.length))throw new TypeError(`${e} Option "context" must be a non-empty string`);if(void 0!==t.showTiming&&"boolean"!=typeof t.showTiming)throw new TypeError(`${e} Option "showTiming" must be a boolean`);if(void 0!==t.showParamsDiff&&"boolean"!=typeof t.showParamsDiff)throw new TypeError(`${e} Option "showParamsDiff" must be a boolean`);if(void 0!==t.usePerformanceMarks&&"boolean"!=typeof t.usePerformanceMarks)throw new TypeError(`${e} Option "usePerformanceMarks" must be a boolean`)}}(t);const r={...o,...t};return()=>new f(r).getPlugin()}export{c as loggerPluginFactory};//# sourceMappingURL=index.mjs.map
1
+ const e=`logger-plugin`,t=`[@real-router/${e}]`,n={level:`all`,usePerformanceMarks:!1,showParamsDiff:!0,showTiming:!0,context:e},r=()=>typeof console<`u`&&typeof console.group==`function`&&typeof console.groupEnd==`function`,i=e=>{let t=!1;return{open(n){!e||t||(console.group(n),t=!0)},close(){!e||!t||(console.groupEnd(),t=!1)},isOpen(){return t}}},a=e=>e?.name??`(none)`,o=(e,t)=>{if(e===null)return``;let n=t()-e;return!Number.isFinite(n)||n<0?` (?)`:n<.1?` (${(n*1e3).toFixed(2)}μs)`:` (${n.toFixed(2)}ms)`},s=(e,t)=>`${e}→${t}`,c=(e,t)=>{let n={},r={},i={},a=!1;for(let r in e)r in t?e[r]!==t[r]&&(n[r]={from:e[r],to:t[r]},a=!0):(i[r]=e[r],a=!0);for(let n in t)n in e||(r[n]=t[n],a=!0);return a?{changed:n,added:r,removed:i}:null},l=(e,t)=>{let n=[],r=Object.entries(e.changed);if(r.length>0){let e=[];for(let[t,{from:n,to:i}]of r)e.push(`${t}: ${JSON.stringify(n)} → ${JSON.stringify(i)}`);n.push(`Changed: { ${e.join(`, `)} }`)}Object.keys(e.added).length>0&&n.push(`Added: ${JSON.stringify(e.added)}`),Object.keys(e.removed).length>0&&n.push(`Removed: ${JSON.stringify(e.removed)}`),console.log(`[${t}] ${n.join(`, `)}`)},u=()=>typeof performance<`u`&&typeof performance.mark==`function`&&typeof performance.measure==`function`,d=(e,t)=>{let n=e&&u();return{mark(e){n&&performance.mark(e)},measure(e,r,i){if(n)try{performance.measure(e,r,i)}catch(n){console.warn(`[${t}] Failed to create performance measure: ${e}`,n)}}}};let f=0,p=0;function m(){return()=>{let e=Date.now();return e<f&&(p+=f-e),f=e,e+p}}const h=typeof performance<`u`&&typeof performance.now==`function`?()=>performance.now():m(),g=()=>h();var _=class{#e;#t;#n;#r;#i;#a;#o;#s;#c;#l;#u=null;#d=``;#f=``;constructor(e){this.#e=e.level===`all`,this.#t=e.level!==`none`&&e.level!==`errors`,this.#n=e.level!==`none`,this.#r=this.#t&&e.showParamsDiff,this.#i=e.showTiming,this.#a=e.usePerformanceMarks,this.#o=`[${e.context}]`,this.#s=e.context,this.#c=i(r()),this.#l=d(e.usePerformanceMarks,e.context)}getPlugin(){return{onStart:()=>{this.#l.mark(`router:start`),this.#e&&console.log(`${this.#o} Router started`)},onStop:()=>{this.#c.close(),this.#l.mark(`router:stop`),this.#l.measure(`router:lifetime`,`router:start`,`router:stop`),this.#e&&console.log(`${this.#o} Router stopped`)},onTransitionStart:(e,t)=>{this.#c.open(`Router transition`),this.#u=this.#i?g():null;let n=a(t),r=a(e);this.#a&&(this.#d=s(n,r),this.#f=`router:transition-start:${this.#d}`,this.#l.mark(this.#f)),this.#t&&(console.log(`${this.#o} Transition: ${n} → ${r}`,{from:t,to:e}),this.#p(e,t))},onTransitionSuccess:(e,t)=>{if(this.#a){let e=this.#d,t=`router:transition-end:${e}`;this.#l.mark(t),this.#l.measure(`router:transition:${e}`,this.#f,t)}if(this.#t){let n=this.#i?o(this.#u,g):``;console.log(`${this.#o} Transition success${n}`,{to:e,from:t})}this.#m()},onTransitionCancel:(e,t)=>{if(this.#a){let e=this.#d,t=`router:transition-cancel:${e}`;this.#l.mark(t),this.#l.measure(`router:transition-cancelled:${e}`,this.#f,t)}if(this.#t){let n=this.#i?o(this.#u,g):``;console.warn(`${this.#o} Transition cancelled${n}`,{to:e,from:t})}this.#m()},onTransitionError:(e,t,n)=>{if(this.#a){let e=this.#d,t=`router:transition-error:${e}`;this.#l.mark(t),this.#l.measure(`router:transition-failed:${e}`,this.#f,t)}if(this.#n){let r=this.#i?o(this.#u,g):``;console.error(`${this.#o} Transition error: ${n.code}${r}`,{error:n,stack:n.stack,to:e,from:t})}this.#m()},teardown:()=>{this.#m()}}}#p(e,t){if(!this.#r||!t||e.name!==t.name)return;let n=c(t.params,e.params);n&&l(n,this.#s)}#m(){this.#c.close(),this.#d=``,this.#f=``,this.#u=null}};const v=new Set([`all`,`transitions`,`errors`,`none`]);function y(e){if(e!==void 0){if(typeof e!=`object`||!e)throw TypeError(`${t} Options must be an object`);if(e.level!==void 0&&!v.has(e.level))throw TypeError(`${t} Invalid level: "${e.level}". Expected: ${[...v].join(`, `)}`);if(e.context!==void 0&&(typeof e.context!=`string`||e.context.length===0))throw TypeError(`${t} Option "context" must be a non-empty string`);if(e.showTiming!==void 0&&typeof e.showTiming!=`boolean`)throw TypeError(`${t} Option "showTiming" must be a boolean`);if(e.showParamsDiff!==void 0&&typeof e.showParamsDiff!=`boolean`)throw TypeError(`${t} Option "showParamsDiff" must be a boolean`);if(e.usePerformanceMarks!==void 0&&typeof e.usePerformanceMarks!=`boolean`)throw TypeError(`${t} Option "usePerformanceMarks" must be a boolean`)}}function b(e){y(e);let t={...n,...e};return()=>new _(t).getPlugin()}export{b as loggerPluginFactory};
2
+ //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/constants.ts","../../src/internal/console-groups.ts","../../src/internal/formatting.ts","../../src/internal/params-diff.ts","../../src/internal/performance-marks.ts","../../src/internal/timing.ts","../../src/plugin.ts","../../src/validation.ts","../../src/factory.ts"],"names":["now"],"mappings":"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","file":"index.mjs","sourcesContent":["// packages/logger-plugin/src/constants.ts\n\nimport type { LoggerPluginConfig } from \"./types\";\n\nexport const LOGGER_CONTEXT = \"logger-plugin\";\n\nexport const ERROR_PREFIX = `[@real-router/${LOGGER_CONTEXT}]`;\n\nexport const DEFAULT_CONFIG: Required<LoggerPluginConfig> = {\n level: \"all\",\n usePerformanceMarks: false,\n showParamsDiff: true,\n showTiming: true,\n context: LOGGER_CONTEXT,\n};\n","// packages/logger-plugin/src/internal/console-groups.ts\n\n/**\n * Checks if console.group is supported in the current environment.\n */\nexport const supportsConsoleGroups = (): boolean => {\n return (\n typeof console !== \"undefined\" &&\n typeof console.group === \"function\" &&\n typeof console.groupEnd === \"function\"\n );\n};\n\n/**\n * Manager for handling console groups\n */\nexport interface GroupManager {\n /**\n * Opens a group if it's not already open\n */\n open: (label: string) => void;\n /**\n * Closes a group if it's open\n */\n close: () => void;\n /**\n * Checks if a group is currently open\n */\n isOpen: () => boolean;\n}\n\n/**\n * Creates a manager for handling console groups.\n * Prevents duplicate group opening.\n *\n * @param enabled - Whether groups are supported in the environment\n * @returns Object with open and close methods\n */\nexport const createGroupManager = (enabled: boolean): GroupManager => {\n let isOpened = false;\n\n return {\n /**\n * Opens a group if it's not already open.\n */\n open(label: string): void {\n if (!enabled || isOpened) {\n return;\n }\n\n console.group(label);\n isOpened = true;\n },\n\n /**\n * Closes a group if it's open.\n */\n close(): void {\n if (!enabled || !isOpened) {\n return;\n }\n\n console.groupEnd();\n isOpened = false;\n },\n\n /**\n * Checks if a group is currently open.\n */\n isOpen(): boolean {\n return isOpened;\n },\n };\n};\n","// packages/logger-plugin/src/internal/formatting.ts\n\nimport type { State } from \"@real-router/core\";\n\n/**\n * Formats route name for logging output.\n * Handles undefined/null.\n */\nexport const formatRouteName = (state?: State): string => {\n return state?.name ?? \"(none)\";\n};\n\n/**\n * Formats execution time information.\n * Uses adaptive units:\n * - Microseconds (μs) for <0.1ms\n * - Milliseconds (ms) for ≥0.1ms\n *\n * @param startTime - Start time or null\n * @param now - Function to get current time\n * @returns String with time or empty string\n */\nexport const formatTiming = (\n startTime: number | null,\n now: () => number,\n): string => {\n if (startTime === null) {\n return \"\";\n }\n\n const durationMs = now() - startTime;\n\n if (!Number.isFinite(durationMs) || durationMs < 0) {\n return \" (?)\";\n }\n\n if (durationMs < 0.1) {\n const durationMks = (durationMs * 1000).toFixed(2);\n\n return ` (${durationMks}μs)`;\n } else {\n const duration = durationMs.toFixed(2);\n\n return ` (${duration}ms)`;\n }\n};\n\n/**\n * Creates a label for Performance API from route names.\n */\nexport const createTransitionLabel = (\n fromRoute: string,\n toRoute: string,\n): string => {\n return `${fromRoute}→${toRoute}`;\n};\n","// packages/logger-plugin/src/internal/params-diff.ts\n\nimport type { Params } from \"@real-router/core\";\n\nexport interface ParamsDiff {\n changed: Record<string, { from: unknown; to: unknown }>;\n added: Record<string, unknown>;\n removed: Record<string, unknown>;\n}\n\n/**\n * Calculates differences between two parameter objects.\n * Performs only shallow comparison.\n *\n * @param fromParams - Previous parameters\n * @param toParams - New parameters\n * @returns Object with differences or null if there are no changes\n */\nexport const getParamsDiff = (\n fromParams: Params,\n toParams: Params,\n): ParamsDiff | null => {\n const changed: ParamsDiff[\"changed\"] = {};\n const added: ParamsDiff[\"added\"] = {};\n const removed: ParamsDiff[\"removed\"] = {};\n\n // Track if any changes found to avoid iterating through objects at the end.\n // This is a performance optimization: instead of calling Object.keys().length\n // three times to check if objects are empty, we set this flag when we find\n // any change and check it once at the end.\n let hasChanges = false;\n\n // Find changed and removed\n for (const key in fromParams) {\n if (!(key in toParams)) {\n removed[key] = fromParams[key];\n hasChanges = true;\n } else if (fromParams[key] !== toParams[key]) {\n changed[key] = { from: fromParams[key], to: toParams[key] };\n hasChanges = true;\n }\n }\n\n // Find added\n for (const key in toParams) {\n if (!(key in fromParams)) {\n added[key] = toParams[key];\n hasChanges = true;\n }\n }\n\n // Return null if there are no changes\n if (!hasChanges) {\n return null;\n }\n\n return { changed, added, removed };\n};\n\n/**\n * Formats and logs parameter differences.\n *\n * @param diff - Object with differences\n * @param context - Context for console\n */\nexport const logParamsDiff = (diff: ParamsDiff, context: string): void => {\n const parts: string[] = [];\n\n // Cache entries to avoid double iteration\n const changedEntries = Object.entries(diff.changed);\n\n if (changedEntries.length > 0) {\n const items: string[] = [];\n\n for (const [key, { from, to }] of changedEntries) {\n items.push(`${key}: ${JSON.stringify(from)} → ${JSON.stringify(to)}`);\n }\n\n parts.push(`Changed: { ${items.join(\", \")} }`);\n }\n\n if (Object.keys(diff.added).length > 0) {\n parts.push(`Added: ${JSON.stringify(diff.added)}`);\n }\n\n if (Object.keys(diff.removed).length > 0) {\n parts.push(`Removed: ${JSON.stringify(diff.removed)}`);\n }\n\n console.log(`[${context}] ${parts.join(\", \")}`);\n};\n","// packages/logger-plugin/src/internal/performance-marks.ts\n\n/**\n * Checks if Performance API is supported in the current environment.\n */\nexport const supportsPerformanceAPI = (): boolean => {\n return (\n typeof performance !== \"undefined\" &&\n typeof performance.mark === \"function\" &&\n typeof performance.measure === \"function\"\n );\n};\n\n/**\n * Performance tracker interface with mark and measure methods.\n */\nexport interface PerformanceTracker {\n mark: (name: string) => void;\n measure: (measureName: string, startMark: string, endMark: string) => void;\n}\n\n/**\n * Creates a tracker for working with the Performance API.\n * Ignores calls if the API is unavailable.\n *\n * @param enabled - Whether the functionality is enabled (from config)\n * @param context - Context for error logging\n * @returns Object with mark and measure methods\n */\nexport const createPerformanceTracker = (\n enabled: boolean,\n context: string,\n): PerformanceTracker => {\n const isSupported = enabled && supportsPerformanceAPI();\n\n return {\n /**\n * Creates a performance mark with the specified name.\n */\n mark(name: string): void {\n if (!isSupported) {\n return;\n }\n\n performance.mark(name);\n },\n\n /**\n * Creates a performance measure between two marks.\n * Logs a warning if the marks don't exist.\n */\n measure(measureName: string, startMark: string, endMark: string): void {\n if (!isSupported) {\n return;\n }\n\n try {\n performance.measure(measureName, startMark, endMark);\n } catch (error) {\n console.warn(\n `[${context}] Failed to create performance measure: ${measureName}`,\n error,\n );\n }\n },\n };\n};\n","// packages/logger-plugin/src/internal/timing.ts\n\n/**\n * Function that returns high-resolution timestamp in milliseconds.\n */\ntype TimeProvider = () => number;\n\n/**\n * State for Date.now() monotonic emulation\n */\nlet lastTimestamp = 0;\nlet timeOffset = 0;\n\n/**\n * Creates monotonic Date.now() wrapper that ensures time never goes backwards.\n *\n * @returns Time provider function with monotonic guarantee\n */\nfunction createMonotonicDateNow(): TimeProvider {\n // eslint-disable-next-line unicorn/consistent-function-scoping -- closure over module-level lastTimestamp/timeOffset\n return (): number => {\n const current: number = Date.now();\n\n if (current < lastTimestamp) {\n timeOffset += lastTimestamp - current;\n }\n\n lastTimestamp = current;\n\n return current + timeOffset;\n };\n}\n\n/**\n * Initialize time provider based on environment.\n * Uses performance.now() in modern environments (Node.js 16+, all browsers),\n * falls back to monotonic Date.now() wrapper for edge cases.\n */\nconst nowFn: TimeProvider =\n typeof performance !== \"undefined\" && typeof performance.now === \"function\"\n ? (): number => performance.now()\n : createMonotonicDateNow();\n\n/**\n * Returns high-resolution monotonic timestamp.\n *\n * Uses performance.now() in modern environments (Node.js 16+, all browsers).\n * Falls back to monotonic Date.now() wrapper (~1ms precision) for edge cases.\n *\n * @returns Timestamp in milliseconds\n */\nexport const now = (): number => nowFn();\n","// packages/logger-plugin/src/plugin.ts\n\nimport {\n createGroupManager,\n supportsConsoleGroups,\n} from \"./internal/console-groups\";\nimport {\n formatRouteName,\n formatTiming,\n createTransitionLabel,\n} from \"./internal/formatting\";\nimport { getParamsDiff, logParamsDiff } from \"./internal/params-diff\";\nimport { createPerformanceTracker } from \"./internal/performance-marks\";\nimport { now } from \"./internal/timing\";\n\nimport type { GroupManager } from \"./internal/console-groups\";\nimport type { PerformanceTracker } from \"./internal/performance-marks\";\nimport type { LoggerPluginConfig } from \"./types\";\nimport type { Plugin, RouterError, State } from \"@real-router/core\";\n\nexport class LoggerPlugin {\n readonly #logLifecycle: boolean;\n readonly #logTransition: boolean;\n readonly #logError: boolean;\n\n readonly #shouldLogParams: boolean;\n readonly #shouldShowTiming: boolean;\n readonly #usePerf: boolean;\n\n readonly #prefix: string;\n readonly #context: string;\n\n readonly #groups: GroupManager;\n readonly #perf: PerformanceTracker;\n\n // Transition state\n #transitionStartTime: number | null = null;\n #transitionLabel = \"\";\n #startMarkName = \"\";\n\n constructor(config: Required<LoggerPluginConfig>) {\n this.#logLifecycle = config.level === \"all\";\n this.#logTransition = config.level !== \"none\" && config.level !== \"errors\";\n this.#logError = config.level !== \"none\";\n\n this.#shouldLogParams = this.#logTransition && config.showParamsDiff;\n this.#shouldShowTiming = config.showTiming;\n this.#usePerf = config.usePerformanceMarks;\n\n this.#prefix = `[${config.context}]`;\n this.#context = config.context;\n\n this.#groups = createGroupManager(supportsConsoleGroups());\n this.#perf = createPerformanceTracker(\n config.usePerformanceMarks,\n config.context,\n );\n }\n\n getPlugin(): Plugin {\n return {\n onStart: () => {\n this.#perf.mark(\"router:start\");\n\n if (this.#logLifecycle) {\n console.log(`${this.#prefix} Router started`);\n }\n },\n\n onStop: () => {\n this.#groups.close();\n\n this.#perf.mark(\"router:stop\");\n this.#perf.measure(\"router:lifetime\", \"router:start\", \"router:stop\");\n\n if (this.#logLifecycle) {\n console.log(`${this.#prefix} Router stopped`);\n }\n },\n\n onTransitionStart: (toState: State, fromState?: State) => {\n this.#groups.open(\"Router transition\");\n this.#transitionStartTime = this.#shouldShowTiming ? now() : null;\n\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n\n if (this.#usePerf) {\n this.#transitionLabel = createTransitionLabel(fromRoute, toRoute);\n this.#startMarkName = `router:transition-start:${this.#transitionLabel}`;\n this.#perf.mark(this.#startMarkName);\n }\n\n if (this.#logTransition) {\n console.log(`${this.#prefix} Transition: ${fromRoute} → ${toRoute}`, {\n from: fromState,\n to: toState,\n });\n\n this.#logParamsIfNeeded(toState, fromState);\n }\n },\n\n onTransitionSuccess: (toState: State, fromState?: State) => {\n if (this.#usePerf) {\n const label = this.#transitionLabel;\n const endMark = `router:transition-end:${label}`;\n\n this.#perf.mark(endMark);\n this.#perf.measure(\n `router:transition:${label}`,\n this.#startMarkName,\n endMark,\n );\n }\n\n if (this.#logTransition) {\n const timing = this.#shouldShowTiming\n ? formatTiming(this.#transitionStartTime, now)\n : \"\";\n\n console.log(`${this.#prefix} Transition success${timing}`, {\n to: toState,\n from: fromState,\n });\n }\n\n this.#resetTransitionState();\n },\n\n onTransitionCancel: (toState: State, fromState?: State) => {\n if (this.#usePerf) {\n const label = this.#transitionLabel;\n const cancelMark = `router:transition-cancel:${label}`;\n\n this.#perf.mark(cancelMark);\n this.#perf.measure(\n `router:transition-cancelled:${label}`,\n this.#startMarkName,\n cancelMark,\n );\n }\n\n if (this.#logTransition) {\n const timing = this.#shouldShowTiming\n ? formatTiming(this.#transitionStartTime, now)\n : \"\";\n\n console.warn(`${this.#prefix} Transition cancelled${timing}`, {\n to: toState,\n from: fromState,\n });\n }\n\n this.#resetTransitionState();\n },\n\n onTransitionError: (\n toState: State | undefined,\n fromState: State | undefined,\n err: RouterError,\n ) => {\n if (this.#usePerf) {\n const label = this.#transitionLabel;\n const errorMark = `router:transition-error:${label}`;\n\n this.#perf.mark(errorMark);\n this.#perf.measure(\n `router:transition-failed:${label}`,\n this.#startMarkName,\n errorMark,\n );\n }\n\n if (this.#logError) {\n const timing = this.#shouldShowTiming\n ? formatTiming(this.#transitionStartTime, now)\n : \"\";\n\n console.error(\n `${this.#prefix} Transition error: ${err.code}${timing}`,\n {\n error: err,\n stack: err.stack,\n to: toState,\n from: fromState,\n },\n );\n }\n\n this.#resetTransitionState();\n },\n\n teardown: () => {\n this.#resetTransitionState();\n },\n };\n }\n\n #logParamsIfNeeded(toState: State, fromState?: State): void {\n if (!this.#shouldLogParams || !fromState) {\n return;\n }\n\n if (toState.name !== fromState.name) {\n return;\n }\n\n const diff = getParamsDiff(fromState.params, toState.params);\n\n if (diff) {\n logParamsDiff(diff, this.#context);\n }\n }\n\n #resetTransitionState(): void {\n this.#groups.close();\n this.#transitionLabel = \"\";\n this.#startMarkName = \"\";\n this.#transitionStartTime = null;\n }\n}\n","// packages/logger-plugin/src/validation.ts\n\nimport { ERROR_PREFIX } from \"./constants\";\n\nimport type { LoggerPluginConfig } from \"./types\";\n\nconst VALID_LEVELS = new Set([\"all\", \"transitions\", \"errors\", \"none\"]);\n\nexport function validateOptions(options?: Partial<LoggerPluginConfig>): void {\n if (options === undefined) {\n return;\n }\n\n // Runtime defense: typeof null === \"object\", so check identity first.\n // TypeScript excludes null from the parameter type, but JS callers may pass it.\n if (options === (null as never) || typeof options !== \"object\") {\n throw new TypeError(`${ERROR_PREFIX} Options must be an object`);\n }\n\n if (options.level !== undefined && !VALID_LEVELS.has(options.level)) {\n throw new TypeError(\n `${ERROR_PREFIX} Invalid level: \"${options.level}\". Expected: ${[...VALID_LEVELS].join(\", \")}`,\n );\n }\n\n if (\n options.context !== undefined &&\n (typeof options.context !== \"string\" || options.context.length === 0)\n ) {\n throw new TypeError(\n `${ERROR_PREFIX} Option \"context\" must be a non-empty string`,\n );\n }\n\n if (\n options.showTiming !== undefined &&\n typeof options.showTiming !== \"boolean\"\n ) {\n throw new TypeError(\n `${ERROR_PREFIX} Option \"showTiming\" must be a boolean`,\n );\n }\n\n if (\n options.showParamsDiff !== undefined &&\n typeof options.showParamsDiff !== \"boolean\"\n ) {\n throw new TypeError(\n `${ERROR_PREFIX} Option \"showParamsDiff\" must be a boolean`,\n );\n }\n\n if (\n options.usePerformanceMarks !== undefined &&\n typeof options.usePerformanceMarks !== \"boolean\"\n ) {\n throw new TypeError(\n `${ERROR_PREFIX} Option \"usePerformanceMarks\" must be a boolean`,\n );\n }\n}\n","// packages/logger-plugin/src/factory.ts\n\nimport { DEFAULT_CONFIG } from \"./constants\";\nimport { LoggerPlugin } from \"./plugin\";\nimport { validateOptions } from \"./validation\";\n\nimport type { LoggerPluginConfig } from \"./types\";\nimport type { PluginFactory } from \"@real-router/core\";\n\nexport function loggerPluginFactory(\n options?: Partial<LoggerPluginConfig>,\n): PluginFactory {\n validateOptions(options);\n\n const config: Required<LoggerPluginConfig> = {\n ...DEFAULT_CONFIG,\n ...options,\n };\n\n return () => new LoggerPlugin(config).getPlugin();\n}\n"]}
1
+ {"version":3,"file":"index.mjs","names":["#logLifecycle","#logTransition","#logError","#shouldLogParams","#shouldShowTiming","#usePerf","#prefix","#context","#groups","#perf","#transitionStartTime","#transitionLabel","#startMarkName","#logParamsIfNeeded","#resetTransitionState"],"sources":["../../src/constants.ts","../../src/internal/console-groups.ts","../../src/internal/formatting.ts","../../src/internal/params-diff.ts","../../src/internal/performance-marks.ts","../../src/internal/timing.ts","../../src/plugin.ts","../../src/validation.ts","../../src/factory.ts"],"sourcesContent":["// packages/logger-plugin/src/constants.ts\n\nimport type { LoggerPluginConfig } from \"./types\";\n\nexport const LOGGER_CONTEXT = \"logger-plugin\";\n\nexport const ERROR_PREFIX = `[@real-router/${LOGGER_CONTEXT}]`;\n\nexport const DEFAULT_CONFIG: Required<LoggerPluginConfig> = {\n level: \"all\",\n usePerformanceMarks: false,\n showParamsDiff: true,\n showTiming: true,\n context: LOGGER_CONTEXT,\n};\n","// packages/logger-plugin/src/internal/console-groups.ts\n\n/**\n * Checks if console.group is supported in the current environment.\n */\nexport const supportsConsoleGroups = (): boolean => {\n return (\n typeof console !== \"undefined\" &&\n typeof console.group === \"function\" &&\n typeof console.groupEnd === \"function\"\n );\n};\n\n/**\n * Manager for handling console groups\n */\nexport interface GroupManager {\n /**\n * Opens a group if it's not already open\n */\n open: (label: string) => void;\n /**\n * Closes a group if it's open\n */\n close: () => void;\n /**\n * Checks if a group is currently open\n */\n isOpen: () => boolean;\n}\n\n/**\n * Creates a manager for handling console groups.\n * Prevents duplicate group opening.\n *\n * @param enabled - Whether groups are supported in the environment\n * @returns Object with open and close methods\n */\nexport const createGroupManager = (enabled: boolean): GroupManager => {\n let isOpened = false;\n\n return {\n /**\n * Opens a group if it's not already open.\n */\n open(label: string): void {\n if (!enabled || isOpened) {\n return;\n }\n\n console.group(label);\n isOpened = true;\n },\n\n /**\n * Closes a group if it's open.\n */\n close(): void {\n if (!enabled || !isOpened) {\n return;\n }\n\n console.groupEnd();\n isOpened = false;\n },\n\n /**\n * Checks if a group is currently open.\n */\n isOpen(): boolean {\n return isOpened;\n },\n };\n};\n","// packages/logger-plugin/src/internal/formatting.ts\n\nimport type { State } from \"@real-router/core\";\n\n/**\n * Formats route name for logging output.\n * Handles undefined/null.\n */\nexport const formatRouteName = (state?: State): string => {\n return state?.name ?? \"(none)\";\n};\n\n/**\n * Formats execution time information.\n * Uses adaptive units:\n * - Microseconds (μs) for <0.1ms\n * - Milliseconds (ms) for ≥0.1ms\n *\n * @param startTime - Start time or null\n * @param now - Function to get current time\n * @returns String with time or empty string\n */\nexport const formatTiming = (\n startTime: number | null,\n now: () => number,\n): string => {\n if (startTime === null) {\n return \"\";\n }\n\n const durationMs = now() - startTime;\n\n if (!Number.isFinite(durationMs) || durationMs < 0) {\n return \" (?)\";\n }\n\n if (durationMs < 0.1) {\n const durationMks = (durationMs * 1000).toFixed(2);\n\n return ` (${durationMks}μs)`;\n } else {\n const duration = durationMs.toFixed(2);\n\n return ` (${duration}ms)`;\n }\n};\n\n/**\n * Creates a label for Performance API from route names.\n */\nexport const createTransitionLabel = (\n fromRoute: string,\n toRoute: string,\n): string => {\n return `${fromRoute}→${toRoute}`;\n};\n","// packages/logger-plugin/src/internal/params-diff.ts\n\nimport type { Params } from \"@real-router/core\";\n\nexport interface ParamsDiff {\n changed: Record<string, { from: unknown; to: unknown }>;\n added: Record<string, unknown>;\n removed: Record<string, unknown>;\n}\n\n/**\n * Calculates differences between two parameter objects.\n * Performs only shallow comparison.\n *\n * @param fromParams - Previous parameters\n * @param toParams - New parameters\n * @returns Object with differences or null if there are no changes\n */\nexport const getParamsDiff = (\n fromParams: Params,\n toParams: Params,\n): ParamsDiff | null => {\n const changed: ParamsDiff[\"changed\"] = {};\n const added: ParamsDiff[\"added\"] = {};\n const removed: ParamsDiff[\"removed\"] = {};\n\n // Track if any changes found to avoid iterating through objects at the end.\n // This is a performance optimization: instead of calling Object.keys().length\n // three times to check if objects are empty, we set this flag when we find\n // any change and check it once at the end.\n let hasChanges = false;\n\n // Find changed and removed\n for (const key in fromParams) {\n if (!(key in toParams)) {\n removed[key] = fromParams[key];\n hasChanges = true;\n } else if (fromParams[key] !== toParams[key]) {\n changed[key] = { from: fromParams[key], to: toParams[key] };\n hasChanges = true;\n }\n }\n\n // Find added\n for (const key in toParams) {\n if (!(key in fromParams)) {\n added[key] = toParams[key];\n hasChanges = true;\n }\n }\n\n // Return null if there are no changes\n if (!hasChanges) {\n return null;\n }\n\n return { changed, added, removed };\n};\n\n/**\n * Formats and logs parameter differences.\n *\n * @param diff - Object with differences\n * @param context - Context for console\n */\nexport const logParamsDiff = (diff: ParamsDiff, context: string): void => {\n const parts: string[] = [];\n\n // Cache entries to avoid double iteration\n const changedEntries = Object.entries(diff.changed);\n\n if (changedEntries.length > 0) {\n const items: string[] = [];\n\n for (const [key, { from, to }] of changedEntries) {\n items.push(`${key}: ${JSON.stringify(from)} → ${JSON.stringify(to)}`);\n }\n\n parts.push(`Changed: { ${items.join(\", \")} }`);\n }\n\n if (Object.keys(diff.added).length > 0) {\n parts.push(`Added: ${JSON.stringify(diff.added)}`);\n }\n\n if (Object.keys(diff.removed).length > 0) {\n parts.push(`Removed: ${JSON.stringify(diff.removed)}`);\n }\n\n console.log(`[${context}] ${parts.join(\", \")}`);\n};\n","// packages/logger-plugin/src/internal/performance-marks.ts\n\n/**\n * Checks if Performance API is supported in the current environment.\n */\nexport const supportsPerformanceAPI = (): boolean => {\n return (\n typeof performance !== \"undefined\" &&\n typeof performance.mark === \"function\" &&\n typeof performance.measure === \"function\"\n );\n};\n\n/**\n * Performance tracker interface with mark and measure methods.\n */\nexport interface PerformanceTracker {\n mark: (name: string) => void;\n measure: (measureName: string, startMark: string, endMark: string) => void;\n}\n\n/**\n * Creates a tracker for working with the Performance API.\n * Ignores calls if the API is unavailable.\n *\n * @param enabled - Whether the functionality is enabled (from config)\n * @param context - Context for error logging\n * @returns Object with mark and measure methods\n */\nexport const createPerformanceTracker = (\n enabled: boolean,\n context: string,\n): PerformanceTracker => {\n const isSupported = enabled && supportsPerformanceAPI();\n\n return {\n /**\n * Creates a performance mark with the specified name.\n */\n mark(name: string): void {\n if (!isSupported) {\n return;\n }\n\n performance.mark(name);\n },\n\n /**\n * Creates a performance measure between two marks.\n * Logs a warning if the marks don't exist.\n */\n measure(measureName: string, startMark: string, endMark: string): void {\n if (!isSupported) {\n return;\n }\n\n try {\n performance.measure(measureName, startMark, endMark);\n } catch (error) {\n console.warn(\n `[${context}] Failed to create performance measure: ${measureName}`,\n error,\n );\n }\n },\n };\n};\n","// packages/logger-plugin/src/internal/timing.ts\n\n/**\n * Function that returns high-resolution timestamp in milliseconds.\n */\ntype TimeProvider = () => number;\n\n/**\n * State for Date.now() monotonic emulation\n */\nlet lastTimestamp = 0;\nlet timeOffset = 0;\n\n/**\n * Creates monotonic Date.now() wrapper that ensures time never goes backwards.\n *\n * @returns Time provider function with monotonic guarantee\n */\nfunction createMonotonicDateNow(): TimeProvider {\n // eslint-disable-next-line unicorn/consistent-function-scoping -- closure over module-level lastTimestamp/timeOffset\n return (): number => {\n const current: number = Date.now();\n\n if (current < lastTimestamp) {\n timeOffset += lastTimestamp - current;\n }\n\n lastTimestamp = current;\n\n return current + timeOffset;\n };\n}\n\n/**\n * Initialize time provider based on environment.\n * Uses performance.now() in modern environments (Node.js 16+, all browsers),\n * falls back to monotonic Date.now() wrapper for edge cases.\n */\nconst nowFn: TimeProvider =\n typeof performance !== \"undefined\" && typeof performance.now === \"function\"\n ? (): number => performance.now()\n : createMonotonicDateNow();\n\n/**\n * Returns high-resolution monotonic timestamp.\n *\n * Uses performance.now() in modern environments (Node.js 16+, all browsers).\n * Falls back to monotonic Date.now() wrapper (~1ms precision) for edge cases.\n *\n * @returns Timestamp in milliseconds\n */\nexport const now = (): number => nowFn();\n","// packages/logger-plugin/src/plugin.ts\n\nimport {\n createGroupManager,\n supportsConsoleGroups,\n} from \"./internal/console-groups\";\nimport {\n formatRouteName,\n formatTiming,\n createTransitionLabel,\n} from \"./internal/formatting\";\nimport { getParamsDiff, logParamsDiff } from \"./internal/params-diff\";\nimport { createPerformanceTracker } from \"./internal/performance-marks\";\nimport { now } from \"./internal/timing\";\n\nimport type { GroupManager } from \"./internal/console-groups\";\nimport type { PerformanceTracker } from \"./internal/performance-marks\";\nimport type { LoggerPluginConfig } from \"./types\";\nimport type { Plugin, RouterError, State } from \"@real-router/core\";\n\nexport class LoggerPlugin {\n readonly #logLifecycle: boolean;\n readonly #logTransition: boolean;\n readonly #logError: boolean;\n\n readonly #shouldLogParams: boolean;\n readonly #shouldShowTiming: boolean;\n readonly #usePerf: boolean;\n\n readonly #prefix: string;\n readonly #context: string;\n\n readonly #groups: GroupManager;\n readonly #perf: PerformanceTracker;\n\n // Transition state\n #transitionStartTime: number | null = null;\n #transitionLabel = \"\";\n #startMarkName = \"\";\n\n constructor(config: Required<LoggerPluginConfig>) {\n this.#logLifecycle = config.level === \"all\";\n this.#logTransition = config.level !== \"none\" && config.level !== \"errors\";\n this.#logError = config.level !== \"none\";\n\n this.#shouldLogParams = this.#logTransition && config.showParamsDiff;\n this.#shouldShowTiming = config.showTiming;\n this.#usePerf = config.usePerformanceMarks;\n\n this.#prefix = `[${config.context}]`;\n this.#context = config.context;\n\n this.#groups = createGroupManager(supportsConsoleGroups());\n this.#perf = createPerformanceTracker(\n config.usePerformanceMarks,\n config.context,\n );\n }\n\n getPlugin(): Plugin {\n return {\n onStart: () => {\n this.#perf.mark(\"router:start\");\n\n if (this.#logLifecycle) {\n console.log(`${this.#prefix} Router started`);\n }\n },\n\n onStop: () => {\n this.#groups.close();\n\n this.#perf.mark(\"router:stop\");\n this.#perf.measure(\"router:lifetime\", \"router:start\", \"router:stop\");\n\n if (this.#logLifecycle) {\n console.log(`${this.#prefix} Router stopped`);\n }\n },\n\n onTransitionStart: (toState: State, fromState?: State) => {\n this.#groups.open(\"Router transition\");\n this.#transitionStartTime = this.#shouldShowTiming ? now() : null;\n\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n\n if (this.#usePerf) {\n this.#transitionLabel = createTransitionLabel(fromRoute, toRoute);\n this.#startMarkName = `router:transition-start:${this.#transitionLabel}`;\n this.#perf.mark(this.#startMarkName);\n }\n\n if (this.#logTransition) {\n console.log(`${this.#prefix} Transition: ${fromRoute} → ${toRoute}`, {\n from: fromState,\n to: toState,\n });\n\n this.#logParamsIfNeeded(toState, fromState);\n }\n },\n\n onTransitionSuccess: (toState: State, fromState?: State) => {\n if (this.#usePerf) {\n const label = this.#transitionLabel;\n const endMark = `router:transition-end:${label}`;\n\n this.#perf.mark(endMark);\n this.#perf.measure(\n `router:transition:${label}`,\n this.#startMarkName,\n endMark,\n );\n }\n\n if (this.#logTransition) {\n const timing = this.#shouldShowTiming\n ? formatTiming(this.#transitionStartTime, now)\n : \"\";\n\n console.log(`${this.#prefix} Transition success${timing}`, {\n to: toState,\n from: fromState,\n });\n }\n\n this.#resetTransitionState();\n },\n\n onTransitionCancel: (toState: State, fromState?: State) => {\n if (this.#usePerf) {\n const label = this.#transitionLabel;\n const cancelMark = `router:transition-cancel:${label}`;\n\n this.#perf.mark(cancelMark);\n this.#perf.measure(\n `router:transition-cancelled:${label}`,\n this.#startMarkName,\n cancelMark,\n );\n }\n\n if (this.#logTransition) {\n const timing = this.#shouldShowTiming\n ? formatTiming(this.#transitionStartTime, now)\n : \"\";\n\n console.warn(`${this.#prefix} Transition cancelled${timing}`, {\n to: toState,\n from: fromState,\n });\n }\n\n this.#resetTransitionState();\n },\n\n onTransitionError: (\n toState: State | undefined,\n fromState: State | undefined,\n err: RouterError,\n ) => {\n if (this.#usePerf) {\n const label = this.#transitionLabel;\n const errorMark = `router:transition-error:${label}`;\n\n this.#perf.mark(errorMark);\n this.#perf.measure(\n `router:transition-failed:${label}`,\n this.#startMarkName,\n errorMark,\n );\n }\n\n if (this.#logError) {\n const timing = this.#shouldShowTiming\n ? formatTiming(this.#transitionStartTime, now)\n : \"\";\n\n console.error(\n `${this.#prefix} Transition error: ${err.code}${timing}`,\n {\n error: err,\n stack: err.stack,\n to: toState,\n from: fromState,\n },\n );\n }\n\n this.#resetTransitionState();\n },\n\n teardown: () => {\n this.#resetTransitionState();\n },\n };\n }\n\n #logParamsIfNeeded(toState: State, fromState?: State): void {\n if (!this.#shouldLogParams || !fromState) {\n return;\n }\n\n if (toState.name !== fromState.name) {\n return;\n }\n\n const diff = getParamsDiff(fromState.params, toState.params);\n\n if (diff) {\n logParamsDiff(diff, this.#context);\n }\n }\n\n #resetTransitionState(): void {\n this.#groups.close();\n this.#transitionLabel = \"\";\n this.#startMarkName = \"\";\n this.#transitionStartTime = null;\n }\n}\n","// packages/logger-plugin/src/validation.ts\n\nimport { ERROR_PREFIX } from \"./constants\";\n\nimport type { LoggerPluginConfig } from \"./types\";\n\nconst VALID_LEVELS = new Set([\"all\", \"transitions\", \"errors\", \"none\"]);\n\nexport function validateOptions(options?: Partial<LoggerPluginConfig>): void {\n if (options === undefined) {\n return;\n }\n\n // Runtime defense: typeof null === \"object\", so check identity first.\n // TypeScript excludes null from the parameter type, but JS callers may pass it.\n if (options === (null as never) || typeof options !== \"object\") {\n throw new TypeError(`${ERROR_PREFIX} Options must be an object`);\n }\n\n if (options.level !== undefined && !VALID_LEVELS.has(options.level)) {\n throw new TypeError(\n `${ERROR_PREFIX} Invalid level: \"${options.level}\". Expected: ${[...VALID_LEVELS].join(\", \")}`,\n );\n }\n\n if (\n options.context !== undefined &&\n (typeof options.context !== \"string\" || options.context.length === 0)\n ) {\n throw new TypeError(\n `${ERROR_PREFIX} Option \"context\" must be a non-empty string`,\n );\n }\n\n if (\n options.showTiming !== undefined &&\n typeof options.showTiming !== \"boolean\"\n ) {\n throw new TypeError(\n `${ERROR_PREFIX} Option \"showTiming\" must be a boolean`,\n );\n }\n\n if (\n options.showParamsDiff !== undefined &&\n typeof options.showParamsDiff !== \"boolean\"\n ) {\n throw new TypeError(\n `${ERROR_PREFIX} Option \"showParamsDiff\" must be a boolean`,\n );\n }\n\n if (\n options.usePerformanceMarks !== undefined &&\n typeof options.usePerformanceMarks !== \"boolean\"\n ) {\n throw new TypeError(\n `${ERROR_PREFIX} Option \"usePerformanceMarks\" must be a boolean`,\n );\n }\n}\n","// packages/logger-plugin/src/factory.ts\n\nimport { DEFAULT_CONFIG } from \"./constants\";\nimport { LoggerPlugin } from \"./plugin\";\nimport { validateOptions } from \"./validation\";\n\nimport type { LoggerPluginConfig } from \"./types\";\nimport type { PluginFactory } from \"@real-router/core\";\n\nexport function loggerPluginFactory(\n options?: Partial<LoggerPluginConfig>,\n): PluginFactory {\n validateOptions(options);\n\n const config: Required<LoggerPluginConfig> = {\n ...DEFAULT_CONFIG,\n ...options,\n };\n\n return () => new LoggerPlugin(config).getPlugin();\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@real-router/logger-plugin",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "type": "commonjs",
5
5
  "description": "Development logging plugin with transition tracking and performance metrics",
6
6
  "main": "./dist/cjs/index.js",
@@ -45,10 +45,10 @@
45
45
  "homepage": "https://github.com/greydragon888/real-router",
46
46
  "sideEffects": false,
47
47
  "dependencies": {
48
- "@real-router/core": "^0.41.0"
48
+ "@real-router/core": "^0.42.0"
49
49
  },
50
50
  "scripts": {
51
- "build": "tsup",
51
+ "build": "tsdown --config-loader unrun",
52
52
  "test": "vitest run",
53
53
  "test:properties": "vitest run --config vitest.config.properties.mts",
54
54
  "type-check": "tsc --noEmit",
@@ -57,6 +57,6 @@
57
57
  "test:mutation:report": "open reports/mutation-report.html",
58
58
  "lint:package": "publint",
59
59
  "lint:types": "attw --pack .",
60
- "build:dist-only": "tsup"
60
+ "build:dist-only": "tsdown --config-loader unrun"
61
61
  }
62
62
  }
@@ -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"},"src/constants.ts":{"bytes":391,"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/internal/console-groups.ts":{"bytes":1493,"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/internal/formatting.ts":{"bytes":1230,"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/internal/params-diff.ts":{"bytes":2530,"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/internal/performance-marks.ts":{"bytes":1723,"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/internal/timing.ts":{"bytes":1476,"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/plugin.ts":{"bytes":6172,"imports":[{"path":"src/internal/console-groups.ts","kind":"import-statement","original":"./internal/console-groups"},{"path":"src/internal/formatting.ts","kind":"import-statement","original":"./internal/formatting"},{"path":"src/internal/params-diff.ts","kind":"import-statement","original":"./internal/params-diff"},{"path":"src/internal/performance-marks.ts","kind":"import-statement","original":"./internal/performance-marks"},{"path":"src/internal/timing.ts","kind":"import-statement","original":"./internal/timing"},{"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":1714,"imports":[{"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":561,"imports":[{"path":"src/constants.ts","kind":"import-statement","original":"./constants"},{"path":"src/plugin.ts","kind":"import-statement","original":"./plugin"},{"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":151,"imports":[{"path":"src/factory.ts","kind":"import-statement","original":"./factory"},{"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":25622},"dist/cjs/index.js":{"imports":[],"exports":["loggerPluginFactory"],"entryPoint":"src/index.ts","inputs":{"src/constants.ts":{"bytesInOutput":235},"src/internal/console-groups.ts":{"bytesInOutput":727},"src/internal/formatting.ts":{"bytesInOutput":592},"src/internal/params-diff.ts":{"bytesInOutput":1277},"src/internal/performance-marks.ts":{"bytesInOutput":941},"src/internal/timing.ts":{"bytesInOutput":450},"src/plugin.ts":{"bytesInOutput":4975},"src/validation.ts":{"bytesInOutput":1298},"src/factory.ts":{"bytesInOutput":185},"src/index.ts":{"bytesInOutput":0}},"bytes":10956}}}
@@ -1 +0,0 @@
1
- {"inputs":{"src/constants.ts":{"bytes":391,"imports":[],"format":"esm"},"src/internal/console-groups.ts":{"bytes":1493,"imports":[],"format":"esm"},"src/internal/formatting.ts":{"bytes":1230,"imports":[],"format":"esm"},"src/internal/params-diff.ts":{"bytes":2530,"imports":[],"format":"esm"},"src/internal/performance-marks.ts":{"bytes":1723,"imports":[],"format":"esm"},"src/internal/timing.ts":{"bytes":1476,"imports":[],"format":"esm"},"src/plugin.ts":{"bytes":6172,"imports":[{"path":"src/internal/console-groups.ts","kind":"import-statement","original":"./internal/console-groups"},{"path":"src/internal/formatting.ts","kind":"import-statement","original":"./internal/formatting"},{"path":"src/internal/params-diff.ts","kind":"import-statement","original":"./internal/params-diff"},{"path":"src/internal/performance-marks.ts","kind":"import-statement","original":"./internal/performance-marks"},{"path":"src/internal/timing.ts","kind":"import-statement","original":"./internal/timing"}],"format":"esm"},"src/validation.ts":{"bytes":1714,"imports":[{"path":"src/constants.ts","kind":"import-statement","original":"./constants"}],"format":"esm"},"src/factory.ts":{"bytes":561,"imports":[{"path":"src/constants.ts","kind":"import-statement","original":"./constants"},{"path":"src/plugin.ts","kind":"import-statement","original":"./plugin"},{"path":"src/validation.ts","kind":"import-statement","original":"./validation"}],"format":"esm"},"src/index.ts":{"bytes":151,"imports":[{"path":"src/factory.ts","kind":"import-statement","original":"./factory"}],"format":"esm"}},"outputs":{"dist/esm/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":25622},"dist/esm/index.mjs":{"imports":[],"exports":["loggerPluginFactory"],"entryPoint":"src/index.ts","inputs":{"src/constants.ts":{"bytesInOutput":235},"src/internal/console-groups.ts":{"bytesInOutput":727},"src/internal/formatting.ts":{"bytesInOutput":592},"src/internal/params-diff.ts":{"bytesInOutput":1277},"src/internal/performance-marks.ts":{"bytesInOutput":941},"src/internal/timing.ts":{"bytesInOutput":450},"src/plugin.ts":{"bytesInOutput":4975},"src/validation.ts":{"bytesInOutput":1298},"src/factory.ts":{"bytesInOutput":185},"src/index.ts":{"bytesInOutput":0}},"bytes":10956}}}