@tripod311/flow 0.0.0
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 +93 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +135 -0
- package/dist/index.js.map +1 -0
- package/package.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Flow Router
|
|
2
|
+
|
|
3
|
+
A minimalistic client-side router built on top of the native `history API`.
|
|
4
|
+
Perfect for SPAs, easy to embed into any project, and just a few kilobytes in size.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **Zero dependencies** — pure TypeScript/JavaScript.
|
|
11
|
+
- **Supports static, parametric, and wildcard routes.**
|
|
12
|
+
- **Automatic route prioritization (static > parametric > wildcard).**
|
|
13
|
+
- **Direct control over the history API (`pushState`, `replaceState`).**
|
|
14
|
+
- **Fallback handler for unmatched routes.**
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install flow-router
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Or simply copy the file into your project.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Example Usage
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
const router = new Flow();
|
|
32
|
+
|
|
33
|
+
router.add("/", () => {
|
|
34
|
+
console.log("Home page");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
router.add("/about", () => {
|
|
38
|
+
console.log("About page");
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
router.add("/user/:id", (params) => {
|
|
42
|
+
console.log("User page:", params.id);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
router.add("/files/*", (params) => {
|
|
46
|
+
console.log("Files path:", params[0]);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
router.setFallback(() => {
|
|
50
|
+
console.log("404 Not Found");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
router.init();
|
|
54
|
+
|
|
55
|
+
// Navigate programmatically:
|
|
56
|
+
router.navigate("/about");
|
|
57
|
+
router.navigate("/user/42");
|
|
58
|
+
router.navigate("/files/images/avatar.png");
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## API
|
|
64
|
+
|
|
65
|
+
### `router.init()`
|
|
66
|
+
Starts listening to `popstate` events and performs the initial route matching for the current URL.
|
|
67
|
+
|
|
68
|
+
### `router.deinit()`
|
|
69
|
+
Stops listening to `popstate` events.
|
|
70
|
+
|
|
71
|
+
### `router.add(path: string, handler: RouteHandler)`
|
|
72
|
+
Registers a new route.
|
|
73
|
+
- `:param` — parametric segment.
|
|
74
|
+
- `*` — wildcard segment (must be the last one).
|
|
75
|
+
|
|
76
|
+
Examples:
|
|
77
|
+
- `/user/:id` → `{ id: "42" }`
|
|
78
|
+
- `/files/*` → `{ 0: "images/avatar.png" }`
|
|
79
|
+
|
|
80
|
+
### `router.setFallback(handler: () => void)`
|
|
81
|
+
Sets a fallback handler that runs when no routes match.
|
|
82
|
+
|
|
83
|
+
### `router.match(path: string)`
|
|
84
|
+
Performs a manual match of the given path (usually called internally).
|
|
85
|
+
|
|
86
|
+
### `router.navigate(path: string, replace: boolean = false)`
|
|
87
|
+
Changes the URL via `pushState` or `replaceState` and runs the matched route handler.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## License
|
|
92
|
+
|
|
93
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type RouteHandler = (routeParams: Record<string, string>, urlParams: URLSearchParams) => void;
|
|
2
|
+
export interface Route {
|
|
3
|
+
pathname: string;
|
|
4
|
+
pattern: RegExp;
|
|
5
|
+
keys: string[];
|
|
6
|
+
staticParts: number;
|
|
7
|
+
parametricParts: number;
|
|
8
|
+
handler: RouteHandler;
|
|
9
|
+
}
|
|
10
|
+
export declare class Flow {
|
|
11
|
+
private staticRoutes;
|
|
12
|
+
private parametricRoutes;
|
|
13
|
+
private wildcardRoutes;
|
|
14
|
+
private fallback?;
|
|
15
|
+
private stateListener;
|
|
16
|
+
constructor();
|
|
17
|
+
init(): void;
|
|
18
|
+
deinit(): void;
|
|
19
|
+
setFallback(handler: () => void): void;
|
|
20
|
+
add(path: string, handler: RouteHandler): void;
|
|
21
|
+
private injectRoute;
|
|
22
|
+
private static pathToRegex;
|
|
23
|
+
match(path: string): void;
|
|
24
|
+
navigate(path: string, replace?: boolean): void;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,EAAE,eAAe,KAAK,IAAI,CAAC;AAErG,MAAM,WAAW,KAAK;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,YAAY,CAAC;CACtB;AAED,qBAAa,IAAI;IAChB,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,gBAAgB,CAAe;IACvC,OAAO,CAAC,cAAc,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,CAAa;IAC9B,OAAO,CAAC,aAAa,CAAa;;IAQlC,IAAI;IAMJ,MAAM;IAIN,WAAW,CAAE,OAAO,EAAE,MAAM,IAAI;IAIhC,GAAG,CAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY;IAoCxC,OAAO,CAAC,WAAW;IAmBnB,OAAO,CAAC,MAAM,CAAC,WAAW;IAuB1B,KAAK,CAAE,IAAI,EAAE,MAAM;IA4CnB,QAAQ,CAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,OAAe;CAShD"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
export class Flow {
|
|
2
|
+
staticRoutes = [];
|
|
3
|
+
parametricRoutes = [];
|
|
4
|
+
wildcardRoutes = [];
|
|
5
|
+
fallback;
|
|
6
|
+
stateListener;
|
|
7
|
+
constructor() {
|
|
8
|
+
this.stateListener = () => {
|
|
9
|
+
this.match(location.pathname);
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
init() {
|
|
13
|
+
window.addEventListener("popstate", this.stateListener);
|
|
14
|
+
this.match(location.pathname);
|
|
15
|
+
}
|
|
16
|
+
deinit() {
|
|
17
|
+
window.removeEventListener("popstate", this.stateListener);
|
|
18
|
+
}
|
|
19
|
+
setFallback(handler) {
|
|
20
|
+
this.fallback = handler;
|
|
21
|
+
}
|
|
22
|
+
add(path, handler) {
|
|
23
|
+
const { pattern, keys } = Flow.pathToRegex(path);
|
|
24
|
+
const route = {
|
|
25
|
+
pathname: path,
|
|
26
|
+
pattern: pattern,
|
|
27
|
+
keys: keys,
|
|
28
|
+
staticParts: 0,
|
|
29
|
+
parametricParts: 0,
|
|
30
|
+
handler: handler
|
|
31
|
+
};
|
|
32
|
+
let isWildCard = false;
|
|
33
|
+
const sp = path.split('/');
|
|
34
|
+
for (const hop of sp) {
|
|
35
|
+
if (hop === "*") {
|
|
36
|
+
if (sp.indexOf(hop) !== sp.length - 1) {
|
|
37
|
+
console.warn(`Wildcard '*' should be last hop: ${path}`);
|
|
38
|
+
}
|
|
39
|
+
isWildCard = true;
|
|
40
|
+
}
|
|
41
|
+
else if (hop.charAt(0) === ':') {
|
|
42
|
+
route.parametricParts++;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
route.staticParts++;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (isWildCard) {
|
|
49
|
+
this.injectRoute(route, this.wildcardRoutes);
|
|
50
|
+
}
|
|
51
|
+
else if (route.parametricParts > 0) {
|
|
52
|
+
this.injectRoute(route, this.parametricRoutes);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
this.injectRoute(route, this.staticRoutes);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
injectRoute(route, collection) {
|
|
59
|
+
let index = 0;
|
|
60
|
+
while (index < collection.length) {
|
|
61
|
+
const r = collection[index];
|
|
62
|
+
if ((r.parametricParts < route.parametricParts) ||
|
|
63
|
+
(r.parametricParts === route.parametricParts && r.staticParts < route.staticParts)) {
|
|
64
|
+
collection.splice(index, 0, route);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
index++;
|
|
68
|
+
}
|
|
69
|
+
collection.push(route);
|
|
70
|
+
}
|
|
71
|
+
static pathToRegex(path) {
|
|
72
|
+
const keys = [];
|
|
73
|
+
const regex = path
|
|
74
|
+
.split("/")
|
|
75
|
+
.map(seg => {
|
|
76
|
+
if (seg.startsWith(":")) {
|
|
77
|
+
keys.push(seg.slice(1));
|
|
78
|
+
return "([^/]+)";
|
|
79
|
+
}
|
|
80
|
+
if (seg === "*") {
|
|
81
|
+
return "(.*)?";
|
|
82
|
+
}
|
|
83
|
+
return seg.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // escape
|
|
84
|
+
})
|
|
85
|
+
.join("/");
|
|
86
|
+
return {
|
|
87
|
+
pattern: new RegExp("^" + regex + "$"),
|
|
88
|
+
keys
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
match(path) {
|
|
92
|
+
const [pathname, search = ""] = path.split("?");
|
|
93
|
+
const params = new URLSearchParams(search);
|
|
94
|
+
for (const route of this.staticRoutes) {
|
|
95
|
+
if (pathname === route.pathname) {
|
|
96
|
+
route.handler({}, params);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
for (const route of this.parametricRoutes) {
|
|
101
|
+
const match = pathname.match(route.pattern);
|
|
102
|
+
if (match !== null) {
|
|
103
|
+
const routeParams = {};
|
|
104
|
+
for (let i = 0; i < route.keys.length; i++) {
|
|
105
|
+
routeParams[route.keys[i]] = match[i + 1];
|
|
106
|
+
}
|
|
107
|
+
route.handler(routeParams, params);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
for (const route of this.wildcardRoutes) {
|
|
112
|
+
const match = pathname.match(route.pattern);
|
|
113
|
+
if (match !== null) {
|
|
114
|
+
const routeParams = {};
|
|
115
|
+
for (let i = 0; i < route.keys.length; i++) {
|
|
116
|
+
routeParams[route.keys[i]] = match[i + 1];
|
|
117
|
+
}
|
|
118
|
+
route.handler(routeParams, params);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (this.fallback !== undefined)
|
|
123
|
+
this.fallback();
|
|
124
|
+
}
|
|
125
|
+
navigate(path, replace = false) {
|
|
126
|
+
if (replace) {
|
|
127
|
+
history.replaceState(null, "", path);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
history.pushState(null, "", path);
|
|
131
|
+
}
|
|
132
|
+
this.match(path);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tripod311/flow",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Lightweight minimalistic router for single page applications",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"js",
|
|
7
|
+
"ts"
|
|
8
|
+
],
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"author": "Tripod ind.tripod@gmail.com",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"main": "dist/index.js",
|
|
13
|
+
"types": "dist/index.d.ts",
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"typescript": "^5.9.2"
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/Tripod311/flow.git"
|
|
27
|
+
}
|
|
28
|
+
}
|