@marianmeres/simple-router 2.0.1 â 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +347 -66
- package/dist/mod.d.ts +4 -0
- package/dist/mod.js +3 -0
- package/dist/route.d.ts +88 -9
- package/dist/route.js +248 -0
- package/dist/router.d.ts +242 -27
- package/dist/router.js +255 -0
- package/package.json +19 -49
- package/dist/index.cjs +0 -244
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -241
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 Marian Meres
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,79 +1,360 @@
|
|
|
1
1
|
# @marianmeres/simple-router
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
A lightweight, framework-agnostic string pattern matcher and router with support for dynamic parameters, wildcards, query strings, and reactive subscriptions.
|
|
4
|
+
|
|
5
|
+
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.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- âĻ Dynamic route parameters with optional regex constraints
|
|
10
|
+
- ðŊ Wildcard and catch-all routes
|
|
11
|
+
- ðĶ Spread parameters for multi-segment matching
|
|
12
|
+
- ð Query string parsing (with option to disable per route)
|
|
13
|
+
- ð Reactive subscriptions (Svelte store contract compatible)
|
|
14
|
+
- ðŠķ Zero dependencies (except `@marianmeres/pubsub` for subscriptions)
|
|
15
|
+
- ð Full TypeScript support
|
|
16
|
+
- ðĻ Framework-agnostic
|
|
6
17
|
|
|
7
18
|
## Installation
|
|
8
19
|
|
|
9
20
|
```shell
|
|
10
|
-
|
|
21
|
+
deno add "jsr:@marianmeres/simple-router"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
```shell
|
|
25
|
+
npm install @marianmeres/simple-router
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { SimpleRouter } from "@marianmeres/simple-router";
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Quick Example
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { SimpleRouter } from "@marianmeres/simple-router";
|
|
36
|
+
|
|
37
|
+
// Routes can be defined via constructor config
|
|
38
|
+
const router = new SimpleRouter({
|
|
39
|
+
"/": () => HomePage,
|
|
40
|
+
"/about": () => AboutPage,
|
|
41
|
+
"*": () => NotFoundPage, // catch-all fallback
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Or via the "on" API
|
|
45
|
+
router.on("/user/[id([0-9]+)]", (params) => {
|
|
46
|
+
console.log("User ID:", params?.id);
|
|
47
|
+
return UserPage(params?.id);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
router.on("/article/[id]/[slug]", ({ id, slug }) => {
|
|
51
|
+
return ArticlePage(id, slug);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Execute route matching
|
|
55
|
+
const component = router.exec("/user/123");
|
|
56
|
+
|
|
57
|
+
// Use with hash routing
|
|
58
|
+
window.onhashchange = () => {
|
|
59
|
+
const component = router.exec(location.hash.slice(1));
|
|
60
|
+
render(component);
|
|
61
|
+
};
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Route Patterns
|
|
65
|
+
|
|
66
|
+
### Basic Segments
|
|
67
|
+
|
|
68
|
+
- `exact` - Matches exactly "exact"
|
|
69
|
+
- `[name]` - Matches any segment, captured as `{ name: "value" }`
|
|
70
|
+
- `[name(regex)]` - Matches if regex test passes
|
|
71
|
+
- `[name]?` - Optional segment
|
|
72
|
+
- `[...name]` - Spread params (matches multiple segments)
|
|
73
|
+
- `*` - Wildcard (matches zero or more segments)
|
|
74
|
+
|
|
75
|
+
### Separators
|
|
76
|
+
|
|
77
|
+
The default separator is `/`. Multiple separators are normalized to single, and separators are trimmed from both ends before matching.
|
|
78
|
+
|
|
79
|
+
## Pattern Examples
|
|
80
|
+
|
|
81
|
+
| Route Pattern | URL Input | Params Result |
|
|
82
|
+
| ----------------------------- | ------------------ | -------------------------------- |
|
|
83
|
+
| `/foo` | `/bar` | `null` (no match) |
|
|
84
|
+
| `/foo` | (empty) | `null` |
|
|
85
|
+
| `/foo/[bar]` | `/foo` | `null` |
|
|
86
|
+
| `/` | (empty) | `{}` |
|
|
87
|
+
| `foo` | `foo` | `{}` |
|
|
88
|
+
| `//foo///bar.baz/` | `foo/bar.baz` | `{}` |
|
|
89
|
+
| `/[foo]` | `/bar` | `{ foo: "bar" }` |
|
|
90
|
+
| `#/[foo]/[bar]` | `#/baz/bat` | `{ foo: "baz", bar: "bat" }` |
|
|
91
|
+
| `/[id([0-9]+)]` | `/123` | `{ id: "123" }` |
|
|
92
|
+
| `/[id([0-9]+)]` | `/foo` | `null` (regex fails) |
|
|
93
|
+
| `/foo/[bar]/[id([0-9]+)]` | `/foo/baz/123` | `{ bar: "baz", id: "123" }` |
|
|
94
|
+
| `/foo/[bar]?` | `/foo` | `{}` |
|
|
95
|
+
| `/foo/[bar]?` | `/foo/bar` | `{ bar: "bar" }` |
|
|
96
|
+
| `/foo/[bar]?/baz` | `/foo/bar/baz` | `{ bar: "bar" }` |
|
|
97
|
+
| `/[...path]/[file]` | `/foo/bar/baz.js` | `{ path: "foo/bar", file: "baz.js" }` |
|
|
98
|
+
| `/foo/*` | `/foo/bar/baz.js` | `{}` |
|
|
99
|
+
| `/[foo]/*` | `/foo/bar` | `{ foo: "foo" }` |
|
|
100
|
+
|
|
101
|
+
## API Reference
|
|
102
|
+
|
|
103
|
+
### SimpleRouter
|
|
104
|
+
|
|
105
|
+
#### Constructor
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
const router = new SimpleRouter(config?);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
- `config` - Optional object mapping route patterns to callbacks
|
|
112
|
+
|
|
113
|
+
#### Methods
|
|
114
|
+
|
|
115
|
+
##### `on(routes, callback, options?)`
|
|
116
|
+
|
|
117
|
+
Register one or more route patterns with a callback.
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
router.on("/users", () => UsersPage);
|
|
121
|
+
|
|
122
|
+
// Multiple routes to same handler
|
|
123
|
+
router.on(["/", "/home", "/index.html"], () => HomePage);
|
|
124
|
+
|
|
125
|
+
// With dynamic params
|
|
126
|
+
router.on("/user/[id]", (params) => UserPage(params?.id));
|
|
127
|
+
|
|
128
|
+
// With regex constraint
|
|
129
|
+
router.on("/post/[id([0-9]+)]", (params) => PostPage(params?.id));
|
|
130
|
+
|
|
131
|
+
// With label for debugging
|
|
132
|
+
router.on("/admin", () => AdminPage, { label: "admin-dashboard" });
|
|
133
|
+
|
|
134
|
+
// Disable query param parsing for this route
|
|
135
|
+
router.on("/raw", (params) => RawPage, { allowQueryParams: false });
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Options:**
|
|
139
|
+
- `label` - Optional label for debugging (visible via `info()`)
|
|
140
|
+
- `allowQueryParams` - Whether to parse query parameters (default: `true`)
|
|
141
|
+
|
|
142
|
+
**Important:** Routes are matched in registration order. First match wins!
|
|
143
|
+
|
|
144
|
+
##### `exec(url, fallbackFn?)`
|
|
145
|
+
|
|
146
|
+
Execute route matching against a URL.
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
const result = router.exec("/users");
|
|
150
|
+
|
|
151
|
+
// With fallback
|
|
152
|
+
router.exec("/unknown", () => console.log("Not found"));
|
|
153
|
+
|
|
154
|
+
// With query params
|
|
155
|
+
router.exec("/search?q=hello");
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Returns the value returned by the matched callback, or `false` if no match.
|
|
159
|
+
|
|
160
|
+
##### `subscribe(callback)`
|
|
161
|
+
|
|
162
|
+
Subscribe to router state changes. Follows the [Svelte store contract](https://svelte.dev/docs#Store_contract).
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
const { unsubscribe } = router.subscribe((state) => {
|
|
166
|
+
console.log("Route:", state.route);
|
|
167
|
+
console.log("Params:", state.params);
|
|
168
|
+
console.log("Label:", state.label);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Later
|
|
172
|
+
unsubscribe();
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
The callback is called immediately with the current state, then on every route change.
|
|
176
|
+
|
|
177
|
+
##### `reset()`
|
|
178
|
+
|
|
179
|
+
Clears all registered routes (except catch-all).
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
router.reset().on("/new-route", () => NewPage);
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
##### `info()`
|
|
186
|
+
|
|
187
|
+
Returns a map of registered routes to their labels (for debugging).
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
router.on("/users", () => {}, { label: "users-list" });
|
|
191
|
+
console.log(router.info()); // { "/users": "users-list" }
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
#### Properties
|
|
195
|
+
|
|
196
|
+
##### `current`
|
|
197
|
+
|
|
198
|
+
Gets the current router state (readonly).
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
router.exec("/user/123");
|
|
202
|
+
console.log(router.current);
|
|
203
|
+
// { route: "/user/[id]", params: { id: "123" }, label: null }
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
##### `static debug`
|
|
207
|
+
|
|
208
|
+
Enable/disable debug logging.
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
SimpleRouter.debug = true;
|
|
212
|
+
router.exec("/test"); // Logs matching details to console
|
|
11
213
|
```
|
|
12
214
|
|
|
13
|
-
|
|
215
|
+
### SimpleRoute
|
|
216
|
+
|
|
217
|
+
Low-level route parser. Usually you don't need to use this directly.
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
import { SimpleRoute } from "@marianmeres/simple-router";
|
|
14
221
|
|
|
15
|
-
|
|
16
|
-
|
|
222
|
+
const route = new SimpleRoute("/user/[id([0-9]+)]");
|
|
223
|
+
const params = route.parse("/user/123");
|
|
224
|
+
console.log(params); // { id: "123" }
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
#### Static Methods
|
|
228
|
+
|
|
229
|
+
##### `parseQueryString(str)`
|
|
230
|
+
|
|
231
|
+
Parse a query string into an object.
|
|
232
|
+
|
|
233
|
+
```ts
|
|
234
|
+
SimpleRoute.parseQueryString("foo=bar&baz=123");
|
|
235
|
+
// Returns: { foo: "bar", baz: "123" }
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## TypeScript
|
|
239
|
+
|
|
240
|
+
Full TypeScript support with exported types:
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
import type {
|
|
244
|
+
RouteParams,
|
|
245
|
+
RouteCallback,
|
|
246
|
+
RouterConfig,
|
|
247
|
+
RouterCurrent,
|
|
248
|
+
RouterOnOptions,
|
|
249
|
+
RouterSubscriber,
|
|
250
|
+
RouterSubscription,
|
|
251
|
+
} from "@marianmeres/simple-router";
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## Advanced Examples
|
|
255
|
+
|
|
256
|
+
### SPA with Hash Routing
|
|
257
|
+
|
|
258
|
+
```ts
|
|
17
259
|
const router = new SimpleRouter({
|
|
18
|
-
|
|
19
|
-
|
|
260
|
+
"/": () => HomePage,
|
|
261
|
+
"/about": () => AboutPage,
|
|
262
|
+
"/user/[id]": (params) => UserPage(params?.id),
|
|
263
|
+
"*": () => NotFoundPage,
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
function render(component) {
|
|
267
|
+
document.getElementById("app").innerHTML = component;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
window.addEventListener("hashchange", () => {
|
|
271
|
+
const path = location.hash.slice(1) || "/";
|
|
272
|
+
const component = router.exec(path);
|
|
273
|
+
render(component);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// Trigger initial render
|
|
277
|
+
window.dispatchEvent(new HashChangeEvent("hashchange"));
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Route Priority
|
|
281
|
+
|
|
282
|
+
Routes are matched in registration order (first match wins):
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
const router = new SimpleRouter();
|
|
286
|
+
|
|
287
|
+
// Register generic route first
|
|
288
|
+
router.on("/user/[id]", (params) => {
|
|
289
|
+
console.log("Generic:", params?.id); // This will match
|
|
20
290
|
});
|
|
21
291
|
|
|
22
|
-
//
|
|
23
|
-
router.on(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
292
|
+
// Specific route registered second (won't match "/user/admin")
|
|
293
|
+
router.on("/user/admin", () => {
|
|
294
|
+
console.log("Admin"); // This won't be reached
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
router.exec("/user/admin"); // Logs: "Generic: admin"
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
To fix, register more specific routes first:
|
|
301
|
+
|
|
302
|
+
```ts
|
|
303
|
+
router.on("/user/admin", () => console.log("Admin"));
|
|
304
|
+
router.on("/user/[id]", (params) => console.log("User:", params?.id));
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Beyond URLs: General Pattern Matching
|
|
308
|
+
|
|
309
|
+
The router can match any string patterns, not just URLs:
|
|
310
|
+
|
|
311
|
+
```ts
|
|
312
|
+
// File path routing
|
|
313
|
+
const fileRouter = new SimpleRouter({
|
|
314
|
+
"src/[module]/[file].ts": ({ module, file }) =>
|
|
315
|
+
console.log(`Module: ${module}, File: ${file}`),
|
|
316
|
+
"assets/images/[...path]": ({ path }) =>
|
|
317
|
+
console.log(`Image path: ${path}`),
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
fileRouter.exec("src/components/Button.ts");
|
|
321
|
+
// Logs: "Module: components, File: Button"
|
|
322
|
+
|
|
323
|
+
fileRouter.exec("assets/images/icons/user.png");
|
|
324
|
+
// Logs: "Image path: icons/user.png"
|
|
325
|
+
|
|
326
|
+
// Command routing
|
|
327
|
+
const cmdRouter = new SimpleRouter({
|
|
328
|
+
"user:create": () => createUser(),
|
|
329
|
+
"user:delete:[id([0-9]+)]": ({ id }) => deleteUser(id),
|
|
330
|
+
"cache:clear:[type(redis|memcached)]?": ({ type = "all" }) =>
|
|
331
|
+
clearCache(type),
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
cmdRouter.exec("user:delete:123");
|
|
335
|
+
cmdRouter.exec("cache:clear:redis");
|
|
336
|
+
cmdRouter.exec("cache:clear"); // type defaults to "all"
|
|
337
|
+
|
|
338
|
+
// Custom separator (anything that's not a special regex char works)
|
|
339
|
+
const dotRouter = new SimpleRouter({
|
|
340
|
+
"app.settings.theme": () => "Theme settings",
|
|
341
|
+
"app.settings.[section]": ({ section }) => `Settings: ${section}`,
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
dotRouter.exec("app.settings.profile");
|
|
345
|
+
// Returns: "Settings: profile"
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
|
|
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
|
|
79
356
|
|
|
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
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { SimpleRoute } from "./route.js";
|
|
2
|
+
export { SimpleRouter } from "./router.js";
|
|
3
|
+
export type { RouteConfig, RouteParams } from "./route.js";
|
|
4
|
+
export type { RouteCallback, RouterConfig, RouterCurrent, RouterOnOptions, RouterSubscriber, RouterSubscription, } from "./router.js";
|
package/dist/mod.js
ADDED
package/dist/route.d.ts
CHANGED
|
@@ -1,19 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for a single route segment.
|
|
3
|
+
* @internal
|
|
4
|
+
*/
|
|
1
5
|
export interface RouteConfig {
|
|
2
6
|
segment: string;
|
|
3
|
-
name: string;
|
|
7
|
+
name: string | null;
|
|
4
8
|
test: RegExp;
|
|
5
9
|
isOptional: boolean;
|
|
6
10
|
isSpread: boolean;
|
|
7
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Route parameters extracted from URL segments and query strings.
|
|
14
|
+
*/
|
|
15
|
+
export type RouteParams = Record<string, any>;
|
|
8
16
|
export declare class SimpleRoute {
|
|
9
|
-
|
|
17
|
+
#private;
|
|
18
|
+
readonly route: string;
|
|
19
|
+
/** Separator used to split URL paths into segments */
|
|
10
20
|
static SPLITTER: string;
|
|
21
|
+
/** Wildcard symbol for catch-all routes */
|
|
11
22
|
static WILDCARD: string;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Creates a new SimpleRoute instance.
|
|
25
|
+
*
|
|
26
|
+
* @param route - Pattern string to match against (URL, file path, command, or any string identifier)
|
|
27
|
+
* @throws {Error} If route pattern is invalid (e.g., multiple spread segments)
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* // URL patterns
|
|
32
|
+
* new SimpleRoute("/user/[id]");
|
|
33
|
+
* new SimpleRoute("/post/[id([0-9]+)]");
|
|
34
|
+
* new SimpleRoute("/api/[...path]");
|
|
35
|
+
*
|
|
36
|
+
* // File path patterns
|
|
37
|
+
* new SimpleRoute("src/[module]/[file].ts");
|
|
38
|
+
*
|
|
39
|
+
* // Command patterns
|
|
40
|
+
* new SimpleRoute("user:delete:[id]");
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
constructor(route: string);
|
|
44
|
+
/**
|
|
45
|
+
* Parses a query string into an object of key-value pairs.
|
|
46
|
+
* Handles URL decoding of both keys and values.
|
|
47
|
+
*
|
|
48
|
+
* @param str - Query string (without leading "?")
|
|
49
|
+
* @returns Object with parsed query parameters
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* SimpleRoute.parseQueryString("foo=bar&baz=123");
|
|
54
|
+
* // Returns: { foo: "bar", baz: "123" }
|
|
55
|
+
*
|
|
56
|
+
* SimpleRoute.parseQueryString("name=John%20Doe");
|
|
57
|
+
* // Returns: { name: "John Doe" }
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
static parseQueryString(str: string): RouteParams;
|
|
61
|
+
/**
|
|
62
|
+
* Parses a string against this route pattern.
|
|
63
|
+
* Returns extracted parameters if the string matches, null otherwise.
|
|
64
|
+
*
|
|
65
|
+
* @param url - String to test against the pattern (can be a URL, file path, command, etc.)
|
|
66
|
+
* @param allowQueryParams - Whether to parse query string parameters (default: true)
|
|
67
|
+
* @returns Object with extracted parameters, or null if no match
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* // URL matching
|
|
72
|
+
* const route = new SimpleRoute("/user/[id]");
|
|
73
|
+
*
|
|
74
|
+
* route.parse("/user/123");
|
|
75
|
+
* // Returns: { id: "123" }
|
|
76
|
+
*
|
|
77
|
+
* route.parse("/user/123?tab=profile");
|
|
78
|
+
* // Returns: { id: "123", tab: "profile" }
|
|
79
|
+
*
|
|
80
|
+
* route.parse("/user/123?tab=profile", false);
|
|
81
|
+
* // Returns: { id: "123?tab=profile" } - query string not parsed
|
|
82
|
+
*
|
|
83
|
+
* route.parse("/post/456");
|
|
84
|
+
* // Returns: null - no match
|
|
85
|
+
*
|
|
86
|
+
* // File path matching
|
|
87
|
+
* const fileRoute = new SimpleRoute("src/[module]/[file].ts");
|
|
88
|
+
* fileRoute.parse("src/components/Button.ts");
|
|
89
|
+
* // Returns: { module: "components", file: "Button" }
|
|
90
|
+
*
|
|
91
|
+
* // Command matching
|
|
92
|
+
* const cmdRoute = new SimpleRoute("user:delete:[id]");
|
|
93
|
+
* cmdRoute.parse("user:delete:123");
|
|
94
|
+
* // Returns: { id: "123" }
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
parse(url: string, allowQueryParams?: boolean): RouteParams | null;
|
|
19
98
|
}
|