@real-router/logger-plugin 0.0.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -130
- package/dist/cjs/index.d.ts +61 -33
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/metafile-cjs.json +1 -1
- package/dist/esm/index.d.mts +61 -33
- package/dist/esm/index.mjs +1 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/metafile-esm.json +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://opensource.org/licenses/MIT)
|
|
4
4
|
[](https://www.typescriptlang.org/)
|
|
5
5
|
|
|
6
|
-
|
|
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 {
|
|
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(
|
|
29
|
+
router.usePlugin(loggerPluginFactory());
|
|
30
30
|
|
|
31
31
|
router.start();
|
|
32
32
|
```
|
|
@@ -34,192 +34,147 @@ 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
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
```
|
|
46
|
-
Transition success (27.29μs)
|
|
47
|
-
```
|
|
43
|
+
---
|
|
48
44
|
|
|
49
45
|
## API
|
|
50
46
|
|
|
51
|
-
### `
|
|
47
|
+
### `loggerPluginFactory(options?)`
|
|
52
48
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
```typescript
|
|
56
|
-
import { loggerPlugin } from "@real-router/logger-plugin";
|
|
57
|
-
|
|
58
|
-
router.usePlugin(loggerPlugin);
|
|
59
|
-
```
|
|
60
|
-
|
|
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
|
-
|
|
73
|
-
The plugin uses the following default configuration:
|
|
74
56
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
level: "
|
|
78
|
-
showTiming:
|
|
79
|
-
|
|
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
|
-
### `
|
|
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
|
-
-
|
|
113
|
-
- `false` - don't show parameter changes
|
|
66
|
+
Ready-to-use plugin instance with default settings. Provided for backward compatibility.
|
|
114
67
|
|
|
115
|
-
|
|
68
|
+
```typescript
|
|
69
|
+
import { loggerPlugin } from "@real-router/logger-plugin";
|
|
116
70
|
|
|
117
|
-
|
|
118
|
-
▼ Router transition
|
|
119
|
-
Transition: users.view → users.view
|
|
120
|
-
Changed: { id: "123" → "456" }, Added: {"sort":"name"}
|
|
121
|
-
Transition success (2.15ms)
|
|
71
|
+
router.usePlugin(loggerPlugin);
|
|
122
72
|
```
|
|
123
73
|
|
|
124
|
-
|
|
74
|
+
---
|
|
125
75
|
|
|
126
|
-
|
|
127
|
-
- **Added** - new parameters in target state
|
|
128
|
-
- **Removed** - parameters present in source but not in target
|
|
76
|
+
## Configuration
|
|
129
77
|
|
|
130
|
-
|
|
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 |
|
|
131
85
|
|
|
132
|
-
|
|
133
|
-
- ✅ Only when parameters actually changed
|
|
134
|
-
- ❌ Not shown when navigating between different routes
|
|
135
|
-
- ❌ Not shown when parameters are identical
|
|
86
|
+
### Configuration Examples
|
|
136
87
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
88
|
+
```typescript
|
|
89
|
+
// With custom context for multiple routers
|
|
90
|
+
router.usePlugin(loggerPluginFactory({
|
|
91
|
+
context: "main-router",
|
|
92
|
+
}));
|
|
140
93
|
|
|
141
|
-
|
|
94
|
+
// Performance profiling enabled
|
|
95
|
+
router.usePlugin(loggerPluginFactory({
|
|
96
|
+
usePerformanceMarks: true,
|
|
97
|
+
showTiming: true,
|
|
98
|
+
}));
|
|
142
99
|
|
|
143
|
-
|
|
100
|
+
// Errors only (for production-like environments)
|
|
101
|
+
router.usePlugin(loggerPluginFactory({
|
|
102
|
+
level: "errors",
|
|
103
|
+
showTiming: false,
|
|
104
|
+
}));
|
|
144
105
|
|
|
106
|
+
// Minimal output
|
|
107
|
+
router.usePlugin(loggerPluginFactory({
|
|
108
|
+
level: "transitions",
|
|
109
|
+
showParamsDiff: false,
|
|
110
|
+
showTiming: false,
|
|
111
|
+
}));
|
|
145
112
|
```
|
|
146
|
-
[logger-plugin] Transition: dashboard → users
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
## Logged Events
|
|
150
113
|
|
|
151
|
-
|
|
114
|
+
See [Wiki](https://github.com/greydragon888/real-router/wiki/logger-plugin#3-configuration-options) for detailed descriptions.
|
|
152
115
|
|
|
153
|
-
|
|
116
|
+
---
|
|
154
117
|
|
|
155
|
-
|
|
156
|
-
Router started
|
|
157
|
-
```
|
|
118
|
+
## Features
|
|
158
119
|
|
|
159
|
-
|
|
120
|
+
### Timing Display
|
|
160
121
|
|
|
161
122
|
```
|
|
162
|
-
|
|
123
|
+
[logger-plugin] Transition success (15ms) // normal
|
|
124
|
+
[logger-plugin] Transition success (27.29μs) // fast (<0.1ms)
|
|
163
125
|
```
|
|
164
126
|
|
|
165
|
-
###
|
|
127
|
+
### Parameter Diff
|
|
166
128
|
|
|
167
|
-
|
|
129
|
+
When navigating within the same route:
|
|
168
130
|
|
|
169
131
|
```
|
|
170
132
|
▼ Router transition
|
|
171
|
-
Transition:
|
|
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: {...}}
|
|
172
136
|
```
|
|
173
137
|
|
|
174
|
-
|
|
138
|
+
### Performance API
|
|
175
139
|
|
|
176
|
-
|
|
177
|
-
Transition success (24ms)
|
|
178
|
-
```
|
|
140
|
+
With `usePerformanceMarks: true`, creates marks visible in DevTools Performance tab:
|
|
179
141
|
|
|
180
|
-
|
|
142
|
+
- `router:transition-start:{from}→{to}`
|
|
143
|
+
- `router:transition-end:{from}→{to}`
|
|
144
|
+
- `router:transition:{from}→{to}` (measure)
|
|
181
145
|
|
|
182
|
-
|
|
183
|
-
Transition cancelled (12ms)
|
|
184
|
-
```
|
|
146
|
+
See [Wiki](https://github.com/greydragon888/real-router/wiki/logger-plugin#10-performance-marks-and-measures) for full list.
|
|
185
147
|
|
|
186
|
-
|
|
148
|
+
---
|
|
187
149
|
|
|
188
|
-
|
|
189
|
-
Transition error: ROUTE_NOT_FOUND (8ms)
|
|
190
|
-
```
|
|
150
|
+
## SSR Support
|
|
191
151
|
|
|
192
|
-
|
|
152
|
+
For high-precision timing in Node.js:
|
|
193
153
|
|
|
194
|
-
|
|
154
|
+
```typescript
|
|
155
|
+
import { performance } from "perf_hooks";
|
|
195
156
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
[middleware logs...]
|
|
200
|
-
[guard logs...]
|
|
201
|
-
Transition success (45ms)
|
|
157
|
+
if (typeof globalThis.performance === "undefined") {
|
|
158
|
+
globalThis.performance = performance;
|
|
159
|
+
}
|
|
202
160
|
```
|
|
203
161
|
|
|
204
|
-
|
|
162
|
+
---
|
|
205
163
|
|
|
206
|
-
##
|
|
164
|
+
## Documentation
|
|
207
165
|
|
|
208
|
-
|
|
166
|
+
Full documentation on [Wiki](https://github.com/greydragon888/real-router/wiki/logger-plugin):
|
|
209
167
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
} from "@real-router/logger-plugin";
|
|
217
|
-
```
|
|
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
|
+
---
|
|
218
174
|
|
|
219
175
|
## Related Packages
|
|
220
176
|
|
|
221
177
|
- [@real-router/core](https://www.npmjs.com/package/@real-router/core) — Core router
|
|
222
|
-
- [@real-router/react](https://www.npmjs.com/package/@real-router/react) — React integration
|
|
223
178
|
- [@real-router/browser-plugin](https://www.npmjs.com/package/@real-router/browser-plugin) — Browser history
|
|
224
179
|
|
|
225
180
|
## License
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,45 +1,32 @@
|
|
|
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
|
-
*
|
|
8
|
-
* @returns Plugin factory function for real-router
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* import { loggerPluginFactory } from "@real-router/logger-plugin";
|
|
13
|
-
*
|
|
14
|
-
* router.usePlugin(loggerPluginFactory());
|
|
15
|
-
* ```
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* ```ts
|
|
19
|
-
* // Use with default configuration
|
|
20
|
-
* router.usePlugin(loggerPluginFactory());
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
declare function loggerPluginFactory(): PluginFactory;
|
|
24
|
-
/**
|
|
25
|
-
* Default logger plugin instance with standard configuration.
|
|
26
|
-
* Provided for backward compatibility with existing code.
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* // Use default configuration
|
|
30
|
-
* router.usePlugin(loggerPlugin);
|
|
31
|
-
*/
|
|
32
|
-
declare const loggerPlugin: PluginFactory;
|
|
33
|
-
|
|
34
3
|
/**
|
|
35
4
|
* Logging level for router events.
|
|
36
5
|
* Controls which events are logged to the console.
|
|
37
6
|
*/
|
|
38
7
|
type LogLevel = "all" | "transitions" | "errors" | "none";
|
|
39
8
|
/**
|
|
40
|
-
* Configuration options for the logger
|
|
9
|
+
* Configuration options for the logger-plugin.
|
|
41
10
|
*/
|
|
42
11
|
interface LoggerPluginConfig {
|
|
12
|
+
/**
|
|
13
|
+
* Use Performance API to create marks and measures.
|
|
14
|
+
* Enables integration with browser DevTools Performance tab.
|
|
15
|
+
*
|
|
16
|
+
* Creates marks:
|
|
17
|
+
* - `router:transition-start:{from}→{to}`
|
|
18
|
+
* - `router:transition-end:{from}→{to}` (success)
|
|
19
|
+
* - `router:transition-cancel:{from}→{to}` (cancelled)
|
|
20
|
+
* - `router:transition-error:{from}→{to}` (error)
|
|
21
|
+
*
|
|
22
|
+
* Creates measures:
|
|
23
|
+
* - `router:transition:{from}→{to}` (success)
|
|
24
|
+
* - `router:transition-cancelled:{from}→{to}` (cancelled)
|
|
25
|
+
* - `router:transition-failed:{from}→{to}` (error)
|
|
26
|
+
*
|
|
27
|
+
* @default false
|
|
28
|
+
*/
|
|
29
|
+
usePerformanceMarks?: boolean;
|
|
43
30
|
/**
|
|
44
31
|
* Logging level - controls what router events to log.
|
|
45
32
|
*
|
|
@@ -51,6 +38,13 @@ interface LoggerPluginConfig {
|
|
|
51
38
|
* @default 'all'
|
|
52
39
|
*/
|
|
53
40
|
level?: LogLevel;
|
|
41
|
+
/**
|
|
42
|
+
* Show execution time in milliseconds for transitions.
|
|
43
|
+
* Helps identify slow route changes.
|
|
44
|
+
*
|
|
45
|
+
* @default true
|
|
46
|
+
*/
|
|
47
|
+
showTiming?: boolean;
|
|
54
48
|
/**
|
|
55
49
|
* Show diff of changed route parameters between transitions.
|
|
56
50
|
* Only applies when navigating within the same route.
|
|
@@ -60,7 +54,7 @@ interface LoggerPluginConfig {
|
|
|
60
54
|
*/
|
|
61
55
|
showParamsDiff?: boolean;
|
|
62
56
|
/**
|
|
63
|
-
* Custom context name for
|
|
57
|
+
* Custom context name for console.
|
|
64
58
|
* Useful when running multiple routers.
|
|
65
59
|
*
|
|
66
60
|
* @default 'logger-plugin'
|
|
@@ -68,4 +62,38 @@ interface LoggerPluginConfig {
|
|
|
68
62
|
context?: string;
|
|
69
63
|
}
|
|
70
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
|
+
|
|
71
99
|
export { type LogLevel, type LoggerPluginConfig, loggerPlugin, loggerPluginFactory };
|
package/dist/cjs/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
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
|
package/dist/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/constants.ts","../../src/internal/console-groups.ts","../../src/internal/formatting.ts","../../src/internal/params-diff.ts","../../src/plugin.ts"],"names":[],"mappings":";AAIO,IAAM,cAAA,GAA+C;AAAA,EAG1D,OAAA,EAAS;AACX,CAAA;;;ACHO,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;;;ACQO,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;;;AC9DO,SAAS,mBAAA,GAAqC;AAEnD,EAAA,OAAO,MAAM;AACX,IAAA,MAAM,MAAA,GAAS,cAAA;AAGf,IAAA,MAAM,MAAA,GAAS,kBAAA,CAAmB,qBAAA,EAAuB,CAAA;AAKzD,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;AACR,QAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAA,EAAI,MAAA,CAAO,OAAO,CAAA,gBAAA,CAAkB,CAAA;AAAA,MAClD,CAAA;AAAA,MAEA,MAAA,GAAS;AACP,QAAA,MAAA,CAAO,KAAA,EAAM;AACb,QAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAA,EAAI,MAAA,CAAO,OAAO,CAAA,gBAAA,CAAkB,CAAA;AAAA,MAClD,CAAA;AAAA,MAEA,iBAAA,CAAkB,SAAgB,SAAA,EAAmB;AACnD,QAAA,MAAA,CAAO,KAAK,mBAAmB,CAAA;AAE/B,QAAA,MAAM,SAAA,GAAY,gBAAgB,SAAS,CAAA;AAC3C,QAAA,MAAM,OAAA,GAAU,gBAAgB,OAAO,CAAA;AAEvC,QAAA,OAAA,CAAQ,GAAA;AAAA,UACN,IAAI,MAAA,CAAO,OAAO,CAAA,cAAA,EAAiB,SAAS,WAAM,OAAO,CAAA,CAAA;AAAA,UACzD;AAAA,YACE,IAAA,EAAM,SAAA;AAAA,YACN,EAAA,EAAI;AAAA;AACN,SACF;AAEA,QAAA,iBAAA,CAAkB,SAAS,SAAS,CAAA;AAAA,MACtC,CAAA;AAAA,MAEA,mBAAA,CAAoB,SAAgB,SAAA,EAAmB;AACrD,QAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAA,EAAI,MAAA,CAAO,OAAO,CAAA,oBAAA,CAAA,EAAwB;AAAA,UACpD,EAAA,EAAI,OAAA;AAAA,UACJ,IAAA,EAAM;AAAA,SACP,CAAA;AAED,QAAA,MAAA,CAAO,KAAA,EAAM;AAAA,MACf,CAAA;AAAA,MAEA,kBAAA,CAAmB,SAAgB,SAAA,EAAmB;AACpD,QAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,CAAA,EAAI,MAAA,CAAO,OAAO,CAAA,sBAAA,CAAA,EAA0B;AAAA,UACvD,EAAA,EAAI,OAAA;AAAA,UACJ,IAAA,EAAM;AAAA,SACP,CAAA;AAED,QAAA,MAAA,CAAO,KAAA,EAAM;AAAA,MACf,CAAA;AAAA,MAEA,iBAAA,CACE,OAAA,EACA,SAAA,EACA,GAAA,EACA;AACA,QAAA,OAAA,CAAQ,MAAM,CAAA,CAAA,EAAI,MAAA,CAAO,OAAO,CAAA,oBAAA,EAAuB,GAAA,CAAI,IAAI,CAAA,CAAA,EAAI;AAAA,UACjE,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;AAAA,MACf,CAAA;AAAA,MAEA,QAAA,GAAW;AACT,QAAA,MAAA,CAAO,KAAA,EAAM;AAAA,MACf;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 showParamsDiff: 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","// 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 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 console.log(`[${context}] ${parts.join(\", \")}`);\n};\n","// packages/logger-plugin/modules/plugin.ts\n\nimport { DEFAULT_CONFIG } from \"./constants\";\nimport {\n createGroupManager,\n supportsConsoleGroups,\n} from \"./internal/console-groups\";\nimport { formatRouteName } from \"./internal/formatting\";\nimport { getParamsDiff, logParamsDiff } from \"./internal/params-diff\";\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 *\n * @returns Plugin factory function for real-router\n *\n * @example\n * ```ts\n * import { loggerPluginFactory } from \"@real-router/logger-plugin\";\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\n return () => {\n const config = DEFAULT_CONFIG;\n\n // Create helper managers\n const groups = createGroupManager(supportsConsoleGroups());\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 console.log(`[${config.context}] Router started`);\n },\n\n onStop() {\n groups.close();\n console.log(`[${config.context}] Router stopped`);\n },\n\n onTransitionStart(toState: State, fromState?: State) {\n groups.open(\"Router transition\");\n\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n\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 onTransitionSuccess(toState: State, fromState?: State) {\n console.log(`[${config.context}] Transition success`, {\n to: toState,\n from: fromState,\n });\n\n groups.close();\n },\n\n onTransitionCancel(toState: State, fromState?: State) {\n console.warn(`[${config.context}] Transition cancelled`, {\n to: toState,\n from: fromState,\n });\n\n groups.close();\n },\n\n onTransitionError(\n toState: State | undefined,\n fromState: State | undefined,\n err: RouterError,\n ) {\n console.error(`[${config.context}] Transition error: ${err.code}`, {\n error: err,\n stack: err.stack,\n to: toState,\n from: fromState,\n });\n\n groups.close();\n },\n\n teardown() {\n groups.close();\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":
|
|
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}}}
|
package/dist/esm/index.d.mts
CHANGED
|
@@ -1,45 +1,32 @@
|
|
|
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
|
-
*
|
|
8
|
-
* @returns Plugin factory function for real-router
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* import { loggerPluginFactory } from "@real-router/logger-plugin";
|
|
13
|
-
*
|
|
14
|
-
* router.usePlugin(loggerPluginFactory());
|
|
15
|
-
* ```
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* ```ts
|
|
19
|
-
* // Use with default configuration
|
|
20
|
-
* router.usePlugin(loggerPluginFactory());
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
declare function loggerPluginFactory(): PluginFactory;
|
|
24
|
-
/**
|
|
25
|
-
* Default logger plugin instance with standard configuration.
|
|
26
|
-
* Provided for backward compatibility with existing code.
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* // Use default configuration
|
|
30
|
-
* router.usePlugin(loggerPlugin);
|
|
31
|
-
*/
|
|
32
|
-
declare const loggerPlugin: PluginFactory;
|
|
33
|
-
|
|
34
3
|
/**
|
|
35
4
|
* Logging level for router events.
|
|
36
5
|
* Controls which events are logged to the console.
|
|
37
6
|
*/
|
|
38
7
|
type LogLevel = "all" | "transitions" | "errors" | "none";
|
|
39
8
|
/**
|
|
40
|
-
* Configuration options for the logger
|
|
9
|
+
* Configuration options for the logger-plugin.
|
|
41
10
|
*/
|
|
42
11
|
interface LoggerPluginConfig {
|
|
12
|
+
/**
|
|
13
|
+
* Use Performance API to create marks and measures.
|
|
14
|
+
* Enables integration with browser DevTools Performance tab.
|
|
15
|
+
*
|
|
16
|
+
* Creates marks:
|
|
17
|
+
* - `router:transition-start:{from}→{to}`
|
|
18
|
+
* - `router:transition-end:{from}→{to}` (success)
|
|
19
|
+
* - `router:transition-cancel:{from}→{to}` (cancelled)
|
|
20
|
+
* - `router:transition-error:{from}→{to}` (error)
|
|
21
|
+
*
|
|
22
|
+
* Creates measures:
|
|
23
|
+
* - `router:transition:{from}→{to}` (success)
|
|
24
|
+
* - `router:transition-cancelled:{from}→{to}` (cancelled)
|
|
25
|
+
* - `router:transition-failed:{from}→{to}` (error)
|
|
26
|
+
*
|
|
27
|
+
* @default false
|
|
28
|
+
*/
|
|
29
|
+
usePerformanceMarks?: boolean;
|
|
43
30
|
/**
|
|
44
31
|
* Logging level - controls what router events to log.
|
|
45
32
|
*
|
|
@@ -51,6 +38,13 @@ interface LoggerPluginConfig {
|
|
|
51
38
|
* @default 'all'
|
|
52
39
|
*/
|
|
53
40
|
level?: LogLevel;
|
|
41
|
+
/**
|
|
42
|
+
* Show execution time in milliseconds for transitions.
|
|
43
|
+
* Helps identify slow route changes.
|
|
44
|
+
*
|
|
45
|
+
* @default true
|
|
46
|
+
*/
|
|
47
|
+
showTiming?: boolean;
|
|
54
48
|
/**
|
|
55
49
|
* Show diff of changed route parameters between transitions.
|
|
56
50
|
* Only applies when navigating within the same route.
|
|
@@ -60,7 +54,7 @@ interface LoggerPluginConfig {
|
|
|
60
54
|
*/
|
|
61
55
|
showParamsDiff?: boolean;
|
|
62
56
|
/**
|
|
63
|
-
* Custom context name for
|
|
57
|
+
* Custom context name for console.
|
|
64
58
|
* Useful when running multiple routers.
|
|
65
59
|
*
|
|
66
60
|
* @default 'logger-plugin'
|
|
@@ -68,4 +62,38 @@ interface LoggerPluginConfig {
|
|
|
68
62
|
context?: string;
|
|
69
63
|
}
|
|
70
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
|
+
|
|
71
99
|
export { type LogLevel, type LoggerPluginConfig, loggerPlugin, loggerPluginFactory };
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
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
|
package/dist/esm/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/constants.ts","../../src/internal/console-groups.ts","../../src/internal/formatting.ts","../../src/internal/params-diff.ts","../../src/plugin.ts"],"names":[],"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 showParamsDiff: 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","// 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 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 console.log(`[${context}] ${parts.join(\", \")}`);\n};\n","// packages/logger-plugin/modules/plugin.ts\n\nimport { DEFAULT_CONFIG } from \"./constants\";\nimport {\n createGroupManager,\n supportsConsoleGroups,\n} from \"./internal/console-groups\";\nimport { formatRouteName } from \"./internal/formatting\";\nimport { getParamsDiff, logParamsDiff } from \"./internal/params-diff\";\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 *\n * @returns Plugin factory function for real-router\n *\n * @example\n * ```ts\n * import { loggerPluginFactory } from \"@real-router/logger-plugin\";\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\n return () => {\n const config = DEFAULT_CONFIG;\n\n // Create helper managers\n const groups = createGroupManager(supportsConsoleGroups());\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 console.log(`[${config.context}] Router started`);\n },\n\n onStop() {\n groups.close();\n console.log(`[${config.context}] Router stopped`);\n },\n\n onTransitionStart(toState: State, fromState?: State) {\n groups.open(\"Router transition\");\n\n const fromRoute = formatRouteName(fromState);\n const toRoute = formatRouteName(toState);\n\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 onTransitionSuccess(toState: State, fromState?: State) {\n console.log(`[${config.context}] Transition success`, {\n to: toState,\n from: fromState,\n });\n\n groups.close();\n },\n\n onTransitionCancel(toState: State, fromState?: State) {\n console.warn(`[${config.context}] Transition cancelled`, {\n to: toState,\n from: fromState,\n });\n\n groups.close();\n },\n\n onTransitionError(\n toState: State | undefined,\n fromState: State | undefined,\n err: RouterError,\n ) {\n console.error(`[${config.context}] Transition error: ${err.code}`, {\n error: err,\n stack: err.stack,\n to: toState,\n from: fromState,\n });\n\n groups.close();\n },\n\n teardown() {\n groups.close();\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.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":
|
|
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.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"type": "commonjs",
|
|
5
5
|
"description": "Development logging plugin with transition tracking and performance metrics",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
},
|
|
54
54
|
"sideEffects": false,
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@real-router/core": "workspace:^"
|
|
56
|
+
"@real-router/core": "workspace:^",
|
|
57
|
+
"logger": "workspace:^"
|
|
57
58
|
}
|
|
58
59
|
}
|