@real-router/logger-plugin 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
4
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue.svg)](https://www.typescriptlang.org/)
5
5
 
6
- A plugin for logging router events to the console. Provides transition timing display, parameter diff tracking, Performance API integration, and log grouping.
6
+ Console logging plugin for Real-Router. Provides transition timing, parameter diff tracking, Performance API integration, and log grouping.
7
7
 
8
8
  ## Installation
9
9
 
@@ -21,12 +21,12 @@ bun add @real-router/logger-plugin
21
21
 
22
22
  ```typescript
23
23
  import { createRouter } from "@real-router/core";
24
- import { loggerPlugin } from "@real-router/logger-plugin";
24
+ import { loggerPluginFactory } from "@real-router/logger-plugin";
25
25
 
26
26
  const router = createRouter(routes);
27
27
 
28
28
  // Use with default settings
29
- router.usePlugin(loggerPlugin);
29
+ router.usePlugin(loggerPluginFactory());
30
30
 
31
31
  router.start();
32
32
  ```
@@ -34,214 +34,124 @@ router.start();
34
34
  **Console output:**
35
35
 
36
36
  ```
37
- Router started
37
+ [logger-plugin] Router started
38
38
  ▼ Router transition
39
- Transition: home → users (1.23ms)
40
- Transition success (1.23ms)
39
+ [logger-plugin] Transition: home → users {from: {...}, to: {...}}
40
+ [logger-plugin] Transition success (1.23ms) {to: {...}, from: {...}}
41
41
  ```
42
42
 
43
- **Fast transitions (<0.1ms) display in microseconds:**
44
-
45
- ```
46
- Transition success (27.29μs)
47
- ```
43
+ ---
48
44
 
49
45
  ## API
50
46
 
51
- ### `loggerPlugin`
52
-
53
- Ready-to-use plugin instance with default settings.
54
-
55
- ```typescript
56
- import { loggerPlugin } from "@real-router/logger-plugin";
57
-
58
- router.usePlugin(loggerPlugin);
59
- ```
47
+ ### `loggerPluginFactory(options?)`
60
48
 
61
- ### `loggerPluginFactory()`
62
-
63
- Factory for creating a new plugin instance.
49
+ Factory for creating a plugin instance with optional configuration.
64
50
 
65
51
  ```typescript
66
52
  import { loggerPluginFactory } from "@real-router/logger-plugin";
67
53
 
54
+ // Default configuration
68
55
  router.usePlugin(loggerPluginFactory());
69
- ```
70
-
71
- ## Default Configuration
72
56
 
73
- The plugin uses the following default configuration:
74
-
75
- ```typescript
76
- interface LoggerPluginConfig {
77
- level: "all" | "transitions" | "errors" | "none"; // default: "all"
78
- showTiming: boolean; // default: true
79
- showParamsDiff: boolean; // default: true
80
- usePerformanceMarks: boolean; // default: false
81
- context: string; // default: "real-router-logger-plugin"
82
- }
57
+ // With custom options
58
+ router.usePlugin(loggerPluginFactory({
59
+ level: "errors",
60
+ showTiming: false,
61
+ }));
83
62
  ```
84
63
 
85
- ### `level`
86
-
87
- Event logging level.
88
-
89
- - `'all'` **(default)** - logs all events (router start/stop + transitions)
90
- - `'transitions'` - only transition events (start/success/cancel/error)
91
- - `'errors'` - only transition errors
92
- - `'none'` - disables all logs
93
-
94
- ### `showTiming`
95
-
96
- Display transition execution time with adaptive units.
97
-
98
- - `true` **(default)** - show timing (μs for fast transitions <0.1ms, ms otherwise)
99
- - `false` - hide timing
100
-
101
- **Output examples:**
102
-
103
- ```
104
- Transition success (15ms) // normal timing
105
- Transition success (27.29μs) // fast transitions
106
- ```
107
-
108
- ### `showParamsDiff`
109
-
110
- Show differences in route parameters when navigating within the same route.
64
+ ### `loggerPlugin`
111
65
 
112
- - `true` **(default)** - show changed, added, and removed parameters
113
- - `false` - don't show parameter changes
66
+ Ready-to-use plugin instance with default settings. Provided for backward compatibility.
114
67
 
115
- **Example output:**
68
+ ```typescript
69
+ import { loggerPlugin } from "@real-router/logger-plugin";
116
70
 
71
+ router.usePlugin(loggerPlugin);
117
72
  ```
118
- ▼ Router transition
119
- Transition: users.view → users.view
120
- Changed: { id: "123" → "456" }, Added: {"sort":"name"}
121
- Transition success (2.15ms)
122
- ```
123
-
124
- **Diff types displayed:**
125
73
 
126
- - **Changed** - parameters with different values
127
- - **Added** - new parameters in target state
128
- - **Removed** - parameters present in source but not in target
74
+ ---
129
75
 
130
- **When diff is shown:**
76
+ ## Configuration
131
77
 
132
- - Only when navigating within the same route (e.g., `users.view` → `users.view`)
133
- - Only when parameters actually changed
134
- - Not shown when navigating between different routes
135
- - Not shown when parameters are identical
78
+ | Option | Type | Default | Description |
79
+ | --------------------- | ---------- | ----------------- | ---------------------------------------------------- |
80
+ | `level` | `LogLevel` | `"all"` | `"all"` \| `"transitions"` \| `"errors"` \| `"none"` |
81
+ | `showTiming` | `boolean` | `true` | Show transition execution time (μs/ms) |
82
+ | `showParamsDiff` | `boolean` | `true` | Show param changes within same route |
83
+ | `usePerformanceMarks` | `boolean` | `false` | Create Performance API marks for DevTools |
84
+ | `context` | `string` | `"logger-plugin"` | Log prefix for multiple routers |
136
85
 
137
- ### `usePerformanceMarks`
86
+ ### Configuration Examples
138
87
 
139
- Use Performance API to create marks and measures. Enables integration with browser DevTools Performance tab.
140
-
141
- - `false` **(default)** - disabled
142
- - `true` - create performance marks and measures
143
-
144
- **Created marks:**
145
-
146
- - `router:transition-start:{from}→{to}`
147
- - `router:transition-end:{from}→{to}` (success)
148
- - `router:transition-cancel:{from}→{to}` (cancelled)
149
- - `router:transition-error:{from}→{to}` (error)
150
-
151
- **Created measures:**
152
-
153
- - `router:transition:{from}→{to}` (success)
154
- - `router:transition-cancelled:{from}→{to}` (cancelled)
155
- - `router:transition-failed:{from}→{to}` (error)
156
-
157
- ### `context`
158
-
159
- Context name for logs. Useful when working with multiple routers.
88
+ ```typescript
89
+ // With custom context for multiple routers
90
+ router.usePlugin(loggerPluginFactory({
91
+ context: "main-router",
92
+ }));
160
93
 
161
- - **Default:** `'logger-plugin'`
94
+ // Performance profiling enabled
95
+ router.usePlugin(loggerPluginFactory({
96
+ usePerformanceMarks: true,
97
+ showTiming: true,
98
+ }));
162
99
 
163
- **Example output:**
100
+ // Errors only (for production-like environments)
101
+ router.usePlugin(loggerPluginFactory({
102
+ level: "errors",
103
+ showTiming: false,
104
+ }));
164
105
 
165
- ```
166
- [logger-plugin] Transition: dashboard → users
106
+ // Minimal output
107
+ router.usePlugin(loggerPluginFactory({
108
+ level: "transitions",
109
+ showParamsDiff: false,
110
+ showTiming: false,
111
+ }));
167
112
  ```
168
113
 
169
- ## Logged Events
114
+ See [Wiki](https://github.com/greydragon888/real-router/wiki/logger-plugin#3-configuration-options) for detailed descriptions.
170
115
 
171
- ### Router Lifecycle
116
+ ---
172
117
 
173
- **`onStart`** - called when router starts
118
+ ## Features
174
119
 
175
- ```
176
- Router started
177
- ```
178
-
179
- **`onStop`** - called when router stops
120
+ ### Timing Display
180
121
 
181
122
  ```
182
- Router stopped
123
+ [logger-plugin] Transition success (15ms) // normal
124
+ [logger-plugin] Transition success (27.29μs) // fast (<0.1ms)
183
125
  ```
184
126
 
185
- ### Transition Events
127
+ ### Parameter Diff
186
128
 
187
- **`onTransitionStart`** - transition begins
129
+ When navigating within the same route:
188
130
 
189
131
  ```
190
132
  ▼ Router transition
191
- Transition: home → users
192
- ```
193
-
194
- **`onTransitionSuccess`** - transition completed successfully
195
-
196
- ```
197
- Transition success (24ms)
198
- ```
199
-
200
- **`onTransitionCancel`** - transition cancelled
201
-
202
- ```
203
- Transition cancelled (12ms)
204
- ```
205
-
206
- **`onTransitionError`** - transition error
207
-
133
+ [logger-plugin] Transition: users.view → users.view {from: {...}, to: {...}}
134
+ [logger-plugin] Changed: { id: "123" → "456" }, Added: {"sort":"name"}
135
+ [logger-plugin] Transition success (2.15ms) {to: {...}, from: {...}}
208
136
  ```
209
- Transition error: ROUTE_NOT_FOUND (8ms)
210
- ```
211
-
212
- ## Log Grouping
213
137
 
214
- Transition events are automatically grouped in the console for better readability:
138
+ ### Performance API
215
139
 
216
- ```
217
- ▼ Router transition
218
- Transition: users → users.view
219
- [middleware logs...]
220
- [guard logs...]
221
- Transition success (45ms)
222
- ```
140
+ With `usePerformanceMarks: true`, creates marks visible in DevTools Performance tab:
223
141
 
224
- This helps organize logs when working with complex transitions, middleware, and guards.
142
+ - `router:transition-start:{from}→{to}`
143
+ - `router:transition-end:{from}→{to}`
144
+ - `router:transition:{from}→{to}` (measure)
225
145
 
226
- ## TypeScript
146
+ See [Wiki](https://github.com/greydragon888/real-router/wiki/logger-plugin#10-performance-marks-and-measures) for full list.
227
147
 
228
- The plugin is fully typed:
148
+ ---
229
149
 
230
- ```typescript
231
- import {
232
- loggerPlugin,
233
- loggerPluginFactory,
234
- type LoggerPluginConfig,
235
- type LogLevel,
236
- } from "@real-router/logger-plugin";
237
- ```
150
+ ## SSR Support
238
151
 
239
- ## Server-Side Rendering
240
-
241
- For high-precision timing in Node.js, polyfill `performance` globally:
152
+ For high-precision timing in Node.js:
242
153
 
243
154
  ```typescript
244
- // server.ts (Node.js entry point)
245
155
  import { performance } from "perf_hooks";
246
156
 
247
157
  if (typeof globalThis.performance === "undefined") {
@@ -249,10 +159,22 @@ if (typeof globalThis.performance === "undefined") {
249
159
  }
250
160
  ```
251
161
 
162
+ ---
163
+
164
+ ## Documentation
165
+
166
+ Full documentation on [Wiki](https://github.com/greydragon888/real-router/wiki/logger-plugin):
167
+
168
+ - [Configuration Options](https://github.com/greydragon888/real-router/wiki/logger-plugin#3-configuration-options)
169
+ - [Lifecycle Hooks](https://github.com/greydragon888/real-router/wiki/logger-plugin#4-lifecycle-hooks)
170
+ - [Performance Marks](https://github.com/greydragon888/real-router/wiki/logger-plugin#10-performance-marks-and-measures)
171
+ - [Migration from router5](https://github.com/greydragon888/real-router/wiki/logger-plugin#13-migration-from-router5)
172
+
173
+ ---
174
+
252
175
  ## Related Packages
253
176
 
254
177
  - [@real-router/core](https://www.npmjs.com/package/@real-router/core) — Core router
255
- - [@real-router/react](https://www.npmjs.com/package/@real-router/react) — React integration
256
178
  - [@real-router/browser-plugin](https://www.npmjs.com/package/@real-router/browser-plugin) — Browser history
257
179
 
258
180
  ## License
@@ -1,52 +1,12 @@
1
1
  import { PluginFactory } from '@real-router/core';
2
2
 
3
- /**
4
- * Creates a logger plugin for real-router.
5
- *
6
- * Configuration is managed through the logger singleton.
7
- * Use `logger.configure()` to customize logging behavior before starting the router.
8
- *
9
- * @returns Plugin factory function for real-router
10
- *
11
- * @example
12
- * ```ts
13
- * import { logger } from "logger";
14
- * import { loggerPluginFactory } from "real-router-logger-plugin";
15
- *
16
- * // Configure logger before using the plugin
17
- * logger.configure({
18
- * level: "transitions",
19
- * showTiming: true,
20
- * context: "MyApp",
21
- * });
22
- *
23
- * router.usePlugin(loggerPluginFactory());
24
- * ```
25
- *
26
- * @example
27
- * ```ts
28
- * // Use with default configuration
29
- * router.usePlugin(loggerPluginFactory());
30
- * ```
31
- */
32
- declare function loggerPluginFactory(): PluginFactory;
33
- /**
34
- * Default logger plugin instance with standard configuration.
35
- * Provided for backward compatibility with existing code.
36
- *
37
- * @example
38
- * // Use default configuration
39
- * router.usePlugin(loggerPlugin);
40
- */
41
- declare const loggerPlugin: PluginFactory;
42
-
43
3
  /**
44
4
  * Logging level for router events.
45
5
  * Controls which events are logged to the console.
46
6
  */
47
7
  type LogLevel = "all" | "transitions" | "errors" | "none";
48
8
  /**
49
- * Configuration options for the logger plugin.
9
+ * Configuration options for the logger-plugin.
50
10
  */
51
11
  interface LoggerPluginConfig {
52
12
  /**
@@ -94,7 +54,7 @@ interface LoggerPluginConfig {
94
54
  */
95
55
  showParamsDiff?: boolean;
96
56
  /**
97
- * Custom context name for logger.
57
+ * Custom context name for console.
98
58
  * Useful when running multiple routers.
99
59
  *
100
60
  * @default 'logger-plugin'
@@ -102,4 +62,38 @@ interface LoggerPluginConfig {
102
62
  context?: string;
103
63
  }
104
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
+ 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
+
105
99
  export { type LogLevel, type LoggerPluginConfig, loggerPlugin, loggerPluginFactory };
package/dist/cjs/index.js CHANGED
@@ -1 +1 @@
1
- var o=require("logger"),n={context:"logger-plugin"},e=o=>o?.name??"(none)",t=(o,n)=>{if(null===o)return"";const e=n()-o;return!Number.isFinite(e)||e<0?" (?)":e<.1?` (${(1e3*e).toFixed(2)}μs)`:` (${e.toFixed(2)}ms)`},r=0,s=0,c="undefined"!=typeof performance&&"function"==typeof performance.now?()=>performance.now():()=>{const o=Date.now();return o<r&&(s+=r-o),r=o,o+s},i=()=>c();function l(){return()=>{const r=n,s=(o=>{let n=!1;return{open(e){o&&!n&&(console.group(e),n=!0)},close(){o&&n&&(console.groupEnd(),n=!1)},isOpen:()=>n}})("undefined"!=typeof console&&"function"==typeof console.group&&"function"==typeof console.groupEnd);let c=null;return{onStart(){o.logger.log(r.context,"Router started")},onStop(){s.close(),o.logger.log(r.context,"Router stopped")},onTransitionStart(n,t){s.open("Router transition"),c=i();const l=e(t),g=e(n);o.logger.log(r.context,`Transition: ${l} → ${g}`,{from:t,to:n}),((n,e)=>{if(!e)return;if(n.name!==e.name)return;const t=((o,n)=>{const e={},t={},r={};let s=!1;for(const t in o)t in n?o[t]!==n[t]&&(e[t]={from:o[t],to:n[t]},s=!0):(r[t]=o[t],s=!0);for(const e in n)e in o||(t[e]=n[e],s=!0);return s?{changed:e,added:t,removed:r}:null})(e.params,n.params);t&&((n,e)=>{const t=[],r=Object.entries(n.changed);if(r.length>0){const o=[];for(const[n,{from:e,to:t}]of r)o.push(`${n}: ${JSON.stringify(e)} → ${JSON.stringify(t)}`);t.push(`Changed: { ${o.join(", ")} }`)}Object.entries(n.added).length>0&&t.push(`Added: ${JSON.stringify(n.added)}`),Object.entries(n.removed).length>0&&t.push(`Removed: ${JSON.stringify(n.removed)}`),o.logger.log(e,` ${t.join(", ")}`)})(t,r.context)})(n,t)},onTransitionSuccess(n,l){e(l),e(n);const g=t(c,i);o.logger.log(r.context,`Transition success${g}`,{to:n,from:l}),s.close(),c=null},onTransitionCancel(n,l){e(l),e(n);const g=t(c,i);o.logger.warn(r.context,`Transition cancelled${g}`,{to:n,from:l}),s.close(),c=null},onTransitionError(n,l,g){e(l),e(n);const u=t(c,i);o.logger.error(r.context,`Transition error: ${g.code}${u}`,{error:g,stack:g.stack,to:n,from:l}),s.close(),c=null},teardown(){s.close(),c=null}}}}var g=l();exports.loggerPlugin=g,exports.loggerPluginFactory=l;//# sourceMappingURL=index.js.map
1
+ var e={level:"all",usePerformanceMarks:!1,showParamsDiff:!0,showTiming:!0,context:"logger-plugin"},r=e=>e?.name??"(none)",o=(e,r)=>`${e}→${r}`,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},i=()=>s(),a=(e,r)=>"none"!==e&&("errors"===e?"error"===r:"transitions"!==e||"transition"===r||"warning"===r||"error"===r);function c(n){const t={...e,...n};return()=>{const e=(e=>{let r=!1;return{open(o){e&&!r&&(console.group(o),r=!0)},close(){e&&r&&(console.groupEnd(),r=!1)},isOpen:()=>r}})("undefined"!=typeof console&&"function"==typeof console.group&&"function"==typeof console.groupEnd),n=((e,r)=>{const o=e&&"undefined"!=typeof performance&&"function"==typeof performance.mark&&"function"==typeof performance.measure;return{mark(e){o&&performance.mark(e)},measure(e,n,t){if(o)try{performance.measure(e,n,t)}catch(o){console.warn(`[${r}] Failed to create performance measure: ${e}`,o)}}}})(t.usePerformanceMarks,t.context);let s=null;const c=()=>t.showTiming?(e=>{if(null===e)return"";const r=i()-e;return!Number.isFinite(r)||r<0?" (?)":r<.1?` (${(1e3*r).toFixed(2)}μs)`:` (${r.toFixed(2)}ms)`})(s):"";return{onStart(){n.mark("router:start"),a(t.level,"lifecycle")&&console.log(`[${t.context}] Router started`)},onStop(){e.close(),n.mark("router:stop"),n.measure("router:lifetime","router:start","router:stop"),a(t.level,"lifecycle")&&console.log(`[${t.context}] Router stopped`)},onTransitionStart(c,l){e.open("Router transition"),s=i();const u=r(l),f=r(c),m=o(u,f);n.mark(`router:transition-start:${m}`),a(t.level,"transition")&&(console.log(`[${t.context}] Transition: ${u} → ${f}`,{from:l,to:c}),((e,r)=>{if(!t.showParamsDiff||!r)return;if(e.name!==r.name)return;const o=((e,r)=>{const o={},n={},t={};let s=!1;for(const n in e)n in r?e[n]!==r[n]&&(o[n]={from:e[n],to:r[n]},s=!0):(t[n]=e[n],s=!0);for(const o in r)o in e||(n[o]=r[o],s=!0);return s?{changed:o,added:n,removed:t}:null})(r.params,e.params);o&&((e,r)=>{const o=[],n=Object.entries(e.changed);if(n.length>0){const e=[];for(const[r,{from:o,to:t}]of n)e.push(`${r}: ${JSON.stringify(o)} → ${JSON.stringify(t)}`);o.push(`Changed: { ${e.join(", ")} }`)}Object.entries(e.added).length>0&&o.push(`Added: ${JSON.stringify(e.added)}`),Object.entries(e.removed).length>0&&o.push(`Removed: ${JSON.stringify(e.removed)}`),console.log(`[${r}] ${o.join(", ")}`)})(o,t.context)})(c,l))},onTransitionSuccess(i,l){const u=r(l),f=r(i),m=o(u,f);if(n.mark(`router:transition-end:${m}`),n.measure(`router:transition:${m}`,`router:transition-start:${m}`,`router:transition-end:${m}`),a(t.level,"transition")){const e=c();console.log(`[${t.context}] Transition success${e}`,{to:i,from:l})}e.close(),s=null},onTransitionCancel(i,l){const u=r(l),f=r(i),m=o(u,f);if(n.mark(`router:transition-cancel:${m}`),n.measure(`router:transition-cancelled:${m}`,`router:transition-start:${m}`,`router:transition-cancel:${m}`),a(t.level,"warning")){const e=c();console.warn(`[${t.context}] Transition cancelled${e}`,{to:i,from:l})}e.close(),s=null},onTransitionError(i,l,u){const f=r(l),m=r(i),d=o(f,m);if(n.mark(`router:transition-error:${d}`),n.measure(`router:transition-failed:${d}`,`router:transition-start:${d}`,`router:transition-error:${d}`),a(t.level,"error")){const e=c();console.error(`[${t.context}] Transition error: ${u.code}${e}`,{error:u,stack:u.stack,to:i,from:l})}e.close(),s=null},teardown(){e.close(),s=null}}}}var l=c();exports.loggerPlugin=l,exports.loggerPluginFactory=c;//# 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/timing.ts","../../src/plugin.ts"],"names":["now","logger"],"mappings":";;;AAIO,IAAM,cAAA,GAA+C;AAAA,EAK1D,OAAA,EAAS;AACX,CAAA;;;ACLO,IAAM,wBAAwB,MAAe;AAClD,EAAA,OACE,OAAO,YAAY,WAAA,IACnB,OAAO,QAAQ,KAAA,KAAU,UAAA,IACzB,OAAO,OAAA,CAAQ,QAAA,KAAa,UAAA;AAEhC,CAAA;AA2BO,IAAM,kBAAA,GAAqB,CAAC,OAAA,KAAmC;AACpE,EAAA,IAAI,QAAA,GAAW,KAAA;AAEf,EAAA,OAAO;AAAA;AAAA;AAAA;AAAA,IAIL,KAAK,KAAA,EAAqB;AACxB,MAAA,IAAI,CAAC,WAAW,QAAA,EAAU;AACxB,QAAA;AAAA,MACF;AAEA,MAAA,OAAA,CAAQ,MAAM,KAAK,CAAA;AACnB,MAAA,QAAA,GAAW,IAAA;AAAA,IACb,CAAA;AAAA;AAAA;AAAA;AAAA,IAKA,KAAA,GAAc;AACZ,MAAA,IAAI,CAAC,OAAA,IAAW,CAAC,QAAA,EAAU;AACzB,QAAA;AAAA,MACF;AAEA,MAAA,OAAA,CAAQ,QAAA,EAAS;AACjB,MAAA,QAAA,GAAW,KAAA;AAAA,IACb,CAAA;AAAA;AAAA;AAAA;AAAA,IAKA,MAAA,GAAkB;AAChB,MAAA,OAAO,QAAA;AAAA,IACT;AAAA,GACF;AACF,CAAA;;;ACjEO,IAAM,eAAA,GAAkB,CAAC,KAAA,KAA0B;AACxD,EAAA,OAAO,OAAO,IAAA,IAAQ,QAAA;AACxB,CAAA;AAYO,IAAM,YAAA,GAAe,CAC1B,SAAA,EACAA,IAAAA,KACW;AACX,EAAA,IAAI,cAAc,IAAA,EAAM;AACtB,IAAA,OAAO,EAAA;AAAA,EACT;AAEA,EAAA,MAAM,UAAA,GAAaA,MAAI,GAAI,SAAA;AAE3B,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,UAAU,CAAA,IAAK,aAAa,CAAA,EAAG;AAClD,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,IAAI,aAAa,GAAA,EAAK;AACpB,IAAA,MAAM,WAAA,GAAA,CAAe,UAAA,GAAa,GAAA,EAAM,OAAA,CAAQ,CAAC,CAAA;AAEjD,IAAA,OAAO,KAAK,WAAW,CAAA,QAAA,CAAA;AAAA,EACzB,CAAA,MAAO;AACL,IAAA,MAAM,QAAA,GAAW,UAAA,CAAW,OAAA,CAAQ,CAAC,CAAA;AAErC,IAAA,OAAO,KAAK,QAAQ,CAAA,GAAA,CAAA;AAAA,EACtB;AACF,CAAA;ACzBO,IAAM,aAAA,GAAgB,CAC3B,UAAA,EACA,QAAA,KACsB;AACtB,EAAA,MAAM,UAAiC,EAAC;AACxC,EAAA,MAAM,QAA6B,EAAC;AACpC,EAAA,MAAM,UAAiC,EAAC;AAMxC,EAAA,IAAI,UAAA,GAAa,KAAA;AAGjB,EAAA,KAAA,MAAW,OAAO,UAAA,EAAY;AAC5B,IAAA,IAAI,EAAE,OAAO,QAAA,CAAA,EAAW;AACtB,MAAA,OAAA,CAAQ,GAAG,CAAA,GAAI,UAAA,CAAW,GAAG,CAAA;AAC7B,MAAA,UAAA,GAAa,IAAA;AAAA,IACf,WAAW,UAAA,CAAW,GAAG,CAAA,KAAM,QAAA,CAAS,GAAG,CAAA,EAAG;AAC5C,MAAA,OAAA,CAAQ,GAAG,CAAA,GAAI,EAAE,IAAA,EAAM,UAAA,CAAW,GAAG,CAAA,EAAG,EAAA,EAAI,QAAA,CAAS,GAAG,CAAA,EAAE;AAC1D,MAAA,UAAA,GAAa,IAAA;AAAA,IACf;AAAA,EACF;AAGA,EAAA,KAAA,MAAW,OAAO,QAAA,EAAU;AAC1B,IAAA,IAAI,EAAE,OAAO,UAAA,CAAA,EAAa;AACxB,MAAA,KAAA,CAAM,GAAG,CAAA,GAAI,QAAA,CAAS,GAAG,CAAA;AACzB,MAAA,UAAA,GAAa,IAAA;AAAA,IACf;AAAA,EACF;AAGA,EAAA,IAAI,CAAC,UAAA,EAAY;AACf,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,OAAA,EAAQ;AACnC,CAAA;AAQO,IAAM,aAAA,GAAgB,CAAC,IAAA,EAAkB,OAAA,KAA0B;AACxE,EAAA,MAAM,QAAkB,EAAC;AAGzB,EAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAA;AAElD,EAAA,IAAI,cAAA,CAAe,SAAS,CAAA,EAAG;AAC7B,IAAA,MAAM,QAAkB,EAAC;AAEzB,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,EAAE,MAAM,EAAA,EAAI,KAAK,cAAA,EAAgB;AAChD,MAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAG,GAAG,CAAA,EAAA,EAAK,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA,QAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,CAAC,CAAA,CAAE,CAAA;AAAA,IACtE;AAEA,IAAA,KAAA,CAAM,KAAK,CAAA,WAAA,EAAc,KAAA,CAAM,IAAA,CAAK,IAAI,CAAC,CAAA,EAAA,CAAI,CAAA;AAAA,EAC/C;AAEA,EAAA,MAAM,YAAA,GAAe,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA;AAE9C,EAAA,IAAI,YAAA,CAAa,SAAS,CAAA,EAAG;AAC3B,IAAA,KAAA,CAAM,KAAK,CAAA,OAAA,EAAU,IAAA,CAAK,UAAU,IAAA,CAAK,KAAK,CAAC,CAAA,CAAE,CAAA;AAAA,EACnD;AAEA,EAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAA;AAElD,EAAA,IAAI,cAAA,CAAe,SAAS,CAAA,EAAG;AAC7B,IAAA,KAAA,CAAM,KAAK,CAAA,SAAA,EAAY,IAAA,CAAK,UAAU,IAAA,CAAK,OAAO,CAAC,CAAA,CAAE,CAAA;AAAA,EACvD;AAEA,EAAAC,aAAA,CAAO,IAAI,OAAA,EAAS,CAAA,EAAA,EAAK,MAAM,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAC7C,CAAA;;;ACtFA,IAAI,aAAA,GAAgB,CAAA;AACpB,IAAI,UAAA,GAAa,CAAA;AAOjB,SAAS,sBAAA,GAAuC;AAE9C,EAAA,OAAO,MAAc;AACnB,IAAA,MAAM,OAAA,GAAkB,KAAK,GAAA,EAAI;AAEjC,IAAA,IAAI,UAAU,aAAA,EAAe;AAC3B,MAAA,UAAA,IAAc,aAAA,GAAgB,OAAA;AAAA,IAChC;AAEA,IAAA,aAAA,GAAgB,OAAA;AAEhB,IAAA,OAAO,OAAA,GAAU,UAAA;AAAA,EACnB,CAAA;AACF;AAOA,IAAM,KAAA,GACJ,OAAO,WAAA,KAAgB,WAAA,IAAe,OAAO,WAAA,CAAY,GAAA,KAAQ,UAAA,GAC7D,MAAc,WAAA,CAAY,GAAA,EAAI,GAC9B,sBAAA,EAAuB;AAUtB,IAAM,GAAA,GAAM,MAAc,KAAA,EAAM;;;ACFhC,SAAS,mBAAA,GAAqC;AAEnD,EAAA,OAAO,MAAM;AACX,IAAA,MAAM,MAAA,GAAS,cAAA;AAGf,IAAA,MAAM,MAAA,GAAS,kBAAA,CAAmB,qBAAA,EAAuB,CAAA;AAOzD,IAAA,IAAI,mBAAA,GAAqC,IAAA;AAKzC,IAAA,MAAM,iBAAA,GAAoB,CAAC,OAAA,EAAgB,SAAA,KAA4B;AACrE,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA;AAAA,MACF;AAGA,MAAA,IAAI,OAAA,CAAQ,IAAA,KAAS,SAAA,CAAU,IAAA,EAAM;AACnC,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,IAAA,GAAO,aAAA,CAAc,SAAA,CAAU,MAAA,EAAQ,QAAQ,MAAM,CAAA;AAE3D,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,aAAA,CAAc,IAAA,EAAM,OAAO,OAAO,CAAA;AAAA,MACpC;AAAA,IACF,CAAA;AAEA,IAAA,OAAO;AAAA,MACL,OAAA,GAAU;AAER,QAAAA,aAAAA,CAAO,GAAA,CAAI,MAAA,CAAO,OAAA,EAAS,gBAAgB,CAAA;AAAA,MAC7C,CAAA;AAAA,MAEA,MAAA,GAAS;AACP,QAAA,MAAA,CAAO,KAAA,EAAM;AAGb,QAAAA,aAAAA,CAAO,GAAA,CAAI,MAAA,CAAO,OAAA,EAAS,gBAAgB,CAAA;AAAA,MAC7C,CAAA;AAAA,MAEA,iBAAA,CAAkB,SAAgB,SAAA,EAAmB;AACnD,QAAA,MAAA,CAAO,KAAK,mBAAmB,CAAA;AAC/B,QAAA,mBAAA,GAAsB,GAAA,EAAI;AAE1B,QAAA,MAAM,SAAA,GAAY,gBAAgB,SAAS,CAAA;AAC3C,QAAA,MAAM,OAAA,GAAU,gBAAgB,OAAO,CAAA;AAIvC,QAAAA,aAAAA,CAAO,IAAI,MAAA,CAAO,OAAA,EAAS,eAAe,SAAS,CAAA,QAAA,EAAM,OAAO,CAAA,CAAA,EAAI;AAAA,UAClE,IAAA,EAAM,SAAA;AAAA,UACN,EAAA,EAAI;AAAA,SACL,CAAA;AAED,QAAA,iBAAA,CAAkB,SAAS,SAAS,CAAA;AAAA,MACtC,CAAA;AAAA,MAEA,mBAAA,CAAoB,SAAgB,SAAA,EAAmB;AACrD,QAAkB,gBAAgB,SAAS;AAC3C,QAAgB,gBAAgB,OAAO;AAUvC,QAAA,MAAM,MAAA,GAAS,YAAA,CAAa,mBAAA,EAAqB,GAAG,CAAA;AAEpD,QAAAA,cAAO,GAAA,CAAI,MAAA,CAAO,OAAA,EAAS,CAAA,kBAAA,EAAqB,MAAM,CAAA,CAAA,EAAI;AAAA,UACxD,EAAA,EAAI,OAAA;AAAA,UACJ,IAAA,EAAM;AAAA,SACP,CAAA;AAED,QAAA,MAAA,CAAO,KAAA,EAAM;AACb,QAAA,mBAAA,GAAsB,IAAA;AAAA,MACxB,CAAA;AAAA,MAEA,kBAAA,CAAmB,SAAgB,SAAA,EAAmB;AACpD,QAAkB,gBAAgB,SAAS;AAC3C,QAAgB,gBAAgB,OAAO;AAUvC,QAAA,MAAM,MAAA,GAAS,YAAA,CAAa,mBAAA,EAAqB,GAAG,CAAA;AAEpD,QAAAA,cAAO,IAAA,CAAK,MAAA,CAAO,OAAA,EAAS,CAAA,oBAAA,EAAuB,MAAM,CAAA,CAAA,EAAI;AAAA,UAC3D,EAAA,EAAI,OAAA;AAAA,UACJ,IAAA,EAAM;AAAA,SACP,CAAA;AAED,QAAA,MAAA,CAAO,KAAA,EAAM;AACb,QAAA,mBAAA,GAAsB,IAAA;AAAA,MACxB,CAAA;AAAA,MAEA,iBAAA,CACE,OAAA,EACA,SAAA,EACA,GAAA,EACA;AACA,QAAkB,gBAAgB,SAAS;AAC3C,QAAgB,gBAAgB,OAAO;AAUvC,QAAA,MAAM,MAAA,GAAS,YAAA,CAAa,mBAAA,EAAqB,GAAG,CAAA;AAEpD,QAAAA,aAAAA,CAAO,MAAM,MAAA,CAAO,OAAA,EAAS,qBAAqB,GAAA,CAAI,IAAI,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI;AAAA,UACrE,KAAA,EAAO,GAAA;AAAA,UACP,OAAO,GAAA,CAAI,KAAA;AAAA,UACX,EAAA,EAAI,OAAA;AAAA,UACJ,IAAA,EAAM;AAAA,SACP,CAAA;AAED,QAAA,MAAA,CAAO,KAAA,EAAM;AACb,QAAA,mBAAA,GAAsB,IAAA;AAAA,MACxB,CAAA;AAAA,MAEA,QAAA,GAAW;AACT,QAAA,MAAA,CAAO,KAAA,EAAM;AACb,QAAA,mBAAA,GAAsB,IAAA;AAAA,MACxB;AAAA,KACF;AAAA,EACF,CAAA;AACF;AAUO,IAAM,eAAe,mBAAA","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 { logger } from \"logger\";\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 logger\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 const addedEntries = Object.entries(diff.added);\n\n if (addedEntries.length > 0) {\n parts.push(`Added: ${JSON.stringify(diff.added)}`);\n }\n\n const removedEntries = Object.entries(diff.removed);\n\n if (removedEntries.length > 0) {\n parts.push(`Removed: ${JSON.stringify(diff.removed)}`);\n }\n\n logger.log(context, ` ${parts.join(\", \")}`);\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 { logger } from \"logger\";\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 { PluginFactory, RouterError, State } from \"@real-router/core\";\n\n/**\n * Creates a logger plugin for real-router.\n *\n * Configuration is managed through the logger singleton.\n * Use `logger.configure()` to customize logging behavior before starting the router.\n *\n * @returns Plugin factory function for real-router\n *\n * @example\n * ```ts\n * import { logger } from \"logger\";\n * import { loggerPluginFactory } from \"real-router-logger-plugin\";\n *\n * // Configure logger before using the plugin\n * logger.configure({\n * level: \"transitions\",\n * showTiming: true,\n * context: \"MyApp\",\n * });\n *\n * router.usePlugin(loggerPluginFactory());\n * ```\n *\n * @example\n * ```ts\n * // Use with default configuration\n * router.usePlugin(loggerPluginFactory());\n * ```\n */\nexport function loggerPluginFactory(): PluginFactory {\n // eslint-disable-next-line unicorn/consistent-function-scoping -- factory pattern: closure captures config, groups, perf, transitionStartTime\n return () => {\n const config = DEFAULT_CONFIG;\n\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\n /**\n * Logs parameter differences when navigating within the same route.\n */\n const logParamsIfNeeded = (toState: State, fromState?: State): void => {\n if (!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 return {\n onStart() {\n perf.mark(\"router:start\");\n logger.log(config.context, \"Router started\");\n },\n\n onStop() {\n groups.close();\n perf.mark(\"router:stop\");\n perf.measure(\"router:lifetime\", \"router:start\", \"router:stop\");\n logger.log(config.context, \"Router stopped\");\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 const label = createTransitionLabel(fromRoute, toRoute);\n\n perf.mark(`router:transition-start:${label}`);\n logger.log(config.context, `Transition: ${fromRoute} → ${toRoute}`, {\n from: fromState,\n to: toState,\n });\n\n logParamsIfNeeded(toState, fromState);\n },\n\n onTransitionSuccess(toState: State, fromState?: State) {\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n const label = createTransitionLabel(fromRoute, toRoute);\n\n perf.mark(`router:transition-end:${label}`);\n perf.measure(\n `router:transition:${label}`,\n `router:transition-start:${label}`,\n `router:transition-end:${label}`,\n );\n\n const timing = formatTiming(transitionStartTime, now);\n\n logger.log(config.context, `Transition success${timing}`, {\n to: toState,\n from: fromState,\n });\n\n groups.close();\n transitionStartTime = null;\n },\n\n onTransitionCancel(toState: State, fromState?: State) {\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n const label = createTransitionLabel(fromRoute, toRoute);\n\n perf.mark(`router:transition-cancel:${label}`);\n perf.measure(\n `router:transition-cancelled:${label}`,\n `router:transition-start:${label}`,\n `router:transition-cancel:${label}`,\n );\n\n const timing = formatTiming(transitionStartTime, now);\n\n logger.warn(config.context, `Transition cancelled${timing}`, {\n to: toState,\n from: fromState,\n });\n\n groups.close();\n transitionStartTime = null;\n },\n\n onTransitionError(\n toState: State | undefined,\n fromState: State | undefined,\n err: RouterError,\n ) {\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n const label = createTransitionLabel(fromRoute, toRoute);\n\n perf.mark(`router:transition-error:${label}`);\n perf.measure(\n `router:transition-failed:${label}`,\n `router:transition-start:${label}`,\n `router:transition-error:${label}`,\n );\n\n const timing = formatTiming(transitionStartTime, now);\n\n logger.error(config.context, `Transition error: ${err.code}${timing}`, {\n error: err,\n stack: err.stack,\n to: toState,\n from: fromState,\n });\n\n groups.close();\n transitionStartTime = null;\n },\n\n teardown() {\n groups.close();\n transitionStartTime = null;\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"],"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 const addedEntries = Object.entries(diff.added);\n\n if (addedEntries.length > 0) {\n parts.push(`Added: ${JSON.stringify(diff.added)}`);\n }\n\n const removedEntries = Object.entries(diff.removed);\n\n if (removedEntries.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, LogLevel } from \"./types\";\nimport type { PluginFactory, RouterError, State } from \"@real-router/core\";\n\n/**\n * Checks if the given log type should be output based on the configured level.\n *\n * Level hierarchy:\n * - 'all': log everything (start, stop, transitions, warnings, errors)\n * - 'transitions': only transition events (start, success, cancel, error)\n * - 'errors': only errors\n * - 'none': nothing\n */\nconst shouldLog = (\n level: LogLevel,\n type: \"lifecycle\" | \"transition\" | \"warning\" | \"error\",\n): boolean => {\n if (level === \"none\") {\n return false;\n }\n\n if (level === \"errors\") {\n return type === \"error\";\n }\n\n if (level === \"transitions\") {\n return type === \"transition\" || type === \"warning\" || type === \"error\";\n }\n\n // level === 'all'\n return true;\n};\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 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\n /**\n * Logs parameter differences when navigating within the same route.\n */\n const logParamsIfNeeded = (toState: State, fromState?: State): void => {\n if (!config.showParamsDiff || !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 * Formats timing string based on config.\n */\n const getTiming = (): string => {\n if (!config.showTiming) {\n return \"\";\n }\n\n return formatTiming(transitionStartTime, now);\n };\n\n return {\n onStart() {\n perf.mark(\"router:start\");\n\n if (shouldLog(config.level, \"lifecycle\")) {\n console.log(`[${config.context}] 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 (shouldLog(config.level, \"lifecycle\")) {\n console.log(`[${config.context}] 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 const label = createTransitionLabel(fromRoute, toRoute);\n\n perf.mark(`router:transition-start:${label}`);\n\n if (shouldLog(config.level, \"transition\")) {\n console.log(\n `[${config.context}] Transition: ${fromRoute} → ${toRoute}`,\n {\n from: fromState,\n to: toState,\n },\n );\n\n logParamsIfNeeded(toState, fromState);\n }\n },\n\n onTransitionSuccess(toState: State, fromState?: State) {\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n const label = createTransitionLabel(fromRoute, toRoute);\n\n perf.mark(`router:transition-end:${label}`);\n perf.measure(\n `router:transition:${label}`,\n `router:transition-start:${label}`,\n `router:transition-end:${label}`,\n );\n\n if (shouldLog(config.level, \"transition\")) {\n const timing = getTiming();\n\n console.log(`[${config.context}] Transition success${timing}`, {\n to: toState,\n from: fromState,\n });\n }\n\n groups.close();\n transitionStartTime = null;\n },\n\n onTransitionCancel(toState: State, fromState?: State) {\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n const label = createTransitionLabel(fromRoute, toRoute);\n\n perf.mark(`router:transition-cancel:${label}`);\n perf.measure(\n `router:transition-cancelled:${label}`,\n `router:transition-start:${label}`,\n `router:transition-cancel:${label}`,\n );\n\n if (shouldLog(config.level, \"warning\")) {\n const timing = getTiming();\n\n console.warn(`[${config.context}] Transition cancelled${timing}`, {\n to: toState,\n from: fromState,\n });\n }\n\n groups.close();\n transitionStartTime = null;\n },\n\n onTransitionError(\n toState: State | undefined,\n fromState: State | undefined,\n err: RouterError,\n ) {\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n const label = createTransitionLabel(fromRoute, toRoute);\n\n perf.mark(`router:transition-error:${label}`);\n perf.measure(\n `router:transition-failed:${label}`,\n `router:transition-start:${label}`,\n `router:transition-error:${label}`,\n );\n\n if (shouldLog(config.level, \"error\")) {\n const timing = getTiming();\n\n console.error(\n `[${config.context}] Transition error: ${err.code}${timing}`,\n {\n error: err,\n stack: err.stack,\n to: toState,\n from: fromState,\n },\n );\n }\n\n groups.close();\n transitionStartTime = null;\n },\n\n teardown() {\n groups.close();\n transitionStartTime = null;\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 +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":2649,"imports":[{"path":"logger","kind":"import-statement","external":true},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.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":1759,"imports":[{"path":"logger","kind":"import-statement","external":true},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.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":5869,"imports":[{"path":"logger","kind":"import-statement","external":true},{"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":21213},"dist/cjs/index.js":{"imports":[{"path":"logger","kind":"import-statement","external":true},{"path":"logger","kind":"import-statement","external":true},{"path":"logger","kind":"import-statement","external":true}],"exports":["loggerPlugin","loggerPluginFactory"],"entryPoint":"src/index.ts","inputs":{"src/plugin.ts":{"bytesInOutput":3864},"src/constants.ts":{"bytesInOutput":143},"src/internal/console-groups.ts":{"bytesInOutput":727},"src/internal/formatting.ts":{"bytesInOutput":592},"src/internal/params-diff.ts":{"bytesInOutput":1390},"src/internal/performance-marks.ts":{"bytesInOutput":991},"src/internal/timing.ts":{"bytesInOutput":450},"src/index.ts":{"bytesInOutput":0}},"bytes":8426}}}
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":2620,"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":7277,"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":23185},"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":1361},"src/internal/performance-marks.ts":{"bytesInOutput":941},"src/internal/timing.ts":{"bytesInOutput":450},"src/plugin.ts":{"bytesInOutput":4751},"src/index.ts":{"bytesInOutput":0}},"bytes":9216}}}
@@ -1,52 +1,12 @@
1
1
  import { PluginFactory } from '@real-router/core';
2
2
 
3
- /**
4
- * Creates a logger plugin for real-router.
5
- *
6
- * Configuration is managed through the logger singleton.
7
- * Use `logger.configure()` to customize logging behavior before starting the router.
8
- *
9
- * @returns Plugin factory function for real-router
10
- *
11
- * @example
12
- * ```ts
13
- * import { logger } from "logger";
14
- * import { loggerPluginFactory } from "real-router-logger-plugin";
15
- *
16
- * // Configure logger before using the plugin
17
- * logger.configure({
18
- * level: "transitions",
19
- * showTiming: true,
20
- * context: "MyApp",
21
- * });
22
- *
23
- * router.usePlugin(loggerPluginFactory());
24
- * ```
25
- *
26
- * @example
27
- * ```ts
28
- * // Use with default configuration
29
- * router.usePlugin(loggerPluginFactory());
30
- * ```
31
- */
32
- declare function loggerPluginFactory(): PluginFactory;
33
- /**
34
- * Default logger plugin instance with standard configuration.
35
- * Provided for backward compatibility with existing code.
36
- *
37
- * @example
38
- * // Use default configuration
39
- * router.usePlugin(loggerPlugin);
40
- */
41
- declare const loggerPlugin: PluginFactory;
42
-
43
3
  /**
44
4
  * Logging level for router events.
45
5
  * Controls which events are logged to the console.
46
6
  */
47
7
  type LogLevel = "all" | "transitions" | "errors" | "none";
48
8
  /**
49
- * Configuration options for the logger plugin.
9
+ * Configuration options for the logger-plugin.
50
10
  */
51
11
  interface LoggerPluginConfig {
52
12
  /**
@@ -94,7 +54,7 @@ interface LoggerPluginConfig {
94
54
  */
95
55
  showParamsDiff?: boolean;
96
56
  /**
97
- * Custom context name for logger.
57
+ * Custom context name for console.
98
58
  * Useful when running multiple routers.
99
59
  *
100
60
  * @default 'logger-plugin'
@@ -102,4 +62,38 @@ interface LoggerPluginConfig {
102
62
  context?: string;
103
63
  }
104
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
+ 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
+
105
99
  export { type LogLevel, type LoggerPluginConfig, loggerPlugin, loggerPluginFactory };
@@ -1 +1 @@
1
- import{logger as n}from"logger";var o={context:"logger-plugin"},e=n=>n?.name??"(none)",t=(n,o)=>{if(null===n)return"";const e=o()-n;return!Number.isFinite(e)||e<0?" (?)":e<.1?` (${(1e3*e).toFixed(2)}μs)`:` (${e.toFixed(2)}ms)`},r=0,s=0,c="undefined"!=typeof performance&&"function"==typeof performance.now?()=>performance.now():()=>{const n=Date.now();return n<r&&(s+=r-n),r=n,n+s},i=()=>c();function l(){return()=>{const r=o,s=(n=>{let o=!1;return{open(e){n&&!o&&(console.group(e),o=!0)},close(){n&&o&&(console.groupEnd(),o=!1)},isOpen:()=>o}})("undefined"!=typeof console&&"function"==typeof console.group&&"function"==typeof console.groupEnd);let c=null;return{onStart(){n.log(r.context,"Router started")},onStop(){s.close(),n.log(r.context,"Router stopped")},onTransitionStart(o,t){s.open("Router transition"),c=i();const l=e(t),a=e(o);n.log(r.context,`Transition: ${l} → ${a}`,{from:t,to:o}),((o,e)=>{if(!e)return;if(o.name!==e.name)return;const t=((n,o)=>{const e={},t={},r={};let s=!1;for(const t in n)t in o?n[t]!==o[t]&&(e[t]={from:n[t],to:o[t]},s=!0):(r[t]=n[t],s=!0);for(const e in o)e in n||(t[e]=o[e],s=!0);return s?{changed:e,added:t,removed:r}:null})(e.params,o.params);t&&((o,e)=>{const t=[],r=Object.entries(o.changed);if(r.length>0){const n=[];for(const[o,{from:e,to:t}]of r)n.push(`${o}: ${JSON.stringify(e)} → ${JSON.stringify(t)}`);t.push(`Changed: { ${n.join(", ")} }`)}Object.entries(o.added).length>0&&t.push(`Added: ${JSON.stringify(o.added)}`),Object.entries(o.removed).length>0&&t.push(`Removed: ${JSON.stringify(o.removed)}`),n.log(e,` ${t.join(", ")}`)})(t,r.context)})(o,t)},onTransitionSuccess(o,l){e(l),e(o);const a=t(c,i);n.log(r.context,`Transition success${a}`,{to:o,from:l}),s.close(),c=null},onTransitionCancel(o,l){e(l),e(o);const a=t(c,i);n.warn(r.context,`Transition cancelled${a}`,{to:o,from:l}),s.close(),c=null},onTransitionError(o,l,a){e(l),e(o);const u=t(c,i);n.error(r.context,`Transition error: ${a.code}${u}`,{error:a,stack:a.stack,to:o,from:l}),s.close(),c=null},teardown(){s.close(),c=null}}}}var a=l();export{a as loggerPlugin,l as loggerPluginFactory};//# sourceMappingURL=index.mjs.map
1
+ var e={level:"all",usePerformanceMarks:!1,showParamsDiff:!0,showTiming:!0,context:"logger-plugin"},r=e=>e?.name??"(none)",o=(e,r)=>`${e}→${r}`,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},i=()=>s(),a=(e,r)=>"none"!==e&&("errors"===e?"error"===r:"transitions"!==e||"transition"===r||"warning"===r||"error"===r);function c(n){const t={...e,...n};return()=>{const e=(e=>{let r=!1;return{open(o){e&&!r&&(console.group(o),r=!0)},close(){e&&r&&(console.groupEnd(),r=!1)},isOpen:()=>r}})("undefined"!=typeof console&&"function"==typeof console.group&&"function"==typeof console.groupEnd),n=((e,r)=>{const o=e&&"undefined"!=typeof performance&&"function"==typeof performance.mark&&"function"==typeof performance.measure;return{mark(e){o&&performance.mark(e)},measure(e,n,t){if(o)try{performance.measure(e,n,t)}catch(o){console.warn(`[${r}] Failed to create performance measure: ${e}`,o)}}}})(t.usePerformanceMarks,t.context);let s=null;const c=()=>t.showTiming?(e=>{if(null===e)return"";const r=i()-e;return!Number.isFinite(r)||r<0?" (?)":r<.1?` (${(1e3*r).toFixed(2)}μs)`:` (${r.toFixed(2)}ms)`})(s):"";return{onStart(){n.mark("router:start"),a(t.level,"lifecycle")&&console.log(`[${t.context}] Router started`)},onStop(){e.close(),n.mark("router:stop"),n.measure("router:lifetime","router:start","router:stop"),a(t.level,"lifecycle")&&console.log(`[${t.context}] Router stopped`)},onTransitionStart(c,l){e.open("Router transition"),s=i();const u=r(l),f=r(c),m=o(u,f);n.mark(`router:transition-start:${m}`),a(t.level,"transition")&&(console.log(`[${t.context}] Transition: ${u} → ${f}`,{from:l,to:c}),((e,r)=>{if(!t.showParamsDiff||!r)return;if(e.name!==r.name)return;const o=((e,r)=>{const o={},n={},t={};let s=!1;for(const n in e)n in r?e[n]!==r[n]&&(o[n]={from:e[n],to:r[n]},s=!0):(t[n]=e[n],s=!0);for(const o in r)o in e||(n[o]=r[o],s=!0);return s?{changed:o,added:n,removed:t}:null})(r.params,e.params);o&&((e,r)=>{const o=[],n=Object.entries(e.changed);if(n.length>0){const e=[];for(const[r,{from:o,to:t}]of n)e.push(`${r}: ${JSON.stringify(o)} → ${JSON.stringify(t)}`);o.push(`Changed: { ${e.join(", ")} }`)}Object.entries(e.added).length>0&&o.push(`Added: ${JSON.stringify(e.added)}`),Object.entries(e.removed).length>0&&o.push(`Removed: ${JSON.stringify(e.removed)}`),console.log(`[${r}] ${o.join(", ")}`)})(o,t.context)})(c,l))},onTransitionSuccess(i,l){const u=r(l),f=r(i),m=o(u,f);if(n.mark(`router:transition-end:${m}`),n.measure(`router:transition:${m}`,`router:transition-start:${m}`,`router:transition-end:${m}`),a(t.level,"transition")){const e=c();console.log(`[${t.context}] Transition success${e}`,{to:i,from:l})}e.close(),s=null},onTransitionCancel(i,l){const u=r(l),f=r(i),m=o(u,f);if(n.mark(`router:transition-cancel:${m}`),n.measure(`router:transition-cancelled:${m}`,`router:transition-start:${m}`,`router:transition-cancel:${m}`),a(t.level,"warning")){const e=c();console.warn(`[${t.context}] Transition cancelled${e}`,{to:i,from:l})}e.close(),s=null},onTransitionError(i,l,u){const f=r(l),m=r(i),d=o(f,m);if(n.mark(`router:transition-error:${d}`),n.measure(`router:transition-failed:${d}`,`router:transition-start:${d}`,`router:transition-error:${d}`),a(t.level,"error")){const e=c();console.error(`[${t.context}] Transition error: ${u.code}${e}`,{error:u,stack:u.stack,to:i,from:l})}e.close(),s=null},teardown(){e.close(),s=null}}}}var l=c();export{l as loggerPlugin,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/timing.ts","../../src/plugin.ts"],"names":["now","logger"],"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 { logger } from \"logger\";\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 logger\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 const addedEntries = Object.entries(diff.added);\n\n if (addedEntries.length > 0) {\n parts.push(`Added: ${JSON.stringify(diff.added)}`);\n }\n\n const removedEntries = Object.entries(diff.removed);\n\n if (removedEntries.length > 0) {\n parts.push(`Removed: ${JSON.stringify(diff.removed)}`);\n }\n\n logger.log(context, ` ${parts.join(\", \")}`);\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 { logger } from \"logger\";\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 { PluginFactory, RouterError, State } from \"@real-router/core\";\n\n/**\n * Creates a logger plugin for real-router.\n *\n * Configuration is managed through the logger singleton.\n * Use `logger.configure()` to customize logging behavior before starting the router.\n *\n * @returns Plugin factory function for real-router\n *\n * @example\n * ```ts\n * import { logger } from \"logger\";\n * import { loggerPluginFactory } from \"real-router-logger-plugin\";\n *\n * // Configure logger before using the plugin\n * logger.configure({\n * level: \"transitions\",\n * showTiming: true,\n * context: \"MyApp\",\n * });\n *\n * router.usePlugin(loggerPluginFactory());\n * ```\n *\n * @example\n * ```ts\n * // Use with default configuration\n * router.usePlugin(loggerPluginFactory());\n * ```\n */\nexport function loggerPluginFactory(): PluginFactory {\n // eslint-disable-next-line unicorn/consistent-function-scoping -- factory pattern: closure captures config, groups, perf, transitionStartTime\n return () => {\n const config = DEFAULT_CONFIG;\n\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\n /**\n * Logs parameter differences when navigating within the same route.\n */\n const logParamsIfNeeded = (toState: State, fromState?: State): void => {\n if (!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 return {\n onStart() {\n perf.mark(\"router:start\");\n logger.log(config.context, \"Router started\");\n },\n\n onStop() {\n groups.close();\n perf.mark(\"router:stop\");\n perf.measure(\"router:lifetime\", \"router:start\", \"router:stop\");\n logger.log(config.context, \"Router stopped\");\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 const label = createTransitionLabel(fromRoute, toRoute);\n\n perf.mark(`router:transition-start:${label}`);\n logger.log(config.context, `Transition: ${fromRoute} → ${toRoute}`, {\n from: fromState,\n to: toState,\n });\n\n logParamsIfNeeded(toState, fromState);\n },\n\n onTransitionSuccess(toState: State, fromState?: State) {\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n const label = createTransitionLabel(fromRoute, toRoute);\n\n perf.mark(`router:transition-end:${label}`);\n perf.measure(\n `router:transition:${label}`,\n `router:transition-start:${label}`,\n `router:transition-end:${label}`,\n );\n\n const timing = formatTiming(transitionStartTime, now);\n\n logger.log(config.context, `Transition success${timing}`, {\n to: toState,\n from: fromState,\n });\n\n groups.close();\n transitionStartTime = null;\n },\n\n onTransitionCancel(toState: State, fromState?: State) {\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n const label = createTransitionLabel(fromRoute, toRoute);\n\n perf.mark(`router:transition-cancel:${label}`);\n perf.measure(\n `router:transition-cancelled:${label}`,\n `router:transition-start:${label}`,\n `router:transition-cancel:${label}`,\n );\n\n const timing = formatTiming(transitionStartTime, now);\n\n logger.warn(config.context, `Transition cancelled${timing}`, {\n to: toState,\n from: fromState,\n });\n\n groups.close();\n transitionStartTime = null;\n },\n\n onTransitionError(\n toState: State | undefined,\n fromState: State | undefined,\n err: RouterError,\n ) {\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n const label = createTransitionLabel(fromRoute, toRoute);\n\n perf.mark(`router:transition-error:${label}`);\n perf.measure(\n `router:transition-failed:${label}`,\n `router:transition-start:${label}`,\n `router:transition-error:${label}`,\n );\n\n const timing = formatTiming(transitionStartTime, now);\n\n logger.error(config.context, `Transition error: ${err.code}${timing}`, {\n error: err,\n stack: err.stack,\n to: toState,\n from: fromState,\n });\n\n groups.close();\n transitionStartTime = null;\n },\n\n teardown() {\n groups.close();\n transitionStartTime = null;\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"],"names":["now"],"mappings":";AAIO,IAAM,cAAA,GAA+C;AAAA,EAC1D,KAAA,EAAO,KAAA;AAAA,EACP,mBAAA,EAAqB,KAAA;AAAA,EACrB,cAAA,EAAgB,IAAA;AAAA,EAChB,UAAA,EAAY,IAAA;AAAA,EACZ,OAAA,EAAS;AACX,CAAA;;;ACLO,IAAM,wBAAwB,MAAe;AAClD,EAAA,OACE,OAAO,YAAY,WAAA,IACnB,OAAO,QAAQ,KAAA,KAAU,UAAA,IACzB,OAAO,OAAA,CAAQ,QAAA,KAAa,UAAA;AAEhC,CAAA;AA2BO,IAAM,kBAAA,GAAqB,CAAC,OAAA,KAAmC;AACpE,EAAA,IAAI,QAAA,GAAW,KAAA;AAEf,EAAA,OAAO;AAAA;AAAA;AAAA;AAAA,IAIL,KAAK,KAAA,EAAqB;AACxB,MAAA,IAAI,CAAC,WAAW,QAAA,EAAU;AACxB,QAAA;AAAA,MACF;AAEA,MAAA,OAAA,CAAQ,MAAM,KAAK,CAAA;AACnB,MAAA,QAAA,GAAW,IAAA;AAAA,IACb,CAAA;AAAA;AAAA;AAAA;AAAA,IAKA,KAAA,GAAc;AACZ,MAAA,IAAI,CAAC,OAAA,IAAW,CAAC,QAAA,EAAU;AACzB,QAAA;AAAA,MACF;AAEA,MAAA,OAAA,CAAQ,QAAA,EAAS;AACjB,MAAA,QAAA,GAAW,KAAA;AAAA,IACb,CAAA;AAAA;AAAA;AAAA;AAAA,IAKA,MAAA,GAAkB;AAChB,MAAA,OAAO,QAAA;AAAA,IACT;AAAA,GACF;AACF,CAAA;;;ACjEO,IAAM,eAAA,GAAkB,CAAC,KAAA,KAA0B;AACxD,EAAA,OAAO,OAAO,IAAA,IAAQ,QAAA;AACxB,CAAA;AAYO,IAAM,YAAA,GAAe,CAC1B,SAAA,EACAA,IAAAA,KACW;AACX,EAAA,IAAI,cAAc,IAAA,EAAM;AACtB,IAAA,OAAO,EAAA;AAAA,EACT;AAEA,EAAA,MAAM,UAAA,GAAaA,MAAI,GAAI,SAAA;AAE3B,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,UAAU,CAAA,IAAK,aAAa,CAAA,EAAG;AAClD,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,IAAI,aAAa,GAAA,EAAK;AACpB,IAAA,MAAM,WAAA,GAAA,CAAe,UAAA,GAAa,GAAA,EAAM,OAAA,CAAQ,CAAC,CAAA;AAEjD,IAAA,OAAO,KAAK,WAAW,CAAA,QAAA,CAAA;AAAA,EACzB,CAAA,MAAO;AACL,IAAA,MAAM,QAAA,GAAW,UAAA,CAAW,OAAA,CAAQ,CAAC,CAAA;AAErC,IAAA,OAAO,KAAK,QAAQ,CAAA,GAAA,CAAA;AAAA,EACtB;AACF,CAAA;AAKO,IAAM,qBAAA,GAAwB,CACnC,SAAA,EACA,OAAA,KACW;AACX,EAAA,OAAO,CAAA,EAAG,SAAS,CAAA,MAAA,EAAI,OAAO,CAAA,CAAA;AAChC,CAAA;;;ACrCO,IAAM,aAAA,GAAgB,CAC3B,UAAA,EACA,QAAA,KACsB;AACtB,EAAA,MAAM,UAAiC,EAAC;AACxC,EAAA,MAAM,QAA6B,EAAC;AACpC,EAAA,MAAM,UAAiC,EAAC;AAMxC,EAAA,IAAI,UAAA,GAAa,KAAA;AAGjB,EAAA,KAAA,MAAW,OAAO,UAAA,EAAY;AAC5B,IAAA,IAAI,EAAE,OAAO,QAAA,CAAA,EAAW;AACtB,MAAA,OAAA,CAAQ,GAAG,CAAA,GAAI,UAAA,CAAW,GAAG,CAAA;AAC7B,MAAA,UAAA,GAAa,IAAA;AAAA,IACf,WAAW,UAAA,CAAW,GAAG,CAAA,KAAM,QAAA,CAAS,GAAG,CAAA,EAAG;AAC5C,MAAA,OAAA,CAAQ,GAAG,CAAA,GAAI,EAAE,IAAA,EAAM,UAAA,CAAW,GAAG,CAAA,EAAG,EAAA,EAAI,QAAA,CAAS,GAAG,CAAA,EAAE;AAC1D,MAAA,UAAA,GAAa,IAAA;AAAA,IACf;AAAA,EACF;AAGA,EAAA,KAAA,MAAW,OAAO,QAAA,EAAU;AAC1B,IAAA,IAAI,EAAE,OAAO,UAAA,CAAA,EAAa;AACxB,MAAA,KAAA,CAAM,GAAG,CAAA,GAAI,QAAA,CAAS,GAAG,CAAA;AACzB,MAAA,UAAA,GAAa,IAAA;AAAA,IACf;AAAA,EACF;AAGA,EAAA,IAAI,CAAC,UAAA,EAAY;AACf,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,OAAA,EAAQ;AACnC,CAAA;AAQO,IAAM,aAAA,GAAgB,CAAC,IAAA,EAAkB,OAAA,KAA0B;AACxE,EAAA,MAAM,QAAkB,EAAC;AAGzB,EAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAA;AAElD,EAAA,IAAI,cAAA,CAAe,SAAS,CAAA,EAAG;AAC7B,IAAA,MAAM,QAAkB,EAAC;AAEzB,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,EAAE,MAAM,EAAA,EAAI,KAAK,cAAA,EAAgB;AAChD,MAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAG,GAAG,CAAA,EAAA,EAAK,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA,QAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,CAAC,CAAA,CAAE,CAAA;AAAA,IACtE;AAEA,IAAA,KAAA,CAAM,KAAK,CAAA,WAAA,EAAc,KAAA,CAAM,IAAA,CAAK,IAAI,CAAC,CAAA,EAAA,CAAI,CAAA;AAAA,EAC/C;AAEA,EAAA,MAAM,YAAA,GAAe,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA;AAE9C,EAAA,IAAI,YAAA,CAAa,SAAS,CAAA,EAAG;AAC3B,IAAA,KAAA,CAAM,KAAK,CAAA,OAAA,EAAU,IAAA,CAAK,UAAU,IAAA,CAAK,KAAK,CAAC,CAAA,CAAE,CAAA;AAAA,EACnD;AAEA,EAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAA;AAElD,EAAA,IAAI,cAAA,CAAe,SAAS,CAAA,EAAG;AAC7B,IAAA,KAAA,CAAM,KAAK,CAAA,SAAA,EAAY,IAAA,CAAK,UAAU,IAAA,CAAK,OAAO,CAAC,CAAA,CAAE,CAAA;AAAA,EACvD;AAEA,EAAA,OAAA,CAAQ,GAAA,CAAI,IAAI,OAAO,CAAA,GAAA,EAAM,MAAM,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AACjD,CAAA;;;ACzFO,IAAM,yBAAyB,MAAe;AACnD,EAAA,OACE,OAAO,gBAAgB,WAAA,IACvB,OAAO,YAAY,IAAA,KAAS,UAAA,IAC5B,OAAO,WAAA,CAAY,OAAA,KAAY,UAAA;AAEnC,CAAA;AAkBO,IAAM,wBAAA,GAA2B,CACtC,OAAA,EACA,OAAA,KACuB;AACvB,EAAA,MAAM,WAAA,GAAc,WAAW,sBAAA,EAAuB;AAEtD,EAAA,OAAO;AAAA;AAAA;AAAA;AAAA,IAIL,KAAK,IAAA,EAAoB;AACvB,MAAA,IAAI,CAAC,WAAA,EAAa;AAChB,QAAA;AAAA,MACF;AAEA,MAAA,WAAA,CAAY,KAAK,IAAI,CAAA;AAAA,IACvB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,OAAA,CAAQ,WAAA,EAAqB,SAAA,EAAmB,OAAA,EAAuB;AACrE,MAAA,IAAI,CAAC,WAAA,EAAa;AAChB,QAAA;AAAA,MACF;AAEA,MAAA,IAAI;AACF,QAAA,WAAA,CAAY,OAAA,CAAQ,WAAA,EAAa,SAAA,EAAW,OAAO,CAAA;AAAA,MACrD,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,IAAA;AAAA,UACN,CAAA,CAAA,EAAI,OAAO,CAAA,wCAAA,EAA2C,WAAW,CAAA,CAAA;AAAA,UACjE;AAAA,SACF;AAAA,MACF;AAAA,IACF;AAAA,GACF;AACF,CAAA;;;ACxDA,IAAI,aAAA,GAAgB,CAAA;AACpB,IAAI,UAAA,GAAa,CAAA;AAOjB,SAAS,sBAAA,GAAuC;AAE9C,EAAA,OAAO,MAAc;AACnB,IAAA,MAAM,OAAA,GAAkB,KAAK,GAAA,EAAI;AAEjC,IAAA,IAAI,UAAU,aAAA,EAAe;AAC3B,MAAA,UAAA,IAAc,aAAA,GAAgB,OAAA;AAAA,IAChC;AAEA,IAAA,aAAA,GAAgB,OAAA;AAEhB,IAAA,OAAO,OAAA,GAAU,UAAA;AAAA,EACnB,CAAA;AACF;AAOA,IAAM,KAAA,GACJ,OAAO,WAAA,KAAgB,WAAA,IAAe,OAAO,WAAA,CAAY,GAAA,KAAQ,UAAA,GAC7D,MAAc,WAAA,CAAY,GAAA,EAAI,GAC9B,sBAAA,EAAuB;AAUtB,IAAM,GAAA,GAAM,MAAc,KAAA,EAAM;;;ACvBvC,IAAM,SAAA,GAAY,CAChB,KAAA,EACA,IAAA,KACY;AACZ,EAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,IAAI,UAAU,QAAA,EAAU;AACtB,IAAA,OAAO,IAAA,KAAS,OAAA;AAAA,EAClB;AAEA,EAAA,IAAI,UAAU,aAAA,EAAe;AAC3B,IAAA,OAAO,IAAA,KAAS,YAAA,IAAgB,IAAA,KAAS,SAAA,IAAa,IAAA,KAAS,OAAA;AAAA,EACjE;AAGA,EAAA,OAAO,IAAA;AACT,CAAA;AAyBO,SAAS,oBACd,OAAA,EACe;AAEf,EAAA,MAAM,MAAA,GAAuC;AAAA,IAC3C,GAAG,cAAA;AAAA,IACH,GAAG;AAAA,GACL;AAEA,EAAA,OAAO,MAAM;AAEX,IAAA,MAAM,MAAA,GAAS,kBAAA,CAAmB,qBAAA,EAAuB,CAAA;AACzD,IAAA,MAAM,IAAA,GAAO,wBAAA;AAAA,MACX,MAAA,CAAO,mBAAA;AAAA,MACP,MAAA,CAAO;AAAA,KACT;AAGA,IAAA,IAAI,mBAAA,GAAqC,IAAA;AAKzC,IAAA,MAAM,iBAAA,GAAoB,CAAC,OAAA,EAAgB,SAAA,KAA4B;AACrE,MAAA,IAAI,CAAC,MAAA,CAAO,cAAA,IAAkB,CAAC,SAAA,EAAW;AACxC,QAAA;AAAA,MACF;AAGA,MAAA,IAAI,OAAA,CAAQ,IAAA,KAAS,SAAA,CAAU,IAAA,EAAM;AACnC,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,IAAA,GAAO,aAAA,CAAc,SAAA,CAAU,MAAA,EAAQ,QAAQ,MAAM,CAAA;AAE3D,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,aAAA,CAAc,IAAA,EAAM,OAAO,OAAO,CAAA;AAAA,MACpC;AAAA,IACF,CAAA;AAKA,IAAA,MAAM,YAAY,MAAc;AAC9B,MAAA,IAAI,CAAC,OAAO,UAAA,EAAY;AACtB,QAAA,OAAO,EAAA;AAAA,MACT;AAEA,MAAA,OAAO,YAAA,CAAa,qBAAqB,GAAG,CAAA;AAAA,IAC9C,CAAA;AAEA,IAAA,OAAO;AAAA,MACL,OAAA,GAAU;AACR,QAAA,IAAA,CAAK,KAAK,cAAc,CAAA;AAExB,QAAA,IAAI,SAAA,CAAU,MAAA,CAAO,KAAA,EAAO,WAAW,CAAA,EAAG;AACxC,UAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAA,EAAI,MAAA,CAAO,OAAO,CAAA,gBAAA,CAAkB,CAAA;AAAA,QAClD;AAAA,MACF,CAAA;AAAA,MAEA,MAAA,GAAS;AACP,QAAA,MAAA,CAAO,KAAA,EAAM;AAEb,QAAA,IAAA,CAAK,KAAK,aAAa,CAAA;AACvB,QAAA,IAAA,CAAK,OAAA,CAAQ,iBAAA,EAAmB,cAAA,EAAgB,aAAa,CAAA;AAE7D,QAAA,IAAI,SAAA,CAAU,MAAA,CAAO,KAAA,EAAO,WAAW,CAAA,EAAG;AACxC,UAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAA,EAAI,MAAA,CAAO,OAAO,CAAA,gBAAA,CAAkB,CAAA;AAAA,QAClD;AAAA,MACF,CAAA;AAAA,MAEA,iBAAA,CAAkB,SAAgB,SAAA,EAAmB;AACnD,QAAA,MAAA,CAAO,KAAK,mBAAmB,CAAA;AAC/B,QAAA,mBAAA,GAAsB,GAAA,EAAI;AAE1B,QAAA,MAAM,SAAA,GAAY,gBAAgB,SAAS,CAAA;AAC3C,QAAA,MAAM,OAAA,GAAU,gBAAgB,OAAO,CAAA;AACvC,QAAA,MAAM,KAAA,GAAQ,qBAAA,CAAsB,SAAA,EAAW,OAAO,CAAA;AAEtD,QAAA,IAAA,CAAK,IAAA,CAAK,CAAA,wBAAA,EAA2B,KAAK,CAAA,CAAE,CAAA;AAE5C,QAAA,IAAI,SAAA,CAAU,MAAA,CAAO,KAAA,EAAO,YAAY,CAAA,EAAG;AACzC,UAAA,OAAA,CAAQ,GAAA;AAAA,YACN,IAAI,MAAA,CAAO,OAAO,CAAA,cAAA,EAAiB,SAAS,WAAM,OAAO,CAAA,CAAA;AAAA,YACzD;AAAA,cACE,IAAA,EAAM,SAAA;AAAA,cACN,EAAA,EAAI;AAAA;AACN,WACF;AAEA,UAAA,iBAAA,CAAkB,SAAS,SAAS,CAAA;AAAA,QACtC;AAAA,MACF,CAAA;AAAA,MAEA,mBAAA,CAAoB,SAAgB,SAAA,EAAmB;AACrD,QAAA,MAAM,SAAA,GAAY,gBAAgB,SAAS,CAAA;AAC3C,QAAA,MAAM,OAAA,GAAU,gBAAgB,OAAO,CAAA;AACvC,QAAA,MAAM,KAAA,GAAQ,qBAAA,CAAsB,SAAA,EAAW,OAAO,CAAA;AAEtD,QAAA,IAAA,CAAK,IAAA,CAAK,CAAA,sBAAA,EAAyB,KAAK,CAAA,CAAE,CAAA;AAC1C,QAAA,IAAA,CAAK,OAAA;AAAA,UACH,qBAAqB,KAAK,CAAA,CAAA;AAAA,UAC1B,2BAA2B,KAAK,CAAA,CAAA;AAAA,UAChC,yBAAyB,KAAK,CAAA;AAAA,SAChC;AAEA,QAAA,IAAI,SAAA,CAAU,MAAA,CAAO,KAAA,EAAO,YAAY,CAAA,EAAG;AACzC,UAAA,MAAM,SAAS,SAAA,EAAU;AAEzB,UAAA,OAAA,CAAQ,IAAI,CAAA,CAAA,EAAI,MAAA,CAAO,OAAO,CAAA,oBAAA,EAAuB,MAAM,CAAA,CAAA,EAAI;AAAA,YAC7D,EAAA,EAAI,OAAA;AAAA,YACJ,IAAA,EAAM;AAAA,WACP,CAAA;AAAA,QACH;AAEA,QAAA,MAAA,CAAO,KAAA,EAAM;AACb,QAAA,mBAAA,GAAsB,IAAA;AAAA,MACxB,CAAA;AAAA,MAEA,kBAAA,CAAmB,SAAgB,SAAA,EAAmB;AACpD,QAAA,MAAM,SAAA,GAAY,gBAAgB,SAAS,CAAA;AAC3C,QAAA,MAAM,OAAA,GAAU,gBAAgB,OAAO,CAAA;AACvC,QAAA,MAAM,KAAA,GAAQ,qBAAA,CAAsB,SAAA,EAAW,OAAO,CAAA;AAEtD,QAAA,IAAA,CAAK,IAAA,CAAK,CAAA,yBAAA,EAA4B,KAAK,CAAA,CAAE,CAAA;AAC7C,QAAA,IAAA,CAAK,OAAA;AAAA,UACH,+BAA+B,KAAK,CAAA,CAAA;AAAA,UACpC,2BAA2B,KAAK,CAAA,CAAA;AAAA,UAChC,4BAA4B,KAAK,CAAA;AAAA,SACnC;AAEA,QAAA,IAAI,SAAA,CAAU,MAAA,CAAO,KAAA,EAAO,SAAS,CAAA,EAAG;AACtC,UAAA,MAAM,SAAS,SAAA,EAAU;AAEzB,UAAA,OAAA,CAAQ,KAAK,CAAA,CAAA,EAAI,MAAA,CAAO,OAAO,CAAA,sBAAA,EAAyB,MAAM,CAAA,CAAA,EAAI;AAAA,YAChE,EAAA,EAAI,OAAA;AAAA,YACJ,IAAA,EAAM;AAAA,WACP,CAAA;AAAA,QACH;AAEA,QAAA,MAAA,CAAO,KAAA,EAAM;AACb,QAAA,mBAAA,GAAsB,IAAA;AAAA,MACxB,CAAA;AAAA,MAEA,iBAAA,CACE,OAAA,EACA,SAAA,EACA,GAAA,EACA;AACA,QAAA,MAAM,SAAA,GAAY,gBAAgB,SAAS,CAAA;AAC3C,QAAA,MAAM,OAAA,GAAU,gBAAgB,OAAO,CAAA;AACvC,QAAA,MAAM,KAAA,GAAQ,qBAAA,CAAsB,SAAA,EAAW,OAAO,CAAA;AAEtD,QAAA,IAAA,CAAK,IAAA,CAAK,CAAA,wBAAA,EAA2B,KAAK,CAAA,CAAE,CAAA;AAC5C,QAAA,IAAA,CAAK,OAAA;AAAA,UACH,4BAA4B,KAAK,CAAA,CAAA;AAAA,UACjC,2BAA2B,KAAK,CAAA,CAAA;AAAA,UAChC,2BAA2B,KAAK,CAAA;AAAA,SAClC;AAEA,QAAA,IAAI,SAAA,CAAU,MAAA,CAAO,KAAA,EAAO,OAAO,CAAA,EAAG;AACpC,UAAA,MAAM,SAAS,SAAA,EAAU;AAEzB,UAAA,OAAA,CAAQ,KAAA;AAAA,YACN,IAAI,MAAA,CAAO,OAAO,uBAAuB,GAAA,CAAI,IAAI,GAAG,MAAM,CAAA,CAAA;AAAA,YAC1D;AAAA,cACE,KAAA,EAAO,GAAA;AAAA,cACP,OAAO,GAAA,CAAI,KAAA;AAAA,cACX,EAAA,EAAI,OAAA;AAAA,cACJ,IAAA,EAAM;AAAA;AACR,WACF;AAAA,QACF;AAEA,QAAA,MAAA,CAAO,KAAA,EAAM;AACb,QAAA,mBAAA,GAAsB,IAAA;AAAA,MACxB,CAAA;AAAA,MAEA,QAAA,GAAW;AACT,QAAA,MAAA,CAAO,KAAA,EAAM;AACb,QAAA,mBAAA,GAAsB,IAAA;AAAA,MACxB;AAAA,KACF;AAAA,EACF,CAAA;AACF;AAUO,IAAM,eAAe,mBAAA","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 const addedEntries = Object.entries(diff.added);\n\n if (addedEntries.length > 0) {\n parts.push(`Added: ${JSON.stringify(diff.added)}`);\n }\n\n const removedEntries = Object.entries(diff.removed);\n\n if (removedEntries.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, LogLevel } from \"./types\";\nimport type { PluginFactory, RouterError, State } from \"@real-router/core\";\n\n/**\n * Checks if the given log type should be output based on the configured level.\n *\n * Level hierarchy:\n * - 'all': log everything (start, stop, transitions, warnings, errors)\n * - 'transitions': only transition events (start, success, cancel, error)\n * - 'errors': only errors\n * - 'none': nothing\n */\nconst shouldLog = (\n level: LogLevel,\n type: \"lifecycle\" | \"transition\" | \"warning\" | \"error\",\n): boolean => {\n if (level === \"none\") {\n return false;\n }\n\n if (level === \"errors\") {\n return type === \"error\";\n }\n\n if (level === \"transitions\") {\n return type === \"transition\" || type === \"warning\" || type === \"error\";\n }\n\n // level === 'all'\n return true;\n};\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 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\n /**\n * Logs parameter differences when navigating within the same route.\n */\n const logParamsIfNeeded = (toState: State, fromState?: State): void => {\n if (!config.showParamsDiff || !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 * Formats timing string based on config.\n */\n const getTiming = (): string => {\n if (!config.showTiming) {\n return \"\";\n }\n\n return formatTiming(transitionStartTime, now);\n };\n\n return {\n onStart() {\n perf.mark(\"router:start\");\n\n if (shouldLog(config.level, \"lifecycle\")) {\n console.log(`[${config.context}] 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 (shouldLog(config.level, \"lifecycle\")) {\n console.log(`[${config.context}] 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 const label = createTransitionLabel(fromRoute, toRoute);\n\n perf.mark(`router:transition-start:${label}`);\n\n if (shouldLog(config.level, \"transition\")) {\n console.log(\n `[${config.context}] Transition: ${fromRoute} → ${toRoute}`,\n {\n from: fromState,\n to: toState,\n },\n );\n\n logParamsIfNeeded(toState, fromState);\n }\n },\n\n onTransitionSuccess(toState: State, fromState?: State) {\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n const label = createTransitionLabel(fromRoute, toRoute);\n\n perf.mark(`router:transition-end:${label}`);\n perf.measure(\n `router:transition:${label}`,\n `router:transition-start:${label}`,\n `router:transition-end:${label}`,\n );\n\n if (shouldLog(config.level, \"transition\")) {\n const timing = getTiming();\n\n console.log(`[${config.context}] Transition success${timing}`, {\n to: toState,\n from: fromState,\n });\n }\n\n groups.close();\n transitionStartTime = null;\n },\n\n onTransitionCancel(toState: State, fromState?: State) {\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n const label = createTransitionLabel(fromRoute, toRoute);\n\n perf.mark(`router:transition-cancel:${label}`);\n perf.measure(\n `router:transition-cancelled:${label}`,\n `router:transition-start:${label}`,\n `router:transition-cancel:${label}`,\n );\n\n if (shouldLog(config.level, \"warning\")) {\n const timing = getTiming();\n\n console.warn(`[${config.context}] Transition cancelled${timing}`, {\n to: toState,\n from: fromState,\n });\n }\n\n groups.close();\n transitionStartTime = null;\n },\n\n onTransitionError(\n toState: State | undefined,\n fromState: State | undefined,\n err: RouterError,\n ) {\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n const label = createTransitionLabel(fromRoute, toRoute);\n\n perf.mark(`router:transition-error:${label}`);\n perf.measure(\n `router:transition-failed:${label}`,\n `router:transition-start:${label}`,\n `router:transition-error:${label}`,\n );\n\n if (shouldLog(config.level, \"error\")) {\n const timing = getTiming();\n\n console.error(\n `[${config.context}] Transition error: ${err.code}${timing}`,\n {\n error: err,\n stack: err.stack,\n to: toState,\n from: fromState,\n },\n );\n }\n\n groups.close();\n transitionStartTime = null;\n },\n\n teardown() {\n groups.close();\n transitionStartTime = null;\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 +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":2649,"imports":[{"path":"logger","kind":"import-statement","external":true}],"format":"esm"},"src/internal/performance-marks.ts":{"bytes":1759,"imports":[{"path":"logger","kind":"import-statement","external":true}],"format":"esm"},"src/internal/timing.ts":{"bytes":1480,"imports":[],"format":"esm"},"src/plugin.ts":{"bytes":5869,"imports":[{"path":"logger","kind":"import-statement","external":true},{"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":21213},"dist/esm/index.mjs":{"imports":[{"path":"logger","kind":"import-statement","external":true},{"path":"logger","kind":"import-statement","external":true},{"path":"logger","kind":"import-statement","external":true}],"exports":["loggerPlugin","loggerPluginFactory"],"entryPoint":"src/index.ts","inputs":{"src/plugin.ts":{"bytesInOutput":3864},"src/constants.ts":{"bytesInOutput":143},"src/internal/console-groups.ts":{"bytesInOutput":727},"src/internal/formatting.ts":{"bytesInOutput":592},"src/internal/params-diff.ts":{"bytesInOutput":1390},"src/internal/performance-marks.ts":{"bytesInOutput":991},"src/internal/timing.ts":{"bytesInOutput":450},"src/index.ts":{"bytesInOutput":0}},"bytes":8426}}}
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":2620,"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":7277,"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":23185},"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":1361},"src/internal/performance-marks.ts":{"bytesInOutput":941},"src/internal/timing.ts":{"bytesInOutput":450},"src/plugin.ts":{"bytesInOutput":4751},"src/index.ts":{"bytesInOutput":0}},"bytes":9216}}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@real-router/logger-plugin",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "type": "commonjs",
5
5
  "description": "Development logging plugin with transition tracking and performance metrics",
6
6
  "main": "./dist/cjs/index.js",