@marianmeres/simple-router 2.2.3 → 3.0.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 +27 -18
- package/dist/mod.d.ts +1 -1
- package/dist/route.d.ts +8 -2
- package/dist/route.js +8 -2
- package/dist/router.d.ts +48 -14
- package/dist/router.js +45 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# @marianmeres/simple-router
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@marianmeres/simple-router)
|
|
4
|
+
[](https://jsr.io/@marianmeres/simple-router)
|
|
5
|
+
|
|
3
6
|
A lightweight, framework-agnostic string pattern matcher and router with support for dynamic parameters, wildcards, query strings, and reactive subscriptions.
|
|
4
7
|
|
|
5
8
|
Can match any string identifiers - URLs, file paths, command names, or custom patterns. Originally inspired by [Sapper-like regex routes](https://sapper.svelte.dev/docs#Regexes_in_routes). Primarily designed for client-side SPA routing, but flexible enough for any pattern matching needs.
|
|
@@ -100,15 +103,30 @@ The default separator is `/`. Multiple separators are normalized to single, and
|
|
|
100
103
|
|
|
101
104
|
## API Reference
|
|
102
105
|
|
|
106
|
+
For the complete API documentation with all methods, types, and detailed examples, see [API.md](API.md).
|
|
107
|
+
|
|
103
108
|
### SimpleRouter
|
|
104
109
|
|
|
105
110
|
#### Constructor
|
|
106
111
|
|
|
107
112
|
```ts
|
|
108
|
-
|
|
113
|
+
// Simple config (backwards compatible)
|
|
114
|
+
const router = new SimpleRouter({
|
|
115
|
+
"/": () => HomePage,
|
|
116
|
+
"/about": () => AboutPage
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// With options object (for logger support)
|
|
120
|
+
const router = new SimpleRouter({
|
|
121
|
+
routes: {
|
|
122
|
+
"/": () => HomePage,
|
|
123
|
+
"/about": () => AboutPage
|
|
124
|
+
},
|
|
125
|
+
logger: myLogger // optional, compatible with @marianmeres/clog
|
|
126
|
+
});
|
|
109
127
|
```
|
|
110
128
|
|
|
111
|
-
- `config` -
|
|
129
|
+
- `config` - Either a `RouterConfig` object mapping route patterns to callbacks, or a `RouterOptions` object with `routes` and `logger` properties
|
|
112
130
|
|
|
113
131
|
#### Methods
|
|
114
132
|
|
|
@@ -162,7 +180,7 @@ Returns the value returned by the matched callback, or `false` if no match.
|
|
|
162
180
|
Subscribe to router state changes. Follows the [Svelte store contract](https://svelte.dev/docs#Store_contract).
|
|
163
181
|
|
|
164
182
|
```ts
|
|
165
|
-
const
|
|
183
|
+
const unsubscribe = router.subscribe((state) => {
|
|
166
184
|
console.log("Route:", state.route);
|
|
167
185
|
console.log("Params:", state.params);
|
|
168
186
|
console.log("Label:", state.label);
|
|
@@ -172,7 +190,7 @@ const { unsubscribe } = router.subscribe((state) => {
|
|
|
172
190
|
unsubscribe();
|
|
173
191
|
```
|
|
174
192
|
|
|
175
|
-
The callback is called immediately with the current state, then on every route change.
|
|
193
|
+
Returns an unsubscribe function directly. The callback is called immediately with the current state, then on every route change.
|
|
176
194
|
|
|
177
195
|
##### `reset()`
|
|
178
196
|
|
|
@@ -205,11 +223,11 @@ console.log(router.current);
|
|
|
205
223
|
|
|
206
224
|
##### `static debug`
|
|
207
225
|
|
|
208
|
-
Enable/disable debug logging.
|
|
226
|
+
Enable/disable debug logging. When enabled, uses the logger instance (if provided) or falls back to `console.log`.
|
|
209
227
|
|
|
210
228
|
```ts
|
|
211
229
|
SimpleRouter.debug = true;
|
|
212
|
-
router.exec("/test"); // Logs matching details to console
|
|
230
|
+
router.exec("/test"); // Logs matching details to console (or custom logger)
|
|
213
231
|
```
|
|
214
232
|
|
|
215
233
|
### SimpleRoute
|
|
@@ -241,13 +259,15 @@ Full TypeScript support with exported types:
|
|
|
241
259
|
|
|
242
260
|
```ts
|
|
243
261
|
import type {
|
|
262
|
+
Logger,
|
|
244
263
|
RouteParams,
|
|
245
264
|
RouteCallback,
|
|
246
265
|
RouterConfig,
|
|
247
266
|
RouterCurrent,
|
|
248
267
|
RouterOnOptions,
|
|
268
|
+
RouterOptions,
|
|
249
269
|
RouterSubscriber,
|
|
250
|
-
|
|
270
|
+
RouterUnsubscribe,
|
|
251
271
|
} from "@marianmeres/simple-router";
|
|
252
272
|
```
|
|
253
273
|
|
|
@@ -346,15 +366,4 @@ dotRouter.exec("app.settings.profile");
|
|
|
346
366
|
```
|
|
347
367
|
|
|
348
368
|
|
|
349
|
-
## Links
|
|
350
|
-
|
|
351
|
-
- [Tests](tests/) - Comprehensive test suite with 82+ tests
|
|
352
|
-
- [GitHub Repository](https://github.com/marianmeres/simple-router)
|
|
353
|
-
- [JSR Package](https://jsr.io/@marianmeres/simple-router)
|
|
354
|
-
|
|
355
|
-
## Package Identity
|
|
356
369
|
|
|
357
|
-
- **Name:** @marianmeres/simple-router
|
|
358
|
-
- **Author:** Marian Meres
|
|
359
|
-
- **Repository:** https://github.com/marianmeres/simple-router
|
|
360
|
-
- **License:** MIT
|
package/dist/mod.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { SimpleRoute } from "./route.js";
|
|
2
2
|
export { SimpleRouter } from "./router.js";
|
|
3
3
|
export type { RouteConfig, RouteParams } from "./route.js";
|
|
4
|
-
export type { RouteCallback, RouterConfig, RouterCurrent, RouterOnOptions, RouterSubscriber,
|
|
4
|
+
export type { Logger, RouteCallback, RouterConfig, RouterCurrent, RouterOnOptions, RouterOptions, RouterSubscriber, RouterUnsubscribe, } from "./router.js";
|
package/dist/route.d.ts
CHANGED
|
@@ -16,9 +16,15 @@ export type RouteParams = Record<string, any>;
|
|
|
16
16
|
export declare class SimpleRoute {
|
|
17
17
|
#private;
|
|
18
18
|
readonly route: string;
|
|
19
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Separator used to split paths into segments.
|
|
21
|
+
* @default "/"
|
|
22
|
+
*/
|
|
20
23
|
static SPLITTER: string;
|
|
21
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* Wildcard symbol for catch-all routes. Must be used as the last segment.
|
|
26
|
+
* @default "*"
|
|
27
|
+
*/
|
|
22
28
|
static WILDCARD: string;
|
|
23
29
|
/**
|
|
24
30
|
* Creates a new SimpleRoute instance.
|
package/dist/route.js
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
export class SimpleRoute {
|
|
2
2
|
route;
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Separator used to split paths into segments.
|
|
5
|
+
* @default "/"
|
|
6
|
+
*/
|
|
4
7
|
static SPLITTER = "/";
|
|
5
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* Wildcard symbol for catch-all routes. Must be used as the last segment.
|
|
10
|
+
* @default "*"
|
|
11
|
+
*/
|
|
6
12
|
static WILDCARD = "*";
|
|
7
13
|
#parsed;
|
|
8
14
|
/**
|
package/dist/router.d.ts
CHANGED
|
@@ -61,13 +61,33 @@ export interface RouterOnOptions {
|
|
|
61
61
|
*/
|
|
62
62
|
export type RouterConfig = Record<string, RouteCallback>;
|
|
63
63
|
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
64
|
+
* Logger interface compatible with `@marianmeres/clog`.
|
|
65
|
+
* Provides console-compatible logging methods.
|
|
66
66
|
*/
|
|
67
|
-
export interface
|
|
68
|
-
/**
|
|
69
|
-
|
|
67
|
+
export interface Logger {
|
|
68
|
+
/** Log debug level messages */
|
|
69
|
+
debug: (...args: unknown[]) => unknown;
|
|
70
|
+
/** Log info level messages */
|
|
71
|
+
log: (...args: unknown[]) => unknown;
|
|
72
|
+
/** Log warning level messages */
|
|
73
|
+
warn: (...args: unknown[]) => unknown;
|
|
74
|
+
/** Log error level messages */
|
|
75
|
+
error: (...args: unknown[]) => unknown;
|
|
70
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Options for the SimpleRouter factory/constructor.
|
|
79
|
+
*/
|
|
80
|
+
export interface RouterOptions {
|
|
81
|
+
/** Route configuration mapping patterns to callbacks */
|
|
82
|
+
routes?: RouterConfig | null;
|
|
83
|
+
/** Optional logger instance for debug output (compatible with @marianmeres/clog) */
|
|
84
|
+
logger?: Logger | null;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Unsubscribe function returned by the `subscribe()` method.
|
|
88
|
+
* Follows the Svelte store contract.
|
|
89
|
+
*/
|
|
90
|
+
export type RouterUnsubscribe = () => void;
|
|
71
91
|
/**
|
|
72
92
|
* Subscriber callback function that receives router state changes.
|
|
73
93
|
*
|
|
@@ -106,22 +126,37 @@ export type RouterSubscriber = (current: RouterCurrent) => void;
|
|
|
106
126
|
*/
|
|
107
127
|
export declare class SimpleRouter {
|
|
108
128
|
#private;
|
|
109
|
-
/**
|
|
129
|
+
/**
|
|
130
|
+
* Enable/disable console debug logging for route matching.
|
|
131
|
+
* When enabled, logs route matching details to the console.
|
|
132
|
+
* @default false
|
|
133
|
+
*/
|
|
110
134
|
static debug: boolean;
|
|
111
135
|
/**
|
|
112
136
|
* Creates a new SimpleRouter instance.
|
|
113
137
|
*
|
|
114
|
-
* @param config - Optional configuration object mapping route patterns
|
|
138
|
+
* @param config - Optional configuration: either a RouterConfig object mapping route patterns
|
|
139
|
+
* to callbacks, or a RouterOptions object with routes and logger
|
|
115
140
|
*
|
|
116
141
|
* @example
|
|
117
142
|
* ```ts
|
|
143
|
+
* // Simple config (backwards compatible)
|
|
118
144
|
* const router = new SimpleRouter({
|
|
119
145
|
* "/": () => HomePage,
|
|
120
146
|
* "/about": () => AboutPage
|
|
121
147
|
* });
|
|
148
|
+
*
|
|
149
|
+
* // With options object
|
|
150
|
+
* const router = new SimpleRouter({
|
|
151
|
+
* routes: {
|
|
152
|
+
* "/": () => HomePage,
|
|
153
|
+
* "/about": () => AboutPage
|
|
154
|
+
* },
|
|
155
|
+
* logger: myLogger // optional, compatible with @marianmeres/clog
|
|
156
|
+
* });
|
|
122
157
|
* ```
|
|
123
158
|
*/
|
|
124
|
-
constructor(config?: RouterConfig | null);
|
|
159
|
+
constructor(config?: RouterConfig | RouterOptions | null);
|
|
125
160
|
/**
|
|
126
161
|
* Returns a map of registered route patterns to their labels.
|
|
127
162
|
* Useful for debugging and introspection.
|
|
@@ -189,7 +224,7 @@ export declare class SimpleRouter {
|
|
|
189
224
|
* router.on("*", () => NotFoundPage);
|
|
190
225
|
* ```
|
|
191
226
|
*/
|
|
192
|
-
on(routes: string | string[], cb: RouteCallback,
|
|
227
|
+
on(routes: string | string[], cb: RouteCallback, options?: RouterOnOptions): void;
|
|
193
228
|
/**
|
|
194
229
|
* Executes pattern matching against the provided string.
|
|
195
230
|
* Returns the value returned by the matched route's callback.
|
|
@@ -220,18 +255,17 @@ export declare class SimpleRouter {
|
|
|
220
255
|
* const component = router.exec("/home");
|
|
221
256
|
* ```
|
|
222
257
|
*/
|
|
223
|
-
exec(url: string, fallbackFn?: RouteCallback):
|
|
258
|
+
exec(url: string, fallbackFn?: RouteCallback): unknown;
|
|
224
259
|
/**
|
|
225
260
|
* Subscribes to router state changes.
|
|
226
261
|
* Follows the Svelte store contract - subscriber is called immediately with current state.
|
|
227
|
-
* Compatible with RxJS Observables (returns object with `unsubscribe` method).
|
|
228
262
|
*
|
|
229
263
|
* @param subscription - Callback function that receives router state changes
|
|
230
|
-
* @returns
|
|
264
|
+
* @returns Unsubscribe function
|
|
231
265
|
*
|
|
232
266
|
* @example
|
|
233
267
|
* ```ts
|
|
234
|
-
* const
|
|
268
|
+
* const unsubscribe = router.subscribe((state) => {
|
|
235
269
|
* console.log("Route changed:", state.route);
|
|
236
270
|
* console.log("Params:", state.params);
|
|
237
271
|
* });
|
|
@@ -242,5 +276,5 @@ export declare class SimpleRouter {
|
|
|
242
276
|
*
|
|
243
277
|
* @see https://svelte.dev/docs#Store_contract
|
|
244
278
|
*/
|
|
245
|
-
subscribe(subscription: RouterSubscriber):
|
|
279
|
+
subscribe(subscription: RouterSubscriber): RouterUnsubscribe;
|
|
246
280
|
}
|
package/dist/router.js
CHANGED
|
@@ -32,7 +32,11 @@ const PUBSUB_TOPIC = "current";
|
|
|
32
32
|
* ```
|
|
33
33
|
*/
|
|
34
34
|
export class SimpleRouter {
|
|
35
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* Enable/disable console debug logging for route matching.
|
|
37
|
+
* When enabled, logs route matching details to the console.
|
|
38
|
+
* @default false
|
|
39
|
+
*/
|
|
36
40
|
static debug = false;
|
|
37
41
|
#routes = [];
|
|
38
42
|
#catchAll = null;
|
|
@@ -42,26 +46,58 @@ export class SimpleRouter {
|
|
|
42
46
|
label: null,
|
|
43
47
|
};
|
|
44
48
|
#pubsub = createPubSub();
|
|
49
|
+
#logger = null;
|
|
45
50
|
/**
|
|
46
51
|
* Creates a new SimpleRouter instance.
|
|
47
52
|
*
|
|
48
|
-
* @param config - Optional configuration object mapping route patterns
|
|
53
|
+
* @param config - Optional configuration: either a RouterConfig object mapping route patterns
|
|
54
|
+
* to callbacks, or a RouterOptions object with routes and logger
|
|
49
55
|
*
|
|
50
56
|
* @example
|
|
51
57
|
* ```ts
|
|
58
|
+
* // Simple config (backwards compatible)
|
|
52
59
|
* const router = new SimpleRouter({
|
|
53
60
|
* "/": () => HomePage,
|
|
54
61
|
* "/about": () => AboutPage
|
|
55
62
|
* });
|
|
63
|
+
*
|
|
64
|
+
* // With options object
|
|
65
|
+
* const router = new SimpleRouter({
|
|
66
|
+
* routes: {
|
|
67
|
+
* "/": () => HomePage,
|
|
68
|
+
* "/about": () => AboutPage
|
|
69
|
+
* },
|
|
70
|
+
* logger: myLogger // optional, compatible with @marianmeres/clog
|
|
71
|
+
* });
|
|
56
72
|
* ```
|
|
57
73
|
*/
|
|
58
74
|
constructor(config = null) {
|
|
59
|
-
|
|
75
|
+
let routes = null;
|
|
76
|
+
if (config) {
|
|
77
|
+
// Check if config is RouterOptions (has 'routes' or 'logger' key)
|
|
78
|
+
if ("routes" in config || "logger" in config) {
|
|
79
|
+
const options = config;
|
|
80
|
+
routes = options.routes ?? null;
|
|
81
|
+
this.#logger = options.logger ?? null;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
// Backwards compatible: treat as RouterConfig
|
|
85
|
+
routes = config;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
Object.entries(routes || {}).forEach(([route, cb]) => {
|
|
60
89
|
this.on(route, cb);
|
|
61
90
|
});
|
|
62
91
|
}
|
|
63
92
|
#dbg(...a) {
|
|
64
|
-
SimpleRouter.debug
|
|
93
|
+
if (SimpleRouter.debug) {
|
|
94
|
+
if (this.#logger) {
|
|
95
|
+
this.#logger.log("[SimpleRouter]", ...a);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
console.log("[SimpleRouter]", ...a);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
65
101
|
}
|
|
66
102
|
/**
|
|
67
103
|
* Returns a map of registered route patterns to their labels.
|
|
@@ -140,7 +176,8 @@ export class SimpleRouter {
|
|
|
140
176
|
* router.on("*", () => NotFoundPage);
|
|
141
177
|
* ```
|
|
142
178
|
*/
|
|
143
|
-
on(routes, cb,
|
|
179
|
+
on(routes, cb, options = {}) {
|
|
180
|
+
const { label = null, allowQueryParams = true } = options;
|
|
144
181
|
if (!Array.isArray(routes))
|
|
145
182
|
routes = [routes];
|
|
146
183
|
routes.forEach((route) => {
|
|
@@ -187,7 +224,6 @@ export class SimpleRouter {
|
|
|
187
224
|
* const component = router.exec("/home");
|
|
188
225
|
* ```
|
|
189
226
|
*/
|
|
190
|
-
// deno-lint-ignore no-explicit-any
|
|
191
227
|
exec(url, fallbackFn) {
|
|
192
228
|
const dbgPrefix = `'${url}' -> `;
|
|
193
229
|
for (const [route, cb, allowQueryParams, label] of this.#routes) {
|
|
@@ -221,14 +257,13 @@ export class SimpleRouter {
|
|
|
221
257
|
/**
|
|
222
258
|
* Subscribes to router state changes.
|
|
223
259
|
* Follows the Svelte store contract - subscriber is called immediately with current state.
|
|
224
|
-
* Compatible with RxJS Observables (returns object with `unsubscribe` method).
|
|
225
260
|
*
|
|
226
261
|
* @param subscription - Callback function that receives router state changes
|
|
227
|
-
* @returns
|
|
262
|
+
* @returns Unsubscribe function
|
|
228
263
|
*
|
|
229
264
|
* @example
|
|
230
265
|
* ```ts
|
|
231
|
-
* const
|
|
266
|
+
* const unsubscribe = router.subscribe((state) => {
|
|
232
267
|
* console.log("Route changed:", state.route);
|
|
233
268
|
* console.log("Params:", state.params);
|
|
234
269
|
* });
|
|
@@ -246,10 +281,6 @@ export class SimpleRouter {
|
|
|
246
281
|
const unsubscribe = this.#pubsub.subscribe(PUBSUB_TOPIC, subscription);
|
|
247
282
|
// immediately call with current value (as per store contract)
|
|
248
283
|
subscription(this.#current);
|
|
249
|
-
|
|
250
|
-
// allowed to return an object with an .unsubscribe method
|
|
251
|
-
return {
|
|
252
|
-
unsubscribe,
|
|
253
|
-
};
|
|
284
|
+
return unsubscribe;
|
|
254
285
|
}
|
|
255
286
|
}
|