@constela/router 7.0.0 → 9.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.
Files changed (2) hide show
  1. package/README.md +212 -0
  2. package/package.json +5 -5
package/README.md ADDED
@@ -0,0 +1,212 @@
1
+ # @constela/router
2
+
3
+ Client-side routing for Constela applications using the History API.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @constela/router
9
+ ```
10
+
11
+ **Peer Dependencies:**
12
+ - `@constela/compiler` ^0.7.0
13
+ - `@constela/runtime` ^0.10.1
14
+
15
+ ## Route Definition
16
+
17
+ Define routes in your JSON program:
18
+
19
+ ```json
20
+ {
21
+ "route": {
22
+ "path": "/users/:id",
23
+ "title": { "expr": "bin", "op": "+", "left": { "expr": "lit", "value": "User: " }, "right": { "expr": "route", "name": "id" } },
24
+ "layout": "MainLayout",
25
+ "meta": {
26
+ "description": { "expr": "lit", "value": "User profile page" }
27
+ }
28
+ },
29
+ "state": { ... },
30
+ "actions": [ ... ],
31
+ "view": { ... }
32
+ }
33
+ ```
34
+
35
+ ## Accessing Route Parameters
36
+
37
+ Use the `route` expression in your JSON:
38
+
39
+ **URL parameter** (e.g., `/users/123` → `"123"`):
40
+ ```json
41
+ { "expr": "route", "name": "id", "source": "param" }
42
+ ```
43
+
44
+ **Query string parameter** (e.g., `?tab=settings` → `"settings"`):
45
+ ```json
46
+ { "expr": "route", "name": "tab", "source": "query" }
47
+ ```
48
+
49
+ **Full path**:
50
+ ```json
51
+ { "expr": "route", "source": "path" }
52
+ ```
53
+
54
+ ## Route Patterns
55
+
56
+ | Pattern | Example Path | Params |
57
+ |---------|--------------|--------|
58
+ | `/` | `/` | `{}` |
59
+ | `/about` | `/about` | `{}` |
60
+ | `/users/:id` | `/users/123` | `{ id: "123" }` |
61
+ | `/posts/:id/comments/:cid` | `/posts/1/comments/5` | `{ id: "1", cid: "5" }` |
62
+ | `/docs/*` | `/docs/getting-started/intro` | Catch-all |
63
+
64
+ ## File-Based Routing
65
+
66
+ With `@constela/start`, routes are derived from file paths:
67
+
68
+ | File | Route |
69
+ |------|-------|
70
+ | `src/routes/index.json` | `/` |
71
+ | `src/routes/about.json` | `/about` |
72
+ | `src/routes/users/[id].json` | `/users/:id` |
73
+ | `src/routes/docs/[...slug].json` | `/docs/*` |
74
+
75
+ ## Example: Dynamic Page
76
+
77
+ ```json
78
+ {
79
+ "version": "1.0",
80
+ "route": {
81
+ "path": "/users/:id"
82
+ },
83
+ "state": {
84
+ "user": { "type": "object", "initial": null },
85
+ "loading": { "type": "boolean", "initial": true }
86
+ },
87
+ "lifecycle": {
88
+ "onMount": "fetchUser"
89
+ },
90
+ "actions": [
91
+ {
92
+ "name": "fetchUser",
93
+ "steps": [
94
+ {
95
+ "do": "fetch",
96
+ "url": {
97
+ "expr": "bin",
98
+ "op": "+",
99
+ "left": { "expr": "lit", "value": "https://api.example.com/users/" },
100
+ "right": { "expr": "route", "name": "id" }
101
+ },
102
+ "method": "GET",
103
+ "onSuccess": [
104
+ { "do": "set", "target": "user", "value": { "expr": "var", "name": "data" } },
105
+ { "do": "set", "target": "loading", "value": { "expr": "lit", "value": false } }
106
+ ]
107
+ }
108
+ ]
109
+ }
110
+ ],
111
+ "view": {
112
+ "kind": "if",
113
+ "condition": { "expr": "state", "name": "loading" },
114
+ "then": { "kind": "text", "value": { "expr": "lit", "value": "Loading..." } },
115
+ "else": {
116
+ "kind": "element",
117
+ "tag": "h1",
118
+ "children": [
119
+ { "kind": "text", "value": { "expr": "get", "base": { "expr": "state", "name": "user" }, "path": "name" } }
120
+ ]
121
+ }
122
+ }
123
+ }
124
+ ```
125
+
126
+ ## Navigation
127
+
128
+ Navigate using the `navigate` action step:
129
+
130
+ **Basic navigation**:
131
+ ```json
132
+ {
133
+ "name": "goToProfile",
134
+ "steps": [
135
+ { "do": "navigate", "url": { "expr": "lit", "value": "/profile" } }
136
+ ]
137
+ }
138
+ ```
139
+
140
+ **With dynamic URL**:
141
+ ```json
142
+ {
143
+ "name": "goToUser",
144
+ "steps": [
145
+ {
146
+ "do": "navigate",
147
+ "url": {
148
+ "expr": "bin",
149
+ "op": "+",
150
+ "left": { "expr": "lit", "value": "/users/" },
151
+ "right": { "expr": "state", "name": "selectedUserId" }
152
+ }
153
+ }
154
+ ]
155
+ }
156
+ ```
157
+
158
+ **Replace history** (no back button):
159
+ ```json
160
+ {
161
+ "do": "navigate",
162
+ "url": { "expr": "lit", "value": "/login" },
163
+ "replace": true
164
+ }
165
+ ```
166
+
167
+ ## Internal API
168
+
169
+ > For framework developers only. End users should use the CLI.
170
+
171
+ ### createRouter
172
+
173
+ ```typescript
174
+ import { createRouter } from '@constela/router';
175
+
176
+ const router = createRouter({
177
+ routes: [
178
+ { path: '/', program: homeProgram, title: 'Home' },
179
+ { path: '/about', program: aboutProgram, title: 'About' },
180
+ { path: '/users/:id', program: userProgram, title: (ctx) => `User ${ctx.params.id}` },
181
+ ],
182
+ basePath: '/app',
183
+ fallback: notFoundProgram,
184
+ onRouteChange: (ctx) => console.log('Route changed:', ctx.path),
185
+ });
186
+
187
+ const { destroy } = router.mount(document.getElementById('app'));
188
+ router.navigate('/about');
189
+ ```
190
+
191
+ ### Helper Functions
192
+
193
+ ```typescript
194
+ import { bindLink, createLink, matchRoute, parseParams } from '@constela/router';
195
+
196
+ // Bind existing anchor to router
197
+ bindLink(router, document.querySelector('a[href="/about"]'), '/about');
198
+
199
+ // Create router-aware anchor
200
+ const link = createLink(router, '/users/123', 'View User');
201
+
202
+ // Match route pattern
203
+ const match = matchRoute('/users/:id', '/users/123'); // { id: '123' }
204
+
205
+ // Parse params from path
206
+ const params = parseParams('/users/:id/posts/:postId', '/users/123/posts/456');
207
+ // { id: '123', postId: '456' }
208
+ ```
209
+
210
+ ## License
211
+
212
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constela/router",
3
- "version": "7.0.0",
3
+ "version": "9.0.0",
4
4
  "description": "Client-side routing for Constela applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -16,8 +16,8 @@
16
16
  ],
17
17
  "dependencies": {},
18
18
  "peerDependencies": {
19
- "@constela/compiler": "^0.7.0",
20
- "@constela/runtime": "^0.9.2"
19
+ "@constela/compiler": "^0.8.0",
20
+ "@constela/runtime": "^0.11.0"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@types/node": "^20.10.0",
@@ -25,8 +25,8 @@
25
25
  "tsup": "^8.0.0",
26
26
  "typescript": "^5.3.0",
27
27
  "vitest": "^2.0.0",
28
- "@constela/compiler": "0.7.0",
29
- "@constela/runtime": "0.9.2"
28
+ "@constela/runtime": "0.11.0",
29
+ "@constela/compiler": "0.8.0"
30
30
  },
31
31
  "engines": {
32
32
  "node": ">=20.0.0"