reroute-js 0.10.1 → 0.11.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 +89 -0
- package/_/README.md +3 -0
- package/_/basic/reroute.config.ts +12 -0
- package/_/basic/tsconfig.json +23 -24
- package/_/blog/reroute.config.ts +12 -0
- package/_/blog/tsconfig.json +23 -24
- package/_/redirects/README.md +63 -0
- package/_/redirects/package.json +27 -0
- package/_/redirects/reroute.config.ts +131 -0
- package/_/redirects/tsconfig.json +25 -0
- package/_/store/reroute.config.ts +13 -0
- package/_/store/src/client/index.html +0 -1
- package/_/store/src/client/lib/api.ts +3 -2
- package/_/store/src/client/routes/index.tsx +2 -3
- package/_/store/tsconfig.json +23 -24
- package/_/streaming/package.json +27 -0
- package/_/streaming/reroute.config.ts +14 -0
- package/_/streaming/tsconfig.json +25 -0
- package/cli/bin.d.ts +1 -1
- package/cli/bin.js +354 -202
- package/cli/bin.js.map +7 -6
- package/cli/index.d.ts +1 -1
- package/cli/index.js +4 -4
- package/cli/index.js.map +1 -1
- package/cli/src/cli.d.ts +1 -1
- package/cli/src/commands/analyze.d.ts +1 -1
- package/cli/src/commands/build.d.ts +1 -1
- package/cli/src/commands/dev.d.ts +1 -1
- package/cli/src/commands/gen.d.ts +1 -1
- package/cli/src/commands/gen.d.ts.map +1 -1
- package/cli/src/commands/index.d.ts +1 -1
- package/cli/src/commands/init.d.ts +1 -1
- package/cli/src/commands/init.d.ts.map +1 -1
- package/cli/src/commands/lib/command.d.ts +1 -1
- package/cli/src/commands/lib/env.d.ts +20 -0
- package/cli/src/commands/lib/env.d.ts.map +1 -0
- package/cli/src/commands/lib/index.d.ts +1 -1
- package/cli/src/commands/lib/log.d.ts +1 -1
- package/cli/src/commands/lib/markdown/availability.d.ts +1 -1
- package/cli/src/commands/lib/markdown/index.d.ts +1 -1
- package/cli/src/commands/lib/markdown/processor.d.ts +1 -1
- package/cli/src/commands/lib/production.d.ts +1 -1
- package/cli/src/commands/lib/server.d.ts +1 -1
- package/cli/src/commands/lib/streaming/analyzer.d.ts +1 -1
- package/cli/src/commands/lib/streaming/suspense.d.ts +1 -1
- package/cli/src/commands/lib/tailwind.d.ts +1 -1
- package/cli/src/commands/lib/version.d.ts +1 -1
- package/cli/src/commands/start.d.ts +1 -1
- package/cli/src/index.d.ts +1 -1
- package/core/index.d.ts +1 -1
- package/core/index.js +2 -2
- package/core/index.js.map +3 -3
- package/core/src/bundler/hash.d.ts +1 -1
- package/core/src/bundler/index.d.ts +1 -1
- package/core/src/config.d.ts +26 -5
- package/core/src/config.d.ts.map +1 -1
- package/core/src/content/discovery.d.ts +1 -1
- package/core/src/content/index.d.ts +1 -1
- package/core/src/content/metadata.d.ts +1 -1
- package/core/src/index.d.ts +1 -1
- package/core/src/ssr/index.d.ts +1 -1
- package/core/src/ssr/lib/cache.d.ts +1 -1
- package/core/src/ssr/lib/collections.d.ts +1 -1
- package/core/src/ssr/lib/compression.d.ts +1 -1
- package/core/src/ssr/lib/compute.d.ts +1 -1
- package/core/src/ssr/lib/data.d.ts +1 -1
- package/core/src/ssr/lib/html.d.ts +1 -1
- package/core/src/ssr/lib/index.d.ts +1 -1
- package/core/src/ssr/lib/metadata.d.ts +1 -1
- package/core/src/ssr/lib/mime.d.ts +1 -1
- package/core/src/ssr/lib/modules.d.ts +1 -1
- package/core/src/ssr/lib/path.d.ts +1 -1
- package/core/src/ssr/lib/preload.d.ts +1 -1
- package/core/src/ssr/lib/scripts.d.ts +1 -1
- package/core/src/ssr/lib/seed.d.ts +1 -1
- package/core/src/ssr/lib/styles.d.ts +1 -1
- package/core/src/ssr/lib/template.d.ts +1 -1
- package/core/src/ssr/lib/types.d.ts +1 -1
- package/core/src/ssr/render.d.ts +1 -1
- package/core/src/ssr/stream.d.ts +1 -1
- package/elysia/index.d.ts +1 -1
- package/elysia/index.js +206 -84
- package/elysia/index.js.map +7 -6
- package/elysia/src/index.d.ts +1 -1
- package/elysia/src/libs/cache.d.ts +1 -1
- package/elysia/src/libs/http.d.ts +1 -1
- package/elysia/src/libs/image.d.ts +1 -1
- package/elysia/src/plugin.d.ts +1 -1
- package/elysia/src/plugin.d.ts.map +1 -1
- package/elysia/src/routes/artifacts.d.ts +1 -1
- package/elysia/src/routes/content.d.ts +1 -1
- package/elysia/src/routes/image.d.ts +1 -1
- package/elysia/src/routes/internal.d.ts +1 -1
- package/elysia/src/routes/redirects.d.ts +17 -0
- package/elysia/src/routes/redirects.d.ts.map +1 -0
- package/elysia/src/routes/ssr.d.ts +1 -1
- package/elysia/src/routes/ssr.d.ts.map +1 -1
- package/elysia/src/routes/static.d.ts +1 -1
- package/elysia/src/types.d.ts +1 -1
- package/package.json +1 -1
- package/react/index.d.ts +1 -1
- package/react/index.js +23 -3
- package/react/index.js.map +3 -3
- package/react/src/components/ClientOnly.d.ts +1 -1
- package/react/src/components/ContentRoute.d.ts +1 -1
- package/react/src/components/Image.d.ts +1 -1
- package/react/src/components/LazyRoute.d.ts +1 -1
- package/react/src/components/Link.d.ts +1 -1
- package/react/src/components/Markdown.d.ts +1 -1
- package/react/src/components/Outlet.d.ts +1 -1
- package/react/src/components/index.d.ts +1 -1
- package/react/src/hooks/index.d.ts +1 -1
- package/react/src/hooks/useContent.d.ts +1 -1
- package/react/src/hooks/useData.d.ts +1 -1
- package/react/src/hooks/useLayoutData.d.ts +1 -1
- package/react/src/hooks/useNavigate.d.ts +1 -1
- package/react/src/hooks/useParams.d.ts +1 -1
- package/react/src/hooks/useRouter.d.ts +1 -1
- package/react/src/hooks/useSearchParams.d.ts +1 -1
- package/react/src/index.d.ts +1 -1
- package/react/src/lib/content.d.ts +1 -1
- package/react/src/lib/head.d.ts +1 -1
- package/react/src/lib/index.d.ts +1 -1
- package/react/src/lib/lazy-route.d.ts +1 -1
- package/react/src/lib/route-loader.d.ts +1 -1
- package/react/src/providers/ContentProvider.d.ts +1 -1
- package/react/src/providers/RerouteProvider.d.ts +1 -1
- package/react/src/providers/RouterProvider.d.ts +1 -1
- package/react/src/providers/RouterProvider.d.ts.map +1 -1
- package/react/src/providers/index.d.ts +1 -1
- package/react/src/types/any.d.ts +1 -1
- package/react/src/types/index.d.ts +1 -1
- package/react/src/types/router.d.ts +1 -1
package/README.md
CHANGED
|
@@ -123,6 +123,7 @@ Reroute is a dead-simple file-based routing framework for building full-stack Re
|
|
|
123
123
|
- 🏷️ **Custom Headers** - Add headers to static file responses
|
|
124
124
|
- ⏰ **Cache Control** - Configurable max-age and cache directives for static files and `__reroute_data` JSON
|
|
125
125
|
- 🎨 **HTML Template** - Custom index.html with variable substitution
|
|
126
|
+
- 🔐 **Environment Variables** - Share REROUTE_ prefixed env vars between server and browser
|
|
126
127
|
|
|
127
128
|
## 🚀 Quick Start
|
|
128
129
|
|
|
@@ -171,6 +172,94 @@ Notes:
|
|
|
171
172
|
- Data is injected as `window.__REROUTE_DATA__` and read during hydration
|
|
172
173
|
- Use with existing content features (useContent); both can be seeded in the same page
|
|
173
174
|
|
|
175
|
+
## 🔐 Environment Variables
|
|
176
|
+
|
|
177
|
+
Reroute supports sharing environment variables between server and browser code using a `REROUTE_` prefix convention (similar to how Vite uses `VITE_`).
|
|
178
|
+
|
|
179
|
+
### Usage
|
|
180
|
+
|
|
181
|
+
Create a `.env` file in your project root:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
# .env
|
|
185
|
+
|
|
186
|
+
# Server-only variables (not exposed to browser)
|
|
187
|
+
DATABASE_URL=postgresql://localhost:5432/mydb
|
|
188
|
+
SECRET_KEY=my-secret-key
|
|
189
|
+
|
|
190
|
+
# Public variables (exposed to browser)
|
|
191
|
+
REROUTE_API_URL=https://api.example.com
|
|
192
|
+
REROUTE_ANALYTICS_ID=G-XXXXXXXXXX
|
|
193
|
+
REROUTE_FEATURE_FLAG=true
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Accessing Variables
|
|
197
|
+
|
|
198
|
+
**In Server Code:**
|
|
199
|
+
All variables are available via `process.env` or `Bun.env`:
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
// src/index.ts
|
|
203
|
+
const dbUrl = process.env.DATABASE_URL;
|
|
204
|
+
const apiUrl = process.env.REROUTE_API_URL;
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**In Client/Browser Code:**
|
|
208
|
+
Only `REROUTE_` prefixed variables are available:
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
// src/client/routes/index.tsx
|
|
212
|
+
export default function Home() {
|
|
213
|
+
// ✅ Available - prefixed with REROUTE_
|
|
214
|
+
const apiUrl = import.meta.env.REROUTE_API_URL;
|
|
215
|
+
const analyticsId = process.env.REROUTE_ANALYTICS_ID; // Also works
|
|
216
|
+
|
|
217
|
+
// ❌ Not available - no REROUTE_ prefix
|
|
218
|
+
const dbUrl = process.env.DATABASE_URL; // undefined in browser
|
|
219
|
+
|
|
220
|
+
return <div>API: {apiUrl}</div>;
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Environment Files
|
|
225
|
+
|
|
226
|
+
Reroute supports multiple environment files with priority:
|
|
227
|
+
|
|
228
|
+
- `.env` - Base environment variables
|
|
229
|
+
- `.env.production` - Production-specific variables
|
|
230
|
+
- `.env.local` - Local overrides (gitignored)
|
|
231
|
+
- `.env.production.local` - Local production overrides (gitignored)
|
|
232
|
+
|
|
233
|
+
Files are loaded in order, with later files overriding earlier ones.
|
|
234
|
+
|
|
235
|
+
**Hot Reload:** Changes to any `.env` file automatically rebuild the bundle and reload your browser in watch mode - no server restart needed!
|
|
236
|
+
|
|
237
|
+
### Security
|
|
238
|
+
|
|
239
|
+
**Important:** Only variables prefixed with `REROUTE_` are bundled into the client code. This prevents accidentally exposing sensitive credentials like database URLs, API keys, or secrets to the browser.
|
|
240
|
+
|
|
241
|
+
- ✅ `REROUTE_API_URL` - Safe to expose
|
|
242
|
+
- ✅ `REROUTE_FEATURE_FLAG` - Safe to expose
|
|
243
|
+
- ❌ `DATABASE_URL` - Server-only
|
|
244
|
+
- ❌ `SECRET_KEY` - Server-only
|
|
245
|
+
|
|
246
|
+
### TypeScript Support
|
|
247
|
+
|
|
248
|
+
For type safety, create a `env.d.ts` file:
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
// env.d.ts
|
|
252
|
+
interface ImportMetaEnv {
|
|
253
|
+
readonly REROUTE_API_URL: string;
|
|
254
|
+
readonly REROUTE_ANALYTICS_ID: string;
|
|
255
|
+
readonly REROUTE_FEATURE_FLAG: string;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
interface ImportMeta {
|
|
259
|
+
readonly env: ImportMetaEnv;
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
174
263
|
## 📝 Markdown Routes
|
|
175
264
|
|
|
176
265
|
Reroute supports native markdown and MDX files as routes with frontmatter support and syntax highlighting.
|
package/_/README.md
CHANGED
|
@@ -8,6 +8,9 @@ Each subdirectory represents a template that users can choose from:
|
|
|
8
8
|
|
|
9
9
|
- `basic/` - Minimal Reroute application with basic routing
|
|
10
10
|
- `blog/` - Full-featured blog with content collections and layouts
|
|
11
|
+
- `redirects/` - Example of redirect configurations
|
|
12
|
+
- `store/` - Example of a simple e-commerce store
|
|
13
|
+
- `streaming/` - Example of a streaming application
|
|
11
14
|
|
|
12
15
|
## How It Works
|
|
13
16
|
|
package/_/basic/tsconfig.json
CHANGED
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"exclude": ["node_modules", "dist", "test"]
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"moduleResolution": "bundler",
|
|
9
|
+
"isolatedModules": true,
|
|
10
|
+
"baseUrl": ".",
|
|
11
|
+
"rootDir": ".",
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"declarationMap": true,
|
|
14
|
+
"outDir": "dist/types",
|
|
15
|
+
"emitDeclarationOnly": true,
|
|
16
|
+
"strict": true,
|
|
17
|
+
"noUnusedLocals": true,
|
|
18
|
+
"noUnusedParameters": true,
|
|
19
|
+
"noFallthroughCasesInSwitch": true,
|
|
20
|
+
"jsx": "react-jsx",
|
|
21
|
+
"types": ["bun", "node"]
|
|
22
|
+
},
|
|
23
|
+
"include": ["**/*.ts", "**/*.tsx"],
|
|
24
|
+
"exclude": ["node_modules", "dist"]
|
|
26
25
|
}
|
package/_/blog/tsconfig.json
CHANGED
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"exclude": ["node_modules", "dist", "test"]
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"moduleResolution": "bundler",
|
|
9
|
+
"isolatedModules": true,
|
|
10
|
+
"baseUrl": ".",
|
|
11
|
+
"rootDir": ".",
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"declarationMap": true,
|
|
14
|
+
"outDir": "dist/types",
|
|
15
|
+
"emitDeclarationOnly": true,
|
|
16
|
+
"strict": true,
|
|
17
|
+
"noUnusedLocals": true,
|
|
18
|
+
"noUnusedParameters": true,
|
|
19
|
+
"noFallthroughCasesInSwitch": true,
|
|
20
|
+
"jsx": "react-jsx",
|
|
21
|
+
"types": ["bun", "node"]
|
|
22
|
+
},
|
|
23
|
+
"include": ["**/*.ts", "**/*.tsx"],
|
|
24
|
+
"exclude": ["node_modules", "dist"]
|
|
26
25
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Reroute Redirects Example
|
|
2
|
+
|
|
3
|
+
Comprehensive example demonstrating all redirect features in reroute.
|
|
4
|
+
|
|
5
|
+
## Features Demonstrated
|
|
6
|
+
|
|
7
|
+
### 1. Static Redirects
|
|
8
|
+
- Permanent redirects (301)
|
|
9
|
+
- Temporary redirects (302)
|
|
10
|
+
|
|
11
|
+
### 2. Regex Redirects
|
|
12
|
+
- Single capture groups
|
|
13
|
+
- Multiple capture groups
|
|
14
|
+
- Regex strings with flags
|
|
15
|
+
|
|
16
|
+
### 3. Dynamic Redirects
|
|
17
|
+
- Query parameter based
|
|
18
|
+
- Hostname based
|
|
19
|
+
- URL inspection
|
|
20
|
+
|
|
21
|
+
### 4. Conditional Redirects
|
|
22
|
+
- Return `null` to skip redirect
|
|
23
|
+
- Continue to normal route handling
|
|
24
|
+
|
|
25
|
+
### 5. Async Redirects
|
|
26
|
+
- Database lookups
|
|
27
|
+
- API calls
|
|
28
|
+
- Delayed operations
|
|
29
|
+
|
|
30
|
+
### 6. Error Handling
|
|
31
|
+
- Graceful error handling
|
|
32
|
+
- Automatic fallback to routes
|
|
33
|
+
- Console logging
|
|
34
|
+
|
|
35
|
+
### 7. Special Cases
|
|
36
|
+
- External redirects
|
|
37
|
+
- Trailing slash removal
|
|
38
|
+
- API versioning
|
|
39
|
+
- Method preservation (308)
|
|
40
|
+
|
|
41
|
+
## Running the Example
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# From the redirects directory
|
|
45
|
+
bun dev
|
|
46
|
+
|
|
47
|
+
# Or from the root
|
|
48
|
+
cd examples/redirects
|
|
49
|
+
bun dev
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Visit http://localhost:3000 to test all redirect scenarios.
|
|
53
|
+
|
|
54
|
+
## Testing Redirects
|
|
55
|
+
|
|
56
|
+
1. Click each link in the index page
|
|
57
|
+
2. Observe the URL changes in your browser
|
|
58
|
+
3. Check server console for error messages (error-test example)
|
|
59
|
+
4. Test with browser dev tools to see redirect status codes
|
|
60
|
+
|
|
61
|
+
## Configuration
|
|
62
|
+
|
|
63
|
+
See `reroute.config.ts` for all redirect configurations with detailed comments.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{PROJECT_NAME}}",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "A Reroute application",
|
|
5
|
+
"private": true,
|
|
6
|
+
"scripts": {
|
|
7
|
+
"types": "tsc --noEmit",
|
|
8
|
+
"gen": "reroute gen",
|
|
9
|
+
"start": "reroute start",
|
|
10
|
+
"dev": "reroute dev",
|
|
11
|
+
"build": "reroute build",
|
|
12
|
+
"analyze": "reroute analyze --prod --open"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"reroute-js": "latest",
|
|
16
|
+
"elysia": "^1.4.12",
|
|
17
|
+
"react": "^19.2.0",
|
|
18
|
+
"react-dom": "^19.2.0",
|
|
19
|
+
"sharp": "^0.34.4"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/bun": "latest",
|
|
23
|
+
"@types/react": "^19.2.2",
|
|
24
|
+
"@types/react-dom": "^19.2.2",
|
|
25
|
+
"typescript": "^5"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { defineConfig } from 'reroute-js/core';
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
options: {
|
|
5
|
+
app: './src/client/App',
|
|
6
|
+
maxAge: 3600,
|
|
7
|
+
compression: true,
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
// Comprehensive redirect examples
|
|
11
|
+
redirects: [
|
|
12
|
+
// 1. Basic static redirect (permanent)
|
|
13
|
+
{
|
|
14
|
+
source: '/old-home',
|
|
15
|
+
destination: '/home',
|
|
16
|
+
status: 301,
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
// 2. Temporary redirect (default status)
|
|
20
|
+
{
|
|
21
|
+
source: '/temp',
|
|
22
|
+
destination: '/home',
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
// 3. Regex with single capture group
|
|
26
|
+
{
|
|
27
|
+
source: /^\/blog\/(\d+)$/,
|
|
28
|
+
destination: '/posts/$1',
|
|
29
|
+
status: 301,
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
// 4. Regex with multiple capture groups
|
|
33
|
+
{
|
|
34
|
+
source: /^\/archive\/(\d{4})\/(\d{2})\/(.+)$/,
|
|
35
|
+
destination: '/posts/$1/$2?slug=$3',
|
|
36
|
+
status: 301,
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
// 5. Regex string with regex flag
|
|
40
|
+
{
|
|
41
|
+
source: '^/products/(.*)$',
|
|
42
|
+
destination: '/shop/$1',
|
|
43
|
+
regex: true,
|
|
44
|
+
status: 301,
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
// 6. Dynamic redirect based on query params
|
|
48
|
+
{
|
|
49
|
+
source: '/language',
|
|
50
|
+
destination: (url: URL) => {
|
|
51
|
+
const lang = url.searchParams.get('lang') || 'en';
|
|
52
|
+
return `/${lang}/home`;
|
|
53
|
+
},
|
|
54
|
+
status: 302,
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
// 7. Conditional redirect (returns null to skip)
|
|
58
|
+
{
|
|
59
|
+
source: '/conditional',
|
|
60
|
+
destination: (url: URL) => {
|
|
61
|
+
const redirect = url.searchParams.get('redirect');
|
|
62
|
+
if (redirect === 'true') {
|
|
63
|
+
return '/redirected';
|
|
64
|
+
}
|
|
65
|
+
return null; // Skip redirect, continue to normal route
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
// 8. Async redirect (simulates database lookup)
|
|
70
|
+
{
|
|
71
|
+
source: '/async-lookup',
|
|
72
|
+
destination: async (url: URL) => {
|
|
73
|
+
const id = url.searchParams.get('id') || '1';
|
|
74
|
+
// Simulate async operation
|
|
75
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
76
|
+
return `/item/${id}`;
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
// 9. Error handling test (will fail gracefully)
|
|
81
|
+
{
|
|
82
|
+
source: '/error-test',
|
|
83
|
+
destination: (url: URL) => {
|
|
84
|
+
const shouldError = url.searchParams.get('error') === 'true';
|
|
85
|
+
if (shouldError) {
|
|
86
|
+
throw new Error('Intentional error for testing');
|
|
87
|
+
}
|
|
88
|
+
return '/success';
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
// 10. External redirect
|
|
93
|
+
{
|
|
94
|
+
source: '/github',
|
|
95
|
+
destination: 'https://github.com',
|
|
96
|
+
status: 301,
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
// 11. Trailing slash removal
|
|
100
|
+
{
|
|
101
|
+
source: /^\/(.+)\/$/,
|
|
102
|
+
destination: '/$1',
|
|
103
|
+
status: 301,
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
// 12. API versioning
|
|
107
|
+
{
|
|
108
|
+
source: /^\/api\/v(\d+)\/(.+)$/,
|
|
109
|
+
destination: '/api/$2?version=$1',
|
|
110
|
+
status: 301,
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
// 13. Complex pattern with hostname check
|
|
114
|
+
{
|
|
115
|
+
source: '/smart',
|
|
116
|
+
destination: (url: URL) => {
|
|
117
|
+
const isLocalhost = url.hostname === 'localhost';
|
|
118
|
+
const query = url.searchParams.get('q') || 'default';
|
|
119
|
+
return `/search?q=${query}&env=${isLocalhost ? 'dev' : 'prod'}`;
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
// 14. Preserve POST method (308)
|
|
124
|
+
{
|
|
125
|
+
source: '/old-api',
|
|
126
|
+
destination: '/new-api',
|
|
127
|
+
status: 308,
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
});
|
|
131
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"moduleResolution": "bundler",
|
|
9
|
+
"isolatedModules": true,
|
|
10
|
+
"baseUrl": ".",
|
|
11
|
+
"rootDir": ".",
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"declarationMap": true,
|
|
14
|
+
"outDir": "dist/types",
|
|
15
|
+
"emitDeclarationOnly": true,
|
|
16
|
+
"strict": true,
|
|
17
|
+
"noUnusedLocals": true,
|
|
18
|
+
"noUnusedParameters": true,
|
|
19
|
+
"noFallthroughCasesInSwitch": true,
|
|
20
|
+
"jsx": "react-jsx",
|
|
21
|
+
"types": ["bun", "node"]
|
|
22
|
+
},
|
|
23
|
+
"include": ["**/*.ts", "**/*.tsx"],
|
|
24
|
+
"exclude": ["node_modules", "dist"]
|
|
25
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { defineConfig } from 'reroute-js/core';
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
options: {
|
|
5
|
+
app: './src/client/App',
|
|
6
|
+
maxAge: 3600,
|
|
7
|
+
compression: true,
|
|
8
|
+
imageAllowedDomains: ['fakestoreapi.com'],
|
|
9
|
+
},
|
|
10
|
+
streaming: {
|
|
11
|
+
enabled: true,
|
|
12
|
+
},
|
|
13
|
+
});
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// API client for FakeStoreAPI with SSR support
|
|
2
2
|
// All responses are plain JSON objects to ensure serialization compatibility
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
// Configuration from environment variables (defaults for development)
|
|
5
|
+
const API_BASE_URL = import.meta.env.REROUTE_API_BASE_URL || 'https://fakestoreapi.com';
|
|
6
|
+
const CACHE_TTL = Number(import.meta.env.REROUTE_API_CACHE_TTL) || 60000; // Default: 1 minute
|
|
5
7
|
|
|
6
8
|
// In-memory cache for API responses
|
|
7
9
|
interface CacheEntry<T> {
|
|
@@ -10,7 +12,6 @@ interface CacheEntry<T> {
|
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
const cache = new Map<string, CacheEntry<unknown>>();
|
|
13
|
-
const CACHE_TTL = 60000; // 1 minute cache
|
|
14
15
|
|
|
15
16
|
interface Product {
|
|
16
17
|
id: number;
|
|
@@ -34,11 +34,10 @@ function HomePage() {
|
|
|
34
34
|
{/* Hero Section */}
|
|
35
35
|
<section className='text-center py-12 mb-12 animate-slide-up'>
|
|
36
36
|
<h1 className='text-5xl md:text-6xl font-bold text-gray-900 mb-4 leading-tight'>
|
|
37
|
-
Welcome to Reroute Store
|
|
37
|
+
Welcome to {import.meta.env.REROUTE_SITE_NAME || 'Reroute Store'}
|
|
38
38
|
</h1>
|
|
39
39
|
<p className='text-xl text-gray-600 mb-8 max-w-2xl mx-auto'>
|
|
40
|
-
A modern e-commerce demo built with Reroute, showcasing file-based
|
|
41
|
-
routing, SSR, and seamless API integration with FakeStoreAPI
|
|
40
|
+
{import.meta.env.REROUTE_SITE_DESCRIPTION || 'A modern e-commerce demo built with Reroute, showcasing file-based routing, SSR, and seamless API integration with FakeStoreAPI'}
|
|
42
41
|
</p>
|
|
43
42
|
<div className='flex gap-4 justify-center flex-wrap'>
|
|
44
43
|
<Link to='/products' className='btn-primary btn-lg'>
|
package/_/store/tsconfig.json
CHANGED
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"exclude": ["node_modules", "dist", "test"]
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"moduleResolution": "bundler",
|
|
9
|
+
"isolatedModules": true,
|
|
10
|
+
"baseUrl": ".",
|
|
11
|
+
"rootDir": ".",
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"declarationMap": true,
|
|
14
|
+
"outDir": "dist/types",
|
|
15
|
+
"emitDeclarationOnly": true,
|
|
16
|
+
"strict": true,
|
|
17
|
+
"noUnusedLocals": true,
|
|
18
|
+
"noUnusedParameters": true,
|
|
19
|
+
"noFallthroughCasesInSwitch": true,
|
|
20
|
+
"jsx": "react-jsx",
|
|
21
|
+
"types": ["bun", "node"]
|
|
22
|
+
},
|
|
23
|
+
"include": ["**/*.ts", "**/*.tsx"],
|
|
24
|
+
"exclude": ["node_modules", "dist"]
|
|
26
25
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{PROJECT_NAME}}",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "A Reroute application",
|
|
5
|
+
"private": true,
|
|
6
|
+
"scripts": {
|
|
7
|
+
"types": "tsc --noEmit",
|
|
8
|
+
"gen": "reroute gen",
|
|
9
|
+
"start": "reroute start",
|
|
10
|
+
"dev": "reroute dev",
|
|
11
|
+
"build": "reroute build",
|
|
12
|
+
"analyze": "reroute analyze --prod --open"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"reroute-js": "latest",
|
|
16
|
+
"elysia": "^1.4.12",
|
|
17
|
+
"react": "^19.2.0",
|
|
18
|
+
"react-dom": "^19.2.0",
|
|
19
|
+
"sharp": "^0.34.4"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/bun": "latest",
|
|
23
|
+
"@types/react": "^19.2.2",
|
|
24
|
+
"@types/react-dom": "^19.2.2",
|
|
25
|
+
"typescript": "^5"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineConfig } from 'reroute-js/core';
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
options: {
|
|
5
|
+
app: './src/client/App',
|
|
6
|
+
maxAge: 0,
|
|
7
|
+
compression: false,
|
|
8
|
+
},
|
|
9
|
+
streaming: {
|
|
10
|
+
enabled: true,
|
|
11
|
+
defaultSkeleton: './src/client/components/DefaultRouteSkeleton',
|
|
12
|
+
defaultLayoutSkeleton: './src/client/components/DefaultLayoutSkeleton',
|
|
13
|
+
},
|
|
14
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"moduleResolution": "bundler",
|
|
9
|
+
"isolatedModules": true,
|
|
10
|
+
"baseUrl": ".",
|
|
11
|
+
"rootDir": ".",
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"declarationMap": true,
|
|
14
|
+
"outDir": "dist/types",
|
|
15
|
+
"emitDeclarationOnly": true,
|
|
16
|
+
"strict": true,
|
|
17
|
+
"noUnusedLocals": true,
|
|
18
|
+
"noUnusedParameters": true,
|
|
19
|
+
"noFallthroughCasesInSwitch": true,
|
|
20
|
+
"jsx": "react-jsx",
|
|
21
|
+
"types": ["bun", "node"]
|
|
22
|
+
},
|
|
23
|
+
"include": ["**/*.ts", "**/*.tsx"],
|
|
24
|
+
"exclude": ["node_modules", "dist"]
|
|
25
|
+
}
|
package/cli/bin.d.ts
CHANGED