@real-router/logger-plugin 0.2.39 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -55,20 +55,12 @@ import { loggerPluginFactory } from "@real-router/logger-plugin";
55
55
  router.usePlugin(loggerPluginFactory());
56
56
 
57
57
  // With custom options
58
- router.usePlugin(loggerPluginFactory({
59
- level: "errors",
60
- showTiming: false,
61
- }));
62
- ```
63
-
64
- ### `loggerPlugin`
65
-
66
- Ready-to-use plugin instance with default settings. Provided for backward compatibility.
67
-
68
- ```typescript
69
- import { loggerPlugin } from "@real-router/logger-plugin";
70
-
71
- router.usePlugin(loggerPlugin);
58
+ router.usePlugin(
59
+ loggerPluginFactory({
60
+ level: "errors",
61
+ showTiming: false,
62
+ }),
63
+ );
72
64
  ```
73
65
 
74
66
  ---
@@ -87,28 +79,36 @@ router.usePlugin(loggerPlugin);
87
79
 
88
80
  ```typescript
89
81
  // With custom context for multiple routers
90
- router.usePlugin(loggerPluginFactory({
91
- context: "main-router",
92
- }));
82
+ router.usePlugin(
83
+ loggerPluginFactory({
84
+ context: "main-router",
85
+ }),
86
+ );
93
87
 
94
88
  // Performance profiling enabled
95
- router.usePlugin(loggerPluginFactory({
96
- usePerformanceMarks: true,
97
- showTiming: true,
98
- }));
89
+ router.usePlugin(
90
+ loggerPluginFactory({
91
+ usePerformanceMarks: true,
92
+ showTiming: true,
93
+ }),
94
+ );
99
95
 
100
96
  // Errors only (for production-like environments)
101
- router.usePlugin(loggerPluginFactory({
102
- level: "errors",
103
- showTiming: false,
104
- }));
97
+ router.usePlugin(
98
+ loggerPluginFactory({
99
+ level: "errors",
100
+ showTiming: false,
101
+ }),
102
+ );
105
103
 
106
104
  // Minimal output
107
- router.usePlugin(loggerPluginFactory({
108
- level: "transitions",
109
- showParamsDiff: false,
110
- showTiming: false,
111
- }));
105
+ router.usePlugin(
106
+ loggerPluginFactory({
107
+ level: "transitions",
108
+ showParamsDiff: false,
109
+ showTiming: false,
110
+ }),
111
+ );
112
112
  ```
113
113
 
114
114
  See [Wiki](https://github.com/greydragon888/real-router/wiki/logger-plugin#3-configuration-options) for detailed descriptions.
@@ -50,7 +50,7 @@ interface LoggerPluginConfig {
50
50
  * Only applies when navigating within the same route.
51
51
  * Helps identify which parameters changed during navigation.
52
52
  *
53
- * @default false
53
+ * @default true
54
54
  */
55
55
  showParamsDiff?: boolean;
56
56
  /**
@@ -62,38 +62,6 @@ interface LoggerPluginConfig {
62
62
  context?: string;
63
63
  }
64
64
 
65
- /**
66
- * Creates a logger-plugin for real-router.
67
- *
68
- * @param options - Plugin configuration options
69
- * @returns Plugin factory function for real-router
70
- *
71
- * @example
72
- * ```ts
73
- * import { loggerPluginFactory } from "@real-router/logger-plugin";
74
- *
75
- * // Use with default configuration
76
- * router.usePlugin(loggerPluginFactory());
77
- *
78
- * // Use with custom configuration
79
- * router.usePlugin(loggerPluginFactory({
80
- * level: 'errors', // only log errors
81
- * usePerformanceMarks: true, // enable Performance API
82
- * showTiming: false, // disable timing info
83
- * showParamsDiff: false, // disable params diff
84
- * context: 'my-router', // custom context name
85
- * }));
86
- * ```
87
- */
88
65
  declare function loggerPluginFactory(options?: Partial<LoggerPluginConfig>): PluginFactory;
89
- /**
90
- * Default logger-plugin instance with standard configuration.
91
- * Provided for backward compatibility with existing code.
92
- *
93
- * @example
94
- * // Use default configuration
95
- * router.usePlugin(loggerPlugin);
96
- */
97
- declare const loggerPlugin: PluginFactory;
98
66
 
99
- export { type LogLevel, type LoggerPluginConfig, loggerPlugin, loggerPluginFactory };
67
+ export { type LogLevel, type LoggerPluginConfig, loggerPluginFactory };
package/dist/cjs/index.js CHANGED
@@ -1 +1 @@
1
- var e={level:"all",usePerformanceMarks:!1,showParamsDiff:!0,showTiming:!0,context:"logger-plugin"},o=e=>e?.name??"(none)",r=(e,o)=>{if(null===e)return"";const r=o()-e;return!Number.isFinite(r)||r<0?" (?)":r<.1?` (${(1e3*r).toFixed(2)}μs)`:` (${r.toFixed(2)}ms)`},n=0,t=0,s="undefined"!=typeof performance&&"function"==typeof performance.now?()=>performance.now():()=>{const e=Date.now();return e<n&&(t+=n-e),n=e,e+t},a=()=>s();function i(n){const t={...e,...n},s="all"===t.level,i="none"!==t.level&&"errors"!==t.level,c=i,l="none"!==t.level,u=i&&t.showParamsDiff,f=t.showTiming,m=`[${t.context}]`;return()=>{const e=(e=>{let o=!1;return{open(r){e&&!o&&(console.group(r),o=!0)},close(){e&&o&&(console.groupEnd(),o=!1)},isOpen:()=>o}})("undefined"!=typeof console&&"function"==typeof console.group&&"function"==typeof console.groupEnd),n=((e,o)=>{const r=e&&"undefined"!=typeof performance&&"function"==typeof performance.mark&&"function"==typeof performance.measure;return{mark(e){r&&performance.mark(e)},measure(e,n,t){if(r)try{performance.measure(e,n,t)}catch(r){console.warn(`[${o}] Failed to create performance measure: ${e}`,r)}}}})(t.usePerformanceMarks,t.context);let d=null,p="",$="";const g=()=>{e.close(),p="",$="",d=null};return{onStart(){n.mark("router:start"),s&&console.log(`${m} Router started`)},onStop(){e.close(),n.mark("router:stop"),n.measure("router:lifetime","router:start","router:stop"),s&&console.log(`${m} Router stopped`)},onTransitionStart(r,s){e.open("Router transition"),d=a();const c=o(s),l=o(r);p=((e,o)=>`${e}→${o}`)(c,l),$=`router:transition-start:${p}`,n.mark($),i&&(console.log(`${m} Transition: ${c} → ${l}`,{from:s,to:r}),((e,o)=>{if(!u||!o)return;if(e.name!==o.name)return;const r=((e,o)=>{const r={},n={},t={};let s=!1;for(const n in e)n in o?e[n]!==o[n]&&(r[n]={from:e[n],to:o[n]},s=!0):(t[n]=e[n],s=!0);for(const r in o)r in e||(n[r]=o[r],s=!0);return s?{changed:r,added:n,removed:t}:null})(o.params,e.params);r&&((e,o)=>{const r=[],n=Object.entries(e.changed);if(n.length>0){const e=[];for(const[o,{from:r,to:t}]of n)e.push(`${o}: ${JSON.stringify(r)} → ${JSON.stringify(t)}`);r.push(`Changed: { ${e.join(", ")} }`)}Object.keys(e.added).length>0&&r.push(`Added: ${JSON.stringify(e.added)}`),Object.keys(e.removed).length>0&&r.push(`Removed: ${JSON.stringify(e.removed)}`),console.log(`[${o}] ${r.join(", ")}`)})(r,t.context)})(r,s))},onTransitionSuccess(e,o){const t=p,s=`router:transition-end:${t}`;if(n.mark(s),n.measure(`router:transition:${t}`,$,s),i){const n=f?r(d,a):"";console.log(`${m} Transition success${n}`,{to:e,from:o})}g()},onTransitionCancel(e,o){const t=p,s=`router:transition-cancel:${t}`;if(n.mark(s),n.measure(`router:transition-cancelled:${t}`,$,s),c){const n=f?r(d,a):"";console.warn(`${m} Transition cancelled${n}`,{to:e,from:o})}g()},onTransitionError(e,o,t){const s=p,i=`router:transition-error:${s}`;if(n.mark(i),n.measure(`router:transition-failed:${s}`,$,i),l){const n=f?r(d,a):"";console.error(`${m} Transition error: ${t.code}${n}`,{error:t,stack:t.stack,to:e,from:o})}g()},teardown(){g()}}}}var c=i();exports.loggerPlugin=c,exports.loggerPluginFactory=i;//# sourceMappingURL=index.js.map
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"]);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 r={...o,...t};return()=>new f(r).getPlugin()};//# 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"],"names":["now"],"mappings":"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","file":"index.js","sourcesContent":["// packages/logger-plugin/modules/constants.ts\n\nimport type { LoggerPluginConfig } from \"./types\";\n\nexport const DEFAULT_CONFIG: Required<LoggerPluginConfig> = {\n level: \"all\",\n usePerformanceMarks: false,\n showParamsDiff: true,\n showTiming: true,\n context: \"logger-plugin\",\n};\n","// packages/logger-plugin/modules/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 */\ninterface 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/modules/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/modules/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/modules/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 */\ninterface 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/modules/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/modules/plugin.ts\n\nimport { DEFAULT_CONFIG } from \"./constants\";\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 { LoggerPluginConfig } from \"./types\";\nimport type { PluginFactory, RouterError, State } from \"@real-router/core\";\n\n/**\n * Creates a logger-plugin for real-router.\n *\n * @param options - Plugin configuration options\n * @returns Plugin factory function for real-router\n *\n * @example\n * ```ts\n * import { loggerPluginFactory } from \"@real-router/logger-plugin\";\n *\n * // Use with default configuration\n * router.usePlugin(loggerPluginFactory());\n *\n * // Use with custom configuration\n * router.usePlugin(loggerPluginFactory({\n * level: 'errors', // only log errors\n * usePerformanceMarks: true, // enable Performance API\n * showTiming: false, // disable timing info\n * showParamsDiff: false, // disable params diff\n * context: 'my-router', // custom context name\n * }));\n * ```\n */\nexport function loggerPluginFactory(\n options?: Partial<LoggerPluginConfig>,\n): PluginFactory {\n // Merge options with defaults\n const config: Required<LoggerPluginConfig> = {\n ...DEFAULT_CONFIG,\n ...options,\n };\n\n // Pre-compute log level flags\n const logLifecycle = config.level === \"all\";\n const logTransition = config.level !== \"none\" && config.level !== \"errors\";\n const logWarning = logTransition;\n const logError = config.level !== \"none\";\n\n // Pre-compute feature flags\n const shouldLogParams = logTransition && config.showParamsDiff;\n const shouldShowTiming = config.showTiming;\n\n // Cached prefix\n const prefix = `[${config.context}]`;\n\n return () => {\n // Create helper managers\n const groups = createGroupManager(supportsConsoleGroups());\n const perf = createPerformanceTracker(\n config.usePerformanceMarks,\n config.context,\n );\n\n // Transition state\n let transitionStartTime: number | null = null;\n let transitionLabel = \"\";\n let startMarkName = \"\";\n\n /**\n * Logs parameter differences when navigating within the same route.\n */\n const logParamsIfNeeded = (toState: State, fromState?: State): void => {\n if (!shouldLogParams || !fromState) {\n return;\n }\n\n // Show diff only for the same route\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, config.context);\n }\n };\n\n /**\n * Resets transition state. Must be called AFTER timing is read.\n */\n const resetTransitionState = (): void => {\n groups.close();\n transitionLabel = \"\";\n startMarkName = \"\";\n transitionStartTime = null;\n };\n\n return {\n onStart() {\n perf.mark(\"router:start\");\n\n if (logLifecycle) {\n console.log(`${prefix} Router started`);\n }\n },\n\n onStop() {\n groups.close();\n\n perf.mark(\"router:stop\");\n perf.measure(\"router:lifetime\", \"router:start\", \"router:stop\");\n\n if (logLifecycle) {\n console.log(`${prefix} Router stopped`);\n }\n },\n\n onTransitionStart(toState: State, fromState?: State) {\n groups.open(\"Router transition\");\n transitionStartTime = now();\n\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n\n transitionLabel = createTransitionLabel(fromRoute, toRoute);\n startMarkName = `router:transition-start:${transitionLabel}`;\n\n perf.mark(startMarkName);\n\n if (logTransition) {\n console.log(`${prefix} Transition: ${fromRoute} → ${toRoute}`, {\n from: fromState,\n to: toState,\n });\n\n logParamsIfNeeded(toState, fromState);\n }\n },\n\n onTransitionSuccess(toState: State, fromState?: State) {\n const label = transitionLabel;\n const endMark = `router:transition-end:${label}`;\n\n perf.mark(endMark);\n perf.measure(`router:transition:${label}`, startMarkName, endMark);\n\n if (logTransition) {\n const timing = shouldShowTiming\n ? formatTiming(transitionStartTime, now)\n : \"\";\n\n console.log(`${prefix} Transition success${timing}`, {\n to: toState,\n from: fromState,\n });\n }\n\n resetTransitionState();\n },\n\n onTransitionCancel(toState: State, fromState?: State) {\n const label = transitionLabel;\n const cancelMark = `router:transition-cancel:${label}`;\n\n perf.mark(cancelMark);\n perf.measure(\n `router:transition-cancelled:${label}`,\n startMarkName,\n cancelMark,\n );\n\n if (logWarning) {\n const timing = shouldShowTiming\n ? formatTiming(transitionStartTime, now)\n : \"\";\n\n console.warn(`${prefix} Transition cancelled${timing}`, {\n to: toState,\n from: fromState,\n });\n }\n\n resetTransitionState();\n },\n\n onTransitionError(\n toState: State | undefined,\n fromState: State | undefined,\n err: RouterError,\n ) {\n const label = transitionLabel;\n const errorMark = `router:transition-error:${label}`;\n\n perf.mark(errorMark);\n perf.measure(\n `router:transition-failed:${label}`,\n startMarkName,\n errorMark,\n );\n\n if (logError) {\n const timing = shouldShowTiming\n ? formatTiming(transitionStartTime, now)\n : \"\";\n\n console.error(`${prefix} Transition error: ${err.code}${timing}`, {\n error: err,\n stack: err.stack,\n to: toState,\n from: fromState,\n });\n }\n\n resetTransitionState();\n },\n\n teardown() {\n resetTransitionState();\n },\n };\n };\n}\n\n/**\n * Default logger-plugin instance with standard configuration.\n * Provided for backward compatibility with existing code.\n *\n * @example\n * // Use default configuration\n * router.usePlugin(loggerPlugin);\n */\nexport const loggerPlugin = loggerPluginFactory();\n"]}
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 +1 @@
1
- {"inputs":{"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js":{"bytes":569,"imports":[],"format":"esm"},"src/constants.ts":{"bytes":283,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/internal/console-groups.ts":{"bytes":1490,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/internal/formatting.ts":{"bytes":1234,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/internal/params-diff.ts":{"bytes":2534,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/internal/performance-marks.ts":{"bytes":1720,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/internal/timing.ts":{"bytes":1480,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/plugin.ts":{"bytes":6520,"imports":[{"path":"src/constants.ts","kind":"import-statement","original":"./constants"},{"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.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":266,"imports":[{"path":"src/plugin.ts","kind":"import-statement","original":"./plugin"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.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":21834},"dist/cjs/index.js":{"imports":[],"exports":["loggerPlugin","loggerPluginFactory"],"entryPoint":"src/index.ts","inputs":{"src/constants.ts":{"bytesInOutput":143},"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":4237},"src/index.ts":{"bytesInOutput":0}},"bytes":8618}}}
1
+ {"inputs":{"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_typescript@5.9.3_yaml@2.8.2/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_typescript@5.9.3_yaml@2.8.2/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_typescript@5.9.3_yaml@2.8.2/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_typescript@5.9.3_yaml@2.8.2/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_typescript@5.9.3_yaml@2.8.2/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_typescript@5.9.3_yaml@2.8.2/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_typescript@5.9.3_yaml@2.8.2/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_typescript@5.9.3_yaml@2.8.2/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_typescript@5.9.3_yaml@2.8.2/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_typescript@5.9.3_yaml@2.8.2/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_typescript@5.9.3_yaml@2.8.2/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}}}
@@ -50,7 +50,7 @@ interface LoggerPluginConfig {
50
50
  * Only applies when navigating within the same route.
51
51
  * Helps identify which parameters changed during navigation.
52
52
  *
53
- * @default false
53
+ * @default true
54
54
  */
55
55
  showParamsDiff?: boolean;
56
56
  /**
@@ -62,38 +62,6 @@ interface LoggerPluginConfig {
62
62
  context?: string;
63
63
  }
64
64
 
65
- /**
66
- * Creates a logger-plugin for real-router.
67
- *
68
- * @param options - Plugin configuration options
69
- * @returns Plugin factory function for real-router
70
- *
71
- * @example
72
- * ```ts
73
- * import { loggerPluginFactory } from "@real-router/logger-plugin";
74
- *
75
- * // Use with default configuration
76
- * router.usePlugin(loggerPluginFactory());
77
- *
78
- * // Use with custom configuration
79
- * router.usePlugin(loggerPluginFactory({
80
- * level: 'errors', // only log errors
81
- * usePerformanceMarks: true, // enable Performance API
82
- * showTiming: false, // disable timing info
83
- * showParamsDiff: false, // disable params diff
84
- * context: 'my-router', // custom context name
85
- * }));
86
- * ```
87
- */
88
65
  declare function loggerPluginFactory(options?: Partial<LoggerPluginConfig>): PluginFactory;
89
- /**
90
- * Default logger-plugin instance with standard configuration.
91
- * Provided for backward compatibility with existing code.
92
- *
93
- * @example
94
- * // Use default configuration
95
- * router.usePlugin(loggerPlugin);
96
- */
97
- declare const loggerPlugin: PluginFactory;
98
66
 
99
- export { type LogLevel, type LoggerPluginConfig, loggerPlugin, loggerPluginFactory };
67
+ export { type LogLevel, type LoggerPluginConfig, loggerPluginFactory };
@@ -1 +1 @@
1
- var e={level:"all",usePerformanceMarks:!1,showParamsDiff:!0,showTiming:!0,context:"logger-plugin"},o=e=>e?.name??"(none)",n=(e,o)=>{if(null===e)return"";const n=o()-e;return!Number.isFinite(n)||n<0?" (?)":n<.1?` (${(1e3*n).toFixed(2)}μs)`:` (${n.toFixed(2)}ms)`},r=0,t=0,s="undefined"!=typeof performance&&"function"==typeof performance.now?()=>performance.now():()=>{const e=Date.now();return e<r&&(t+=r-e),r=e,e+t},a=()=>s();function i(r){const t={...e,...r},s="all"===t.level,i="none"!==t.level&&"errors"!==t.level,c=i,l="none"!==t.level,u=i&&t.showParamsDiff,f=t.showTiming,m=`[${t.context}]`;return()=>{const e=(e=>{let o=!1;return{open(n){e&&!o&&(console.group(n),o=!0)},close(){e&&o&&(console.groupEnd(),o=!1)},isOpen:()=>o}})("undefined"!=typeof console&&"function"==typeof console.group&&"function"==typeof console.groupEnd),r=((e,o)=>{const n=e&&"undefined"!=typeof performance&&"function"==typeof performance.mark&&"function"==typeof performance.measure;return{mark(e){n&&performance.mark(e)},measure(e,r,t){if(n)try{performance.measure(e,r,t)}catch(n){console.warn(`[${o}] Failed to create performance measure: ${e}`,n)}}}})(t.usePerformanceMarks,t.context);let d=null,p="",$="";const g=()=>{e.close(),p="",$="",d=null};return{onStart(){r.mark("router:start"),s&&console.log(`${m} Router started`)},onStop(){e.close(),r.mark("router:stop"),r.measure("router:lifetime","router:start","router:stop"),s&&console.log(`${m} Router stopped`)},onTransitionStart(n,s){e.open("Router transition"),d=a();const c=o(s),l=o(n);p=((e,o)=>`${e}→${o}`)(c,l),$=`router:transition-start:${p}`,r.mark($),i&&(console.log(`${m} Transition: ${c} → ${l}`,{from:s,to:n}),((e,o)=>{if(!u||!o)return;if(e.name!==o.name)return;const n=((e,o)=>{const n={},r={},t={};let s=!1;for(const r in e)r in o?e[r]!==o[r]&&(n[r]={from:e[r],to:o[r]},s=!0):(t[r]=e[r],s=!0);for(const n in o)n in e||(r[n]=o[n],s=!0);return s?{changed:n,added:r,removed:t}:null})(o.params,e.params);n&&((e,o)=>{const n=[],r=Object.entries(e.changed);if(r.length>0){const e=[];for(const[o,{from:n,to:t}]of r)e.push(`${o}: ${JSON.stringify(n)} → ${JSON.stringify(t)}`);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(`[${o}] ${n.join(", ")}`)})(n,t.context)})(n,s))},onTransitionSuccess(e,o){const t=p,s=`router:transition-end:${t}`;if(r.mark(s),r.measure(`router:transition:${t}`,$,s),i){const r=f?n(d,a):"";console.log(`${m} Transition success${r}`,{to:e,from:o})}g()},onTransitionCancel(e,o){const t=p,s=`router:transition-cancel:${t}`;if(r.mark(s),r.measure(`router:transition-cancelled:${t}`,$,s),c){const r=f?n(d,a):"";console.warn(`${m} Transition cancelled${r}`,{to:e,from:o})}g()},onTransitionError(e,o,t){const s=p,i=`router:transition-error:${s}`;if(r.mark(i),r.measure(`router:transition-failed:${s}`,$,i),l){const r=f?n(d,a):"";console.error(`${m} Transition error: ${t.code}${r}`,{error:t,stack:t.stack,to:e,from:o})}g()},teardown(){g()}}}}var c=i();export{c as loggerPlugin,i as loggerPluginFactory};//# sourceMappingURL=index.mjs.map
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 +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"],"names":["now"],"mappings":"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","file":"index.mjs","sourcesContent":["// packages/logger-plugin/modules/constants.ts\n\nimport type { LoggerPluginConfig } from \"./types\";\n\nexport const DEFAULT_CONFIG: Required<LoggerPluginConfig> = {\n level: \"all\",\n usePerformanceMarks: false,\n showParamsDiff: true,\n showTiming: true,\n context: \"logger-plugin\",\n};\n","// packages/logger-plugin/modules/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 */\ninterface 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/modules/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/modules/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/modules/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 */\ninterface 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/modules/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/modules/plugin.ts\n\nimport { DEFAULT_CONFIG } from \"./constants\";\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 { LoggerPluginConfig } from \"./types\";\nimport type { PluginFactory, RouterError, State } from \"@real-router/core\";\n\n/**\n * Creates a logger-plugin for real-router.\n *\n * @param options - Plugin configuration options\n * @returns Plugin factory function for real-router\n *\n * @example\n * ```ts\n * import { loggerPluginFactory } from \"@real-router/logger-plugin\";\n *\n * // Use with default configuration\n * router.usePlugin(loggerPluginFactory());\n *\n * // Use with custom configuration\n * router.usePlugin(loggerPluginFactory({\n * level: 'errors', // only log errors\n * usePerformanceMarks: true, // enable Performance API\n * showTiming: false, // disable timing info\n * showParamsDiff: false, // disable params diff\n * context: 'my-router', // custom context name\n * }));\n * ```\n */\nexport function loggerPluginFactory(\n options?: Partial<LoggerPluginConfig>,\n): PluginFactory {\n // Merge options with defaults\n const config: Required<LoggerPluginConfig> = {\n ...DEFAULT_CONFIG,\n ...options,\n };\n\n // Pre-compute log level flags\n const logLifecycle = config.level === \"all\";\n const logTransition = config.level !== \"none\" && config.level !== \"errors\";\n const logWarning = logTransition;\n const logError = config.level !== \"none\";\n\n // Pre-compute feature flags\n const shouldLogParams = logTransition && config.showParamsDiff;\n const shouldShowTiming = config.showTiming;\n\n // Cached prefix\n const prefix = `[${config.context}]`;\n\n return () => {\n // Create helper managers\n const groups = createGroupManager(supportsConsoleGroups());\n const perf = createPerformanceTracker(\n config.usePerformanceMarks,\n config.context,\n );\n\n // Transition state\n let transitionStartTime: number | null = null;\n let transitionLabel = \"\";\n let startMarkName = \"\";\n\n /**\n * Logs parameter differences when navigating within the same route.\n */\n const logParamsIfNeeded = (toState: State, fromState?: State): void => {\n if (!shouldLogParams || !fromState) {\n return;\n }\n\n // Show diff only for the same route\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, config.context);\n }\n };\n\n /**\n * Resets transition state. Must be called AFTER timing is read.\n */\n const resetTransitionState = (): void => {\n groups.close();\n transitionLabel = \"\";\n startMarkName = \"\";\n transitionStartTime = null;\n };\n\n return {\n onStart() {\n perf.mark(\"router:start\");\n\n if (logLifecycle) {\n console.log(`${prefix} Router started`);\n }\n },\n\n onStop() {\n groups.close();\n\n perf.mark(\"router:stop\");\n perf.measure(\"router:lifetime\", \"router:start\", \"router:stop\");\n\n if (logLifecycle) {\n console.log(`${prefix} Router stopped`);\n }\n },\n\n onTransitionStart(toState: State, fromState?: State) {\n groups.open(\"Router transition\");\n transitionStartTime = now();\n\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n\n transitionLabel = createTransitionLabel(fromRoute, toRoute);\n startMarkName = `router:transition-start:${transitionLabel}`;\n\n perf.mark(startMarkName);\n\n if (logTransition) {\n console.log(`${prefix} Transition: ${fromRoute} → ${toRoute}`, {\n from: fromState,\n to: toState,\n });\n\n logParamsIfNeeded(toState, fromState);\n }\n },\n\n onTransitionSuccess(toState: State, fromState?: State) {\n const label = transitionLabel;\n const endMark = `router:transition-end:${label}`;\n\n perf.mark(endMark);\n perf.measure(`router:transition:${label}`, startMarkName, endMark);\n\n if (logTransition) {\n const timing = shouldShowTiming\n ? formatTiming(transitionStartTime, now)\n : \"\";\n\n console.log(`${prefix} Transition success${timing}`, {\n to: toState,\n from: fromState,\n });\n }\n\n resetTransitionState();\n },\n\n onTransitionCancel(toState: State, fromState?: State) {\n const label = transitionLabel;\n const cancelMark = `router:transition-cancel:${label}`;\n\n perf.mark(cancelMark);\n perf.measure(\n `router:transition-cancelled:${label}`,\n startMarkName,\n cancelMark,\n );\n\n if (logWarning) {\n const timing = shouldShowTiming\n ? formatTiming(transitionStartTime, now)\n : \"\";\n\n console.warn(`${prefix} Transition cancelled${timing}`, {\n to: toState,\n from: fromState,\n });\n }\n\n resetTransitionState();\n },\n\n onTransitionError(\n toState: State | undefined,\n fromState: State | undefined,\n err: RouterError,\n ) {\n const label = transitionLabel;\n const errorMark = `router:transition-error:${label}`;\n\n perf.mark(errorMark);\n perf.measure(\n `router:transition-failed:${label}`,\n startMarkName,\n errorMark,\n );\n\n if (logError) {\n const timing = shouldShowTiming\n ? formatTiming(transitionStartTime, now)\n : \"\";\n\n console.error(`${prefix} Transition error: ${err.code}${timing}`, {\n error: err,\n stack: err.stack,\n to: toState,\n from: fromState,\n });\n }\n\n resetTransitionState();\n },\n\n teardown() {\n resetTransitionState();\n },\n };\n };\n}\n\n/**\n * Default logger-plugin instance with standard configuration.\n * Provided for backward compatibility with existing code.\n *\n * @example\n * // Use default configuration\n * router.usePlugin(loggerPlugin);\n */\nexport const loggerPlugin = loggerPluginFactory();\n"]}
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 +1 @@
1
- {"inputs":{"src/constants.ts":{"bytes":283,"imports":[],"format":"esm"},"src/internal/console-groups.ts":{"bytes":1490,"imports":[],"format":"esm"},"src/internal/formatting.ts":{"bytes":1234,"imports":[],"format":"esm"},"src/internal/params-diff.ts":{"bytes":2534,"imports":[],"format":"esm"},"src/internal/performance-marks.ts":{"bytes":1720,"imports":[],"format":"esm"},"src/internal/timing.ts":{"bytes":1480,"imports":[],"format":"esm"},"src/plugin.ts":{"bytes":6520,"imports":[{"path":"src/constants.ts","kind":"import-statement","original":"./constants"},{"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/index.ts":{"bytes":266,"imports":[{"path":"src/plugin.ts","kind":"import-statement","original":"./plugin"}],"format":"esm"}},"outputs":{"dist/esm/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":21834},"dist/esm/index.mjs":{"imports":[],"exports":["loggerPlugin","loggerPluginFactory"],"entryPoint":"src/index.ts","inputs":{"src/constants.ts":{"bytesInOutput":143},"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":4237},"src/index.ts":{"bytesInOutput":0}},"bytes":8618}}}
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}}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@real-router/logger-plugin",
3
- "version": "0.2.39",
3
+ "version": "0.3.1",
4
4
  "type": "commonjs",
5
5
  "description": "Development logging plugin with transition tracking and performance metrics",
6
6
  "main": "./dist/cjs/index.js",
@@ -45,11 +45,12 @@
45
45
  "homepage": "https://github.com/greydragon888/real-router",
46
46
  "sideEffects": false,
47
47
  "dependencies": {
48
- "@real-router/core": "^0.35.0"
48
+ "@real-router/core": "^0.36.0"
49
49
  },
50
50
  "scripts": {
51
51
  "build": "tsup",
52
52
  "test": "vitest run",
53
+ "test:properties": "vitest run --config vitest.config.properties.mts",
53
54
  "type-check": "tsc --noEmit",
54
55
  "lint": "eslint --cache --ext .ts src/ tests/ --fix --max-warnings 0",
55
56
  "test:mutation": "stryker run",
package/src/constants.ts CHANGED
@@ -1,11 +1,15 @@
1
- // packages/logger-plugin/modules/constants.ts
1
+ // packages/logger-plugin/src/constants.ts
2
2
 
3
3
  import type { LoggerPluginConfig } from "./types";
4
4
 
5
+ export const LOGGER_CONTEXT = "logger-plugin";
6
+
7
+ export const ERROR_PREFIX = `[@real-router/${LOGGER_CONTEXT}]`;
8
+
5
9
  export const DEFAULT_CONFIG: Required<LoggerPluginConfig> = {
6
10
  level: "all",
7
11
  usePerformanceMarks: false,
8
12
  showParamsDiff: true,
9
13
  showTiming: true,
10
- context: "logger-plugin",
14
+ context: LOGGER_CONTEXT,
11
15
  };
package/src/factory.ts ADDED
@@ -0,0 +1,21 @@
1
+ // packages/logger-plugin/src/factory.ts
2
+
3
+ import { DEFAULT_CONFIG } from "./constants";
4
+ import { LoggerPlugin } from "./plugin";
5
+ import { validateOptions } from "./validation";
6
+
7
+ import type { LoggerPluginConfig } from "./types";
8
+ import type { PluginFactory } from "@real-router/core";
9
+
10
+ export function loggerPluginFactory(
11
+ options?: Partial<LoggerPluginConfig>,
12
+ ): PluginFactory {
13
+ validateOptions(options);
14
+
15
+ const config: Required<LoggerPluginConfig> = {
16
+ ...DEFAULT_CONFIG,
17
+ ...options,
18
+ };
19
+
20
+ return () => new LoggerPlugin(config).getPlugin();
21
+ }
package/src/index.ts CHANGED
@@ -1,9 +1,5 @@
1
- // packages/logger-plugin/modules/index.ts
1
+ // packages/logger-plugin/src/index.ts
2
2
 
3
- // Public API exports for real-router-logger-plugin
3
+ export { loggerPluginFactory } from "./factory";
4
4
 
5
- // Main plugin factory and instance
6
- export { loggerPluginFactory, loggerPlugin } from "./plugin";
7
-
8
- // Types
9
5
  export type { LoggerPluginConfig, LogLevel } from "./types";
@@ -1,4 +1,4 @@
1
- // packages/logger-plugin/modules/internal/console-groups.ts
1
+ // packages/logger-plugin/src/internal/console-groups.ts
2
2
 
3
3
  /**
4
4
  * Checks if console.group is supported in the current environment.
@@ -14,7 +14,7 @@ export const supportsConsoleGroups = (): boolean => {
14
14
  /**
15
15
  * Manager for handling console groups
16
16
  */
17
- interface GroupManager {
17
+ export interface GroupManager {
18
18
  /**
19
19
  * Opens a group if it's not already open
20
20
  */
@@ -1,4 +1,4 @@
1
- // packages/logger-plugin/modules/internal/formatting.ts
1
+ // packages/logger-plugin/src/internal/formatting.ts
2
2
 
3
3
  import type { State } from "@real-router/core";
4
4
 
@@ -1,4 +1,4 @@
1
- // packages/logger-plugin/modules/internal/params-diff.ts
1
+ // packages/logger-plugin/src/internal/params-diff.ts
2
2
 
3
3
  import type { Params } from "@real-router/core";
4
4
 
@@ -1,4 +1,4 @@
1
- // packages/logger-plugin/modules/internal/performance-marks.ts
1
+ // packages/logger-plugin/src/internal/performance-marks.ts
2
2
 
3
3
  /**
4
4
  * Checks if Performance API is supported in the current environment.
@@ -14,7 +14,7 @@ export const supportsPerformanceAPI = (): boolean => {
14
14
  /**
15
15
  * Performance tracker interface with mark and measure methods.
16
16
  */
17
- interface PerformanceTracker {
17
+ export interface PerformanceTracker {
18
18
  mark: (name: string) => void;
19
19
  measure: (measureName: string, startMark: string, endMark: string) => void;
20
20
  }
@@ -1,4 +1,4 @@
1
- // packages/logger-plugin/modules/internal/timing.ts
1
+ // packages/logger-plugin/src/internal/timing.ts
2
2
 
3
3
  /**
4
4
  * Function that returns high-resolution timestamp in milliseconds.
package/src/plugin.ts CHANGED
@@ -1,6 +1,5 @@
1
- // packages/logger-plugin/modules/plugin.ts
1
+ // packages/logger-plugin/src/plugin.ts
2
2
 
3
- import { DEFAULT_CONFIG } from "./constants";
4
3
  import {
5
4
  createGroupManager,
6
5
  supportsConsoleGroups,
@@ -14,229 +13,210 @@ import { getParamsDiff, logParamsDiff } from "./internal/params-diff";
14
13
  import { createPerformanceTracker } from "./internal/performance-marks";
15
14
  import { now } from "./internal/timing";
16
15
 
16
+ import type { GroupManager } from "./internal/console-groups";
17
+ import type { PerformanceTracker } from "./internal/performance-marks";
17
18
  import type { LoggerPluginConfig } from "./types";
18
- import type { PluginFactory, RouterError, State } from "@real-router/core";
19
-
20
- /**
21
- * Creates a logger-plugin for real-router.
22
- *
23
- * @param options - Plugin configuration options
24
- * @returns Plugin factory function for real-router
25
- *
26
- * @example
27
- * ```ts
28
- * import { loggerPluginFactory } from "@real-router/logger-plugin";
29
- *
30
- * // Use with default configuration
31
- * router.usePlugin(loggerPluginFactory());
32
- *
33
- * // Use with custom configuration
34
- * router.usePlugin(loggerPluginFactory({
35
- * level: 'errors', // only log errors
36
- * usePerformanceMarks: true, // enable Performance API
37
- * showTiming: false, // disable timing info
38
- * showParamsDiff: false, // disable params diff
39
- * context: 'my-router', // custom context name
40
- * }));
41
- * ```
42
- */
43
- export function loggerPluginFactory(
44
- options?: Partial<LoggerPluginConfig>,
45
- ): PluginFactory {
46
- // Merge options with defaults
47
- const config: Required<LoggerPluginConfig> = {
48
- ...DEFAULT_CONFIG,
49
- ...options,
50
- };
51
-
52
- // Pre-compute log level flags
53
- const logLifecycle = config.level === "all";
54
- const logTransition = config.level !== "none" && config.level !== "errors";
55
- const logWarning = logTransition;
56
- const logError = config.level !== "none";
57
-
58
- // Pre-compute feature flags
59
- const shouldLogParams = logTransition && config.showParamsDiff;
60
- const shouldShowTiming = config.showTiming;
61
-
62
- // Cached prefix
63
- const prefix = `[${config.context}]`;
64
-
65
- return () => {
66
- // Create helper managers
67
- const groups = createGroupManager(supportsConsoleGroups());
68
- const perf = createPerformanceTracker(
19
+ import type { Plugin, RouterError, State } from "@real-router/core";
20
+
21
+ export class LoggerPlugin {
22
+ readonly #logLifecycle: boolean;
23
+ readonly #logTransition: boolean;
24
+ readonly #logError: boolean;
25
+
26
+ readonly #shouldLogParams: boolean;
27
+ readonly #shouldShowTiming: boolean;
28
+ readonly #usePerf: boolean;
29
+
30
+ readonly #prefix: string;
31
+ readonly #context: string;
32
+
33
+ readonly #groups: GroupManager;
34
+ readonly #perf: PerformanceTracker;
35
+
36
+ // Transition state
37
+ #transitionStartTime: number | null = null;
38
+ #transitionLabel = "";
39
+ #startMarkName = "";
40
+
41
+ constructor(config: Required<LoggerPluginConfig>) {
42
+ this.#logLifecycle = config.level === "all";
43
+ this.#logTransition = config.level !== "none" && config.level !== "errors";
44
+ this.#logError = config.level !== "none";
45
+
46
+ this.#shouldLogParams = this.#logTransition && config.showParamsDiff;
47
+ this.#shouldShowTiming = config.showTiming;
48
+ this.#usePerf = config.usePerformanceMarks;
49
+
50
+ this.#prefix = `[${config.context}]`;
51
+ this.#context = config.context;
52
+
53
+ this.#groups = createGroupManager(supportsConsoleGroups());
54
+ this.#perf = createPerformanceTracker(
69
55
  config.usePerformanceMarks,
70
56
  config.context,
71
57
  );
58
+ }
72
59
 
73
- // Transition state
74
- let transitionStartTime: number | null = null;
75
- let transitionLabel = "";
76
- let startMarkName = "";
77
-
78
- /**
79
- * Logs parameter differences when navigating within the same route.
80
- */
81
- const logParamsIfNeeded = (toState: State, fromState?: State): void => {
82
- if (!shouldLogParams || !fromState) {
83
- return;
84
- }
85
-
86
- // Show diff only for the same route
87
- if (toState.name !== fromState.name) {
88
- return;
89
- }
90
-
91
- const diff = getParamsDiff(fromState.params, toState.params);
92
-
93
- if (diff) {
94
- logParamsDiff(diff, config.context);
95
- }
96
- };
97
-
98
- /**
99
- * Resets transition state. Must be called AFTER timing is read.
100
- */
101
- const resetTransitionState = (): void => {
102
- groups.close();
103
- transitionLabel = "";
104
- startMarkName = "";
105
- transitionStartTime = null;
106
- };
107
-
60
+ getPlugin(): Plugin {
108
61
  return {
109
- onStart() {
110
- perf.mark("router:start");
62
+ onStart: () => {
63
+ this.#perf.mark("router:start");
111
64
 
112
- if (logLifecycle) {
113
- console.log(`${prefix} Router started`);
65
+ if (this.#logLifecycle) {
66
+ console.log(`${this.#prefix} Router started`);
114
67
  }
115
68
  },
116
69
 
117
- onStop() {
118
- groups.close();
70
+ onStop: () => {
71
+ this.#groups.close();
119
72
 
120
- perf.mark("router:stop");
121
- perf.measure("router:lifetime", "router:start", "router:stop");
73
+ this.#perf.mark("router:stop");
74
+ this.#perf.measure("router:lifetime", "router:start", "router:stop");
122
75
 
123
- if (logLifecycle) {
124
- console.log(`${prefix} Router stopped`);
76
+ if (this.#logLifecycle) {
77
+ console.log(`${this.#prefix} Router stopped`);
125
78
  }
126
79
  },
127
80
 
128
- onTransitionStart(toState: State, fromState?: State) {
129
- groups.open("Router transition");
130
- transitionStartTime = now();
81
+ onTransitionStart: (toState: State, fromState?: State) => {
82
+ this.#groups.open("Router transition");
83
+ this.#transitionStartTime = this.#shouldShowTiming ? now() : null;
131
84
 
132
85
  const fromRoute = formatRouteName(fromState);
133
86
  const toRoute = formatRouteName(toState);
134
87
 
135
- transitionLabel = createTransitionLabel(fromRoute, toRoute);
136
- startMarkName = `router:transition-start:${transitionLabel}`;
137
-
138
- perf.mark(startMarkName);
88
+ if (this.#usePerf) {
89
+ this.#transitionLabel = createTransitionLabel(fromRoute, toRoute);
90
+ this.#startMarkName = `router:transition-start:${this.#transitionLabel}`;
91
+ this.#perf.mark(this.#startMarkName);
92
+ }
139
93
 
140
- if (logTransition) {
141
- console.log(`${prefix} Transition: ${fromRoute} → ${toRoute}`, {
94
+ if (this.#logTransition) {
95
+ console.log(`${this.#prefix} Transition: ${fromRoute} → ${toRoute}`, {
142
96
  from: fromState,
143
97
  to: toState,
144
98
  });
145
99
 
146
- logParamsIfNeeded(toState, fromState);
100
+ this.#logParamsIfNeeded(toState, fromState);
147
101
  }
148
102
  },
149
103
 
150
- onTransitionSuccess(toState: State, fromState?: State) {
151
- const label = transitionLabel;
152
- const endMark = `router:transition-end:${label}`;
153
-
154
- perf.mark(endMark);
155
- perf.measure(`router:transition:${label}`, startMarkName, endMark);
104
+ onTransitionSuccess: (toState: State, fromState?: State) => {
105
+ if (this.#usePerf) {
106
+ const label = this.#transitionLabel;
107
+ const endMark = `router:transition-end:${label}`;
108
+
109
+ this.#perf.mark(endMark);
110
+ this.#perf.measure(
111
+ `router:transition:${label}`,
112
+ this.#startMarkName,
113
+ endMark,
114
+ );
115
+ }
156
116
 
157
- if (logTransition) {
158
- const timing = shouldShowTiming
159
- ? formatTiming(transitionStartTime, now)
117
+ if (this.#logTransition) {
118
+ const timing = this.#shouldShowTiming
119
+ ? formatTiming(this.#transitionStartTime, now)
160
120
  : "";
161
121
 
162
- console.log(`${prefix} Transition success${timing}`, {
122
+ console.log(`${this.#prefix} Transition success${timing}`, {
163
123
  to: toState,
164
124
  from: fromState,
165
125
  });
166
126
  }
167
127
 
168
- resetTransitionState();
128
+ this.#resetTransitionState();
169
129
  },
170
130
 
171
- onTransitionCancel(toState: State, fromState?: State) {
172
- const label = transitionLabel;
173
- const cancelMark = `router:transition-cancel:${label}`;
174
-
175
- perf.mark(cancelMark);
176
- perf.measure(
177
- `router:transition-cancelled:${label}`,
178
- startMarkName,
179
- cancelMark,
180
- );
131
+ onTransitionCancel: (toState: State, fromState?: State) => {
132
+ if (this.#usePerf) {
133
+ const label = this.#transitionLabel;
134
+ const cancelMark = `router:transition-cancel:${label}`;
135
+
136
+ this.#perf.mark(cancelMark);
137
+ this.#perf.measure(
138
+ `router:transition-cancelled:${label}`,
139
+ this.#startMarkName,
140
+ cancelMark,
141
+ );
142
+ }
181
143
 
182
- if (logWarning) {
183
- const timing = shouldShowTiming
184
- ? formatTiming(transitionStartTime, now)
144
+ if (this.#logTransition) {
145
+ const timing = this.#shouldShowTiming
146
+ ? formatTiming(this.#transitionStartTime, now)
185
147
  : "";
186
148
 
187
- console.warn(`${prefix} Transition cancelled${timing}`, {
149
+ console.warn(`${this.#prefix} Transition cancelled${timing}`, {
188
150
  to: toState,
189
151
  from: fromState,
190
152
  });
191
153
  }
192
154
 
193
- resetTransitionState();
155
+ this.#resetTransitionState();
194
156
  },
195
157
 
196
- onTransitionError(
158
+ onTransitionError: (
197
159
  toState: State | undefined,
198
160
  fromState: State | undefined,
199
161
  err: RouterError,
200
- ) {
201
- const label = transitionLabel;
202
- const errorMark = `router:transition-error:${label}`;
203
-
204
- perf.mark(errorMark);
205
- perf.measure(
206
- `router:transition-failed:${label}`,
207
- startMarkName,
208
- errorMark,
209
- );
210
-
211
- if (logError) {
212
- const timing = shouldShowTiming
213
- ? formatTiming(transitionStartTime, now)
162
+ ) => {
163
+ if (this.#usePerf) {
164
+ const label = this.#transitionLabel;
165
+ const errorMark = `router:transition-error:${label}`;
166
+
167
+ this.#perf.mark(errorMark);
168
+ this.#perf.measure(
169
+ `router:transition-failed:${label}`,
170
+ this.#startMarkName,
171
+ errorMark,
172
+ );
173
+ }
174
+
175
+ if (this.#logError) {
176
+ const timing = this.#shouldShowTiming
177
+ ? formatTiming(this.#transitionStartTime, now)
214
178
  : "";
215
179
 
216
- console.error(`${prefix} Transition error: ${err.code}${timing}`, {
217
- error: err,
218
- stack: err.stack,
219
- to: toState,
220
- from: fromState,
221
- });
180
+ console.error(
181
+ `${this.#prefix} Transition error: ${err.code}${timing}`,
182
+ {
183
+ error: err,
184
+ stack: err.stack,
185
+ to: toState,
186
+ from: fromState,
187
+ },
188
+ );
222
189
  }
223
190
 
224
- resetTransitionState();
191
+ this.#resetTransitionState();
225
192
  },
226
193
 
227
- teardown() {
228
- resetTransitionState();
194
+ teardown: () => {
195
+ this.#resetTransitionState();
229
196
  },
230
197
  };
231
- };
198
+ }
199
+
200
+ #logParamsIfNeeded(toState: State, fromState?: State): void {
201
+ if (!this.#shouldLogParams || !fromState) {
202
+ return;
203
+ }
204
+
205
+ if (toState.name !== fromState.name) {
206
+ return;
207
+ }
208
+
209
+ const diff = getParamsDiff(fromState.params, toState.params);
210
+
211
+ if (diff) {
212
+ logParamsDiff(diff, this.#context);
213
+ }
214
+ }
215
+
216
+ #resetTransitionState(): void {
217
+ this.#groups.close();
218
+ this.#transitionLabel = "";
219
+ this.#startMarkName = "";
220
+ this.#transitionStartTime = null;
221
+ }
232
222
  }
233
-
234
- /**
235
- * Default logger-plugin instance with standard configuration.
236
- * Provided for backward compatibility with existing code.
237
- *
238
- * @example
239
- * // Use default configuration
240
- * router.usePlugin(loggerPlugin);
241
- */
242
- export const loggerPlugin = loggerPluginFactory();
package/src/types.ts CHANGED
@@ -1,4 +1,4 @@
1
- // packages/logger-plugin/modules/types.ts
1
+ // packages/logger-plugin/src/types.ts
2
2
 
3
3
  /**
4
4
  * Logging level for router events.
@@ -53,7 +53,7 @@ export interface LoggerPluginConfig {
53
53
  * Only applies when navigating within the same route.
54
54
  * Helps identify which parameters changed during navigation.
55
55
  *
56
- * @default false
56
+ * @default true
57
57
  */
58
58
  showParamsDiff?: boolean;
59
59
 
@@ -0,0 +1,61 @@
1
+ // packages/logger-plugin/src/validation.ts
2
+
3
+ import { ERROR_PREFIX } from "./constants";
4
+
5
+ import type { LoggerPluginConfig } from "./types";
6
+
7
+ const VALID_LEVELS = new Set(["all", "transitions", "errors", "none"]);
8
+
9
+ export function validateOptions(options?: Partial<LoggerPluginConfig>): void {
10
+ if (options === undefined) {
11
+ return;
12
+ }
13
+
14
+ // Runtime defense: typeof null === "object", so check identity first.
15
+ // TypeScript excludes null from the parameter type, but JS callers may pass it.
16
+ if (options === (null as never) || typeof options !== "object") {
17
+ throw new TypeError(`${ERROR_PREFIX} Options must be an object`);
18
+ }
19
+
20
+ if (options.level !== undefined && !VALID_LEVELS.has(options.level)) {
21
+ throw new TypeError(
22
+ `${ERROR_PREFIX} Invalid level: "${options.level}". Expected: ${[...VALID_LEVELS].join(", ")}`,
23
+ );
24
+ }
25
+
26
+ if (
27
+ options.context !== undefined &&
28
+ (typeof options.context !== "string" || options.context.length === 0)
29
+ ) {
30
+ throw new TypeError(
31
+ `${ERROR_PREFIX} Option "context" must be a non-empty string`,
32
+ );
33
+ }
34
+
35
+ if (
36
+ options.showTiming !== undefined &&
37
+ typeof options.showTiming !== "boolean"
38
+ ) {
39
+ throw new TypeError(
40
+ `${ERROR_PREFIX} Option "showTiming" must be a boolean`,
41
+ );
42
+ }
43
+
44
+ if (
45
+ options.showParamsDiff !== undefined &&
46
+ typeof options.showParamsDiff !== "boolean"
47
+ ) {
48
+ throw new TypeError(
49
+ `${ERROR_PREFIX} Option "showParamsDiff" must be a boolean`,
50
+ );
51
+ }
52
+
53
+ if (
54
+ options.usePerformanceMarks !== undefined &&
55
+ typeof options.usePerformanceMarks !== "boolean"
56
+ ) {
57
+ throw new TypeError(
58
+ `${ERROR_PREFIX} Option "usePerformanceMarks" must be a boolean`,
59
+ );
60
+ }
61
+ }