@ressjs/vite-router 0.6.0-experimental.0 → 0.6.0-rc.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/LICENSE +69 -0
- package/README.md +9 -525
- package/dist/client/entry.d.mts +2 -2
- package/dist/client/entry.mjs +1 -1
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.js +6 -6
- package/dist/config/codegen.d.ts +15 -0
- package/dist/config/codegen.js +27 -8
- package/dist/config/env.d.ts +2 -0
- package/dist/config/env.js +6 -3
- package/dist/config/index.d.ts +4 -4
- package/dist/config/index.js +4 -1
- package/dist/config/load.d.ts +4 -3
- package/dist/config/load.js +17 -7
- package/dist/config/rules.d.ts +12 -1
- package/dist/config/rules.js +15 -2
- package/dist/config/types.d.ts +48 -20
- package/dist/config/validate.js +105 -0
- package/dist/config/watch.d.ts +34 -0
- package/dist/config/watch.js +93 -5
- package/dist/fs/canonical-path.d.ts +12 -0
- package/dist/fs/canonical-path.js +28 -0
- package/dist/fs/module-extensions.d.ts +24 -1
- package/dist/fs/module-extensions.js +23 -6
- package/dist/fs/shared-modules.d.ts +22 -0
- package/dist/fs/shared-modules.js +44 -0
- package/dist/head/resolve.d.ts +5 -0
- package/dist/head/resolve.js +166 -0
- package/dist/head/types.d.ts +44 -0
- package/dist/head/types.js +2 -0
- package/dist/helpers/html-generator.d.ts +4 -1
- package/dist/helpers/html-generator.js +45 -56
- package/dist/helpers/middlewares.d.ts +28 -17
- package/dist/helpers/middlewares.js +141 -65
- package/dist/helpers/page-config-merge.d.ts +11 -0
- package/dist/helpers/page-config-merge.js +84 -0
- package/dist/helpers/request-handler.d.ts +13 -0
- package/dist/helpers/request-handler.js +56 -20
- package/dist/index.d.ts +12 -6
- package/dist/index.js +16 -2
- package/dist/isr/capture.d.ts +79 -0
- package/dist/isr/capture.js +222 -0
- package/dist/isr/handler.d.ts +51 -0
- package/dist/isr/handler.js +207 -0
- package/dist/isr/key.d.ts +26 -0
- package/dist/isr/key.js +59 -0
- package/dist/isr/page-config.d.ts +17 -0
- package/dist/isr/page-config.js +71 -0
- package/dist/isr/preview.d.ts +5 -0
- package/dist/isr/preview.js +38 -0
- package/dist/isr/public-request.d.ts +50 -0
- package/dist/isr/public-request.js +108 -0
- package/dist/isr/response.d.ts +43 -0
- package/dist/isr/response.js +130 -0
- package/dist/isr/store.d.ts +42 -0
- package/dist/isr/store.js +108 -0
- package/dist/isr/types.d.ts +62 -0
- package/dist/isr/types.js +2 -0
- package/dist/plugin/environments.d.ts +2 -0
- package/dist/plugin/environments.js +3 -1
- package/dist/plugin/index.d.ts +46 -6
- package/dist/plugin/index.js +106 -16
- package/dist/plugin/route-manifest.d.ts +19 -0
- package/dist/plugin/route-manifest.js +55 -0
- package/dist/plugin/strip-server-exports.d.ts +39 -0
- package/dist/plugin/strip-server-exports.js +258 -0
- package/dist/plugin/virtual-entries.js +1 -1
- package/dist/render.d.ts +22 -11
- package/dist/render.js +42 -65
- package/dist/router.js +50 -3
- package/dist/routes/dispatcher.d.ts +22 -1
- package/dist/routes/dispatcher.js +3 -2
- package/dist/routes/manifest.js +6 -0
- package/dist/routes/module.d.ts +14 -0
- package/dist/routes/module.js +30 -0
- package/dist/routes/router.d.ts +11 -1
- package/dist/routes/router.js +80 -8
- package/dist/routes/scan.d.ts +16 -0
- package/dist/routes/scan.js +50 -22
- package/dist/routes/types.d.ts +31 -2
- package/dist/routes/types.js +6 -2
- package/dist/runtime/dev-server.d.ts +5 -1
- package/dist/runtime/dev-server.js +56 -4
- package/dist/runtime/dev-styles.d.ts +13 -0
- package/dist/runtime/dev-styles.js +50 -0
- package/dist/runtime/module-loader.d.ts +16 -1
- package/dist/runtime/module-loader.js +15 -1
- package/dist/runtime/prod-server.d.ts +13 -0
- package/dist/runtime/prod-server.js +55 -9
- package/dist/runtime/template.js +11 -1
- package/dist/security/client-props.d.ts +9 -17
- package/dist/security/client-props.js +13 -31
- package/dist/security/config.d.ts +9 -21
- package/dist/security/config.js +10 -5
- package/dist/security/errors.d.ts +0 -11
- package/dist/security/errors.js +0 -21
- package/dist/security/head-tags.d.ts +1 -1
- package/dist/security/head-tags.js +50 -5
- package/dist/security/headers.d.ts +14 -0
- package/dist/security/headers.js +92 -1
- package/dist/security/index.d.ts +4 -4
- package/dist/security/index.js +4 -4
- package/dist/variants/assets.d.ts +11 -0
- package/dist/variants/assets.js +88 -4
- package/dist/variants/resolve.d.ts +1 -1
- package/dist/variants/resolve.js +3 -37
- package/dist/variants/types.d.ts +4 -1
- package/package.json +5 -5
package/LICENSE
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
ress.js Proprietary License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 gabrielspisso. All rights reserved.
|
|
4
|
+
|
|
5
|
+
This license applies to the ress.js packages (the "Software"), published on npm
|
|
6
|
+
under the @ressjs and @gzzy scopes, in every version released from 0.6.0-rc.0
|
|
7
|
+
onwards. Earlier versions were released under the MIT License and remain
|
|
8
|
+
available under those terms.
|
|
9
|
+
|
|
10
|
+
1. GRANT
|
|
11
|
+
Subject to this license, the Licensor grants you a worldwide, non-exclusive,
|
|
12
|
+
non-transferable, non-sublicensable, royalty-free license to install and use
|
|
13
|
+
the Software, as distributed by the Licensor, to build, run and deploy your
|
|
14
|
+
own applications and services, including commercial ones, and to charge your
|
|
15
|
+
own customers for them.
|
|
16
|
+
|
|
17
|
+
2. RESTRICTIONS
|
|
18
|
+
You may not:
|
|
19
|
+
a) fork, copy, or redistribute the Software, in whole or in part, except for
|
|
20
|
+
the portions that are necessarily included in the build output of your own
|
|
21
|
+
application in order to run it;
|
|
22
|
+
b) publish, distribute or make available a modified version of the Software
|
|
23
|
+
or any work derived from it. Modifications for your own internal use are
|
|
24
|
+
allowed, but they remain subject to this license;
|
|
25
|
+
c) use the Software, or any part of it, to build, offer or support a
|
|
26
|
+
framework, library, tool or service that competes with the Software;
|
|
27
|
+
d) sell, sublicense, rent or host the Software itself as a product or service
|
|
28
|
+
for third parties, as opposed to hosting your own application built with
|
|
29
|
+
it;
|
|
30
|
+
e) remove or alter copyright, license or attribution notices;
|
|
31
|
+
f) use the name "ress.js" or the Licensor's names or marks to endorse or
|
|
32
|
+
promote your products without written permission.
|
|
33
|
+
|
|
34
|
+
3. SCAFFOLDING OUTPUT
|
|
35
|
+
Files that @ressjs/create-ress-app copies into your project (templates and
|
|
36
|
+
generated configuration) are yours: you may use, modify and distribute them
|
|
37
|
+
without restriction. This does not extend to the Software packages that the
|
|
38
|
+
generated project installs as dependencies.
|
|
39
|
+
|
|
40
|
+
4. SUPPORT
|
|
41
|
+
The Software is provided without any obligation of support, maintenance or
|
|
42
|
+
updates. The Licensor may offer support, maintenance, training or consulting
|
|
43
|
+
under a separate paid agreement; that agreement does not change this license
|
|
44
|
+
unless it says so explicitly and is signed by the Licensor.
|
|
45
|
+
|
|
46
|
+
5. OWNERSHIP
|
|
47
|
+
The Software is licensed, not sold. The Licensor retains all rights not
|
|
48
|
+
expressly granted here. Feedback and suggestions you send may be used by the
|
|
49
|
+
Licensor without obligation to you.
|
|
50
|
+
|
|
51
|
+
6. TERMINATION
|
|
52
|
+
This license ends automatically if you breach it. On termination you must
|
|
53
|
+
stop using the Software and delete your copies. Sections 4 to 8 survive
|
|
54
|
+
termination.
|
|
55
|
+
|
|
56
|
+
7. NO WARRANTY
|
|
57
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
58
|
+
IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
59
|
+
PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
|
60
|
+
|
|
61
|
+
8. LIMITATION OF LIABILITY
|
|
62
|
+
TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE LICENSOR WILL NOT BE LIABLE FOR
|
|
63
|
+
ANY INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES, OR FOR LOSS OF
|
|
64
|
+
PROFITS, DATA OR BUSINESS, ARISING FROM THE USE OF OR INABILITY TO USE THE
|
|
65
|
+
SOFTWARE. THE LICENSOR'S TOTAL LIABILITY IS LIMITED TO THE AMOUNT YOU PAID
|
|
66
|
+
FOR THE SOFTWARE, WHICH MAY BE ZERO.
|
|
67
|
+
|
|
68
|
+
For other uses, including exceptions to section 2, contact the Licensor to
|
|
69
|
+
agree a separate license.
|
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# @ressjs/vite-router
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Express router for ress.js applications: file-based pages, dynamic routes and server-side rendering on top of Vite.
|
|
4
|
+
|
|
5
|
+
> Pre-release (`0.6.0-rc`). The API may still change before `0.6.0`.
|
|
4
6
|
|
|
5
7
|
## Installation
|
|
6
8
|
|
|
@@ -8,534 +10,16 @@ Advanced Express router with **dynamic routes**, platform detection, and Server-
|
|
|
8
10
|
npm install @ressjs/vite-router
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
- **🎯 Dynamic Routes**: Next.js-style routing with `[param]` syntax
|
|
14
|
-
- **🎨 Platform Detection**: Automatic device, OS, and WebView detection
|
|
15
|
-
- **⚡ SSR Support**: Complete server-side rendering with proper hydration
|
|
16
|
-
- **📱 Smart Assets**: Platform-specific CSS/JS bundle resolution
|
|
17
|
-
- **🔧 Middleware System**: File-based middleware with execution order control
|
|
18
|
-
- **🔄 Development Mode**: Hot reload with fast refresh and dev server
|
|
19
|
-
- **🚀 Production Ready**: Optimized builds with manifest-based asset loading
|
|
20
|
-
- **📝 TypeScript**: Full TypeScript support with comprehensive type definitions
|
|
21
|
-
|
|
22
|
-
### Platform CSS and inline styles
|
|
23
|
-
|
|
24
|
-
Style variants use the same filename convention for every supported format. The
|
|
25
|
-
catalog and the inline components are provided by `@ressjs/assets`:
|
|
26
|
-
|
|
27
|
-
```text
|
|
28
|
-
app/pages/home/index.css
|
|
29
|
-
app/pages/home/index.phone.css
|
|
30
|
-
app/pages/home/index.webview.android.css
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
The matching stylesheet is selected from the detected platform. For CSS that is
|
|
34
|
-
part of the rendered page, use the small `Style` component:
|
|
35
|
-
|
|
36
|
-
```jsx
|
|
37
|
-
import { Style } from '@ressjs/assets/client'
|
|
38
|
-
|
|
39
|
-
export default function Home() {
|
|
40
|
-
return <><Style>{'.notice { color: red; }'}</Style><main className="notice">Hello</main></>
|
|
41
|
-
}
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
`@ressjs/vite-router/client` remains a compatibility alias. `Script` is also
|
|
45
|
-
available from `@ressjs/assets/client` for inline code or an explicit `src`.
|
|
46
|
-
The router consumes `resolvePageAssets` from `@ressjs/assets`; request handling
|
|
47
|
-
only reads the in-memory catalog and artifact index.
|
|
48
|
-
|
|
49
|
-
## Quick Start
|
|
50
|
-
|
|
51
|
-
### Vite Configuration
|
|
52
|
-
|
|
53
|
-
Create a `vite.config.ts` file in your project root:
|
|
54
|
-
|
|
55
|
-
```ts
|
|
56
|
-
import { defineConfig } from 'vite'
|
|
57
|
-
import react from '@vitejs/plugin-react'
|
|
58
|
-
import { ressPlugin } from '@ressjs/vite-router/plugin'
|
|
59
|
-
|
|
60
|
-
export default defineConfig({
|
|
61
|
-
plugins: [react(), ressPlugin()],
|
|
62
|
-
})
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
**Important**: The router automatically generates entry files for each page/platform combination in `dist/.entries/`. These are used by Vite for building client bundles.
|
|
66
|
-
|
|
67
|
-
### Basic Setup
|
|
68
|
-
|
|
69
|
-
```typescript
|
|
70
|
-
import express from 'express'
|
|
71
|
-
import { createViteRouter } from '@ressjs/vite-router'
|
|
72
|
-
|
|
73
|
-
const app = express()
|
|
74
|
-
const router = createViteRouter({
|
|
75
|
-
enablePlatformDetection: true,
|
|
76
|
-
isProduction: process.env.NODE_ENV === 'production'
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
app.use('/', router)
|
|
80
|
-
app.listen(3000, () => console.log('Server running on port 3000'))
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### Development Server Setup
|
|
84
|
-
|
|
85
|
-
Create a `server.js` file for development:
|
|
86
|
-
|
|
87
|
-
```typescript
|
|
88
|
-
import { createServer } from 'vite'
|
|
89
|
-
import { createViteRouter } from '@ressjs/vite-router'
|
|
90
|
-
import express from 'express'
|
|
91
|
-
|
|
92
|
-
async function createDevServer() {
|
|
93
|
-
const app = express()
|
|
94
|
-
|
|
95
|
-
// Create Vite server in middleware mode
|
|
96
|
-
const vite = await createServer({
|
|
97
|
-
server: { middlewareMode: true },
|
|
98
|
-
appType: 'custom'
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
// Use vite's connect instance as middleware
|
|
102
|
-
app.use(vite.ssrLoadModule)
|
|
103
|
-
|
|
104
|
-
// Create router with Vite instance
|
|
105
|
-
const router = createViteRouter({
|
|
106
|
-
vite,
|
|
107
|
-
enablePlatformDetection: true,
|
|
108
|
-
isProduction: false
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
app.use('/', router)
|
|
112
|
-
app.listen(3000, () => console.log('Dev server running on port 3000'))
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
createDevServer()
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### Package.json Scripts
|
|
119
|
-
|
|
120
|
-
Add these scripts to your `package.json`:
|
|
121
|
-
|
|
122
|
-
```json
|
|
123
|
-
{
|
|
124
|
-
"scripts": {
|
|
125
|
-
"dev": "node server.js",
|
|
126
|
-
"build": "vite build",
|
|
127
|
-
"preview": "NODE_ENV=production node server.js",
|
|
128
|
-
"type-check": "tsc --noEmit"
|
|
129
|
-
},
|
|
130
|
-
"dependencies": {
|
|
131
|
-
"@ressjs/vite-router": "^0.5.0",
|
|
132
|
-
"express": "^4.18.0",
|
|
133
|
-
"react": "^18.0.0",
|
|
134
|
-
"react-dom": "^18.0.0",
|
|
135
|
-
"vite": "^5.0.0"
|
|
136
|
-
},
|
|
137
|
-
"devDependencies": {
|
|
138
|
-
"@types/express": "^4.17.0",
|
|
139
|
-
"@types/react": "^18.0.0",
|
|
140
|
-
"@types/react-dom": "^18.0.0",
|
|
141
|
-
"@vitejs/plugin-react": "^4.0.0",
|
|
142
|
-
"typescript": "^5.0.0"
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### TypeScript Backend Integration
|
|
148
|
-
|
|
149
|
-
For full-stack TypeScript projects with backend APIs, use this enhanced configuration:
|
|
150
|
-
|
|
151
|
-
```json
|
|
152
|
-
{
|
|
153
|
-
"name": "my-fullstack-app",
|
|
154
|
-
"type": "module",
|
|
155
|
-
"scripts": {
|
|
156
|
-
"dev": "PORT=3000 vite-node server.ts",
|
|
157
|
-
"build": "vite build",
|
|
158
|
-
"preview": "cross-env NODE_ENV=production PORT=3000 tsx server.ts",
|
|
159
|
-
"start": "npm run build && npm run preview"
|
|
160
|
-
},
|
|
161
|
-
"dependencies": {
|
|
162
|
-
"@ressjs/vite-router": "^0.5.0",
|
|
163
|
-
"cross-env": "^7.0.3",
|
|
164
|
-
"express": "^4.18.0",
|
|
165
|
-
"react": "^18.0.0",
|
|
166
|
-
"react-dom": "^18.0.0",
|
|
167
|
-
"tsx": "^4.7.1",
|
|
168
|
-
"typescript": "^5.0.0",
|
|
169
|
-
"vite": "^5.0.0"
|
|
170
|
-
},
|
|
171
|
-
"devDependencies": {
|
|
172
|
-
"@types/express": "^4.17.0",
|
|
173
|
-
"@types/node": "^22.0.0",
|
|
174
|
-
"@types/react": "^18.0.0",
|
|
175
|
-
"@types/react-dom": "^18.0.0",
|
|
176
|
-
"@vitejs/plugin-react": "^4.0.0",
|
|
177
|
-
"vite-node": "^3.2.0"
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
**Key differences for TypeScript backends**:
|
|
183
|
-
- **`vite-node server.ts`**: Direct TypeScript execution in development
|
|
184
|
-
- **`tsx server.ts`**: Fast TypeScript runner for production
|
|
185
|
-
- **`type: "module"`**: Enable ES modules in Node.js
|
|
186
|
-
- **`cross-env`**: Cross-platform environment variables
|
|
187
|
-
|
|
188
|
-
**When to use this setup**:
|
|
189
|
-
- Building APIs alongside your frontend
|
|
190
|
-
- Need database connections, authentication, file uploads
|
|
191
|
-
- Want full TypeScript integration across the stack
|
|
192
|
-
- Require additional Express middleware and routes
|
|
193
|
-
|
|
194
|
-
**Key Points**:
|
|
195
|
-
- **Un solo `vite build`**: el plugin declara los entornos de cliente y servidor, y ambos se construyen en una sola invocación.
|
|
196
|
-
- **Separate builds**: Client and server are built separately with different entry points
|
|
197
|
-
- **Auto-generated entries**: `getClientEntriesInput()` discovers all page/platform combinations
|
|
198
|
-
|
|
199
|
-
### Auto Server (WIP)
|
|
200
|
-
|
|
201
|
-
```typescript
|
|
202
|
-
import { createAutoViteServer } from '@ressjs/vite-router'
|
|
203
|
-
|
|
204
|
-
// Automatically configures Vite dev server with SSR (Work In Progress)
|
|
205
|
-
const { start } = await createAutoViteServer({
|
|
206
|
-
port: 3000,
|
|
207
|
-
enablePlatformDetection: true
|
|
208
|
-
})
|
|
209
|
-
|
|
210
|
-
start()
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
## 🎯 Dynamic Routes
|
|
214
|
-
|
|
215
|
-
Create pages with parameters using Next.js-style bracket syntax:
|
|
216
|
-
|
|
217
|
-
### File Structure
|
|
218
|
-
```
|
|
219
|
-
app/pages/
|
|
220
|
-
├── index.tsx # / route
|
|
221
|
-
├── about.tsx # /about route
|
|
222
|
-
├── users/
|
|
223
|
-
│ ├── index.tsx # /users route
|
|
224
|
-
│ └── [id].tsx # /users/:id route
|
|
225
|
-
├── products/
|
|
226
|
-
│ ├── [category].tsx # /products/:category route
|
|
227
|
-
│ └── [category]/
|
|
228
|
-
│ └── [id].tsx # /products/:category/:id route
|
|
229
|
-
└── blog/
|
|
230
|
-
└── [...slug].tsx # /blog/* route (coming soon)
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
### Route Examples
|
|
234
|
-
|
|
235
|
-
| File | Route | Express Route | URL Example |
|
|
236
|
-
|------|-------|---------------|-------------|
|
|
237
|
-
| `users/[id].tsx` | `/users/[id]` | `/users/:id` | `/users/123` |
|
|
238
|
-
| `products/[category]/[id].tsx` | `/products/[category]/[id]` | `/products/:category/:id` | `/products/phones/iphone` |
|
|
239
|
-
| `photocard/[photoId].tsx` | `/photocard/[photoId]` | `/photocard/:photoId` | `/photocard/abc123xyz` |
|
|
240
|
-
|
|
241
|
-
### Accessing Parameters
|
|
242
|
-
|
|
243
|
-
```typescript
|
|
244
|
-
// app/pages/users/[id].tsx
|
|
245
|
-
export default function UserPage({ id, user }) {
|
|
246
|
-
return (
|
|
247
|
-
<div>
|
|
248
|
-
<h1>User {id}</h1>
|
|
249
|
-
<p>Name: {user.name}</p>
|
|
250
|
-
</div>
|
|
251
|
-
)
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
export async function getServerSideProps(req, res) {
|
|
255
|
-
const { id } = req.params // Access route parameters
|
|
256
|
-
|
|
257
|
-
// Fetch user data
|
|
258
|
-
const user = await fetchUser(id)
|
|
259
|
-
|
|
260
|
-
return {
|
|
261
|
-
props: { id, user }
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
### Dynamic Route Styles
|
|
267
|
-
|
|
268
|
-
Dynamic routes support platform-specific styles:
|
|
269
|
-
|
|
270
|
-
```
|
|
271
|
-
app/pages/products/[id].tsx # Product page component
|
|
272
|
-
app/pages/products/[id].scss # Desktop styles
|
|
273
|
-
app/pages/products/[id].mobile.scss # Mobile styles
|
|
274
|
-
app/pages/products/[id].webview.scss # WebView styles
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
## 🔧 Middleware System
|
|
278
|
-
|
|
279
|
-
**Important**: Dynamic routes `[param].tsx` do **NOT** support dedicated middleware files. Use page-level or directory-level middleware instead.
|
|
280
|
-
|
|
281
|
-
### Middleware Execution Order
|
|
282
|
-
|
|
283
|
-
```
|
|
284
|
-
app/pages/
|
|
285
|
-
├── middlewares.ts # --> Executes 1st (global)
|
|
286
|
-
├── products/
|
|
287
|
-
│ ├── middlewares.ts # --> Executes 2nd (directory-level)
|
|
288
|
-
│ ├── index.tsx
|
|
289
|
-
│ ├── index.middlewares.ts # --> Executes 3rd (page-specific)
|
|
290
|
-
│ └── [id].tsx # --> No middleware support for dynamic routes
|
|
291
|
-
├── users/
|
|
292
|
-
│ ├── [id].tsx # --> Uses directory and global middleware only
|
|
293
|
-
│ └── middlewares.ts # --> Executes for all /users/* routes
|
|
294
|
-
└── checkout/
|
|
295
|
-
├── middlewares.ts # --> Executes 2nd for /checkout/*
|
|
296
|
-
├── step1.tsx
|
|
297
|
-
├── step1.middlewares.ts # --> Executes 3rd for /checkout/step1
|
|
298
|
-
├── step2.tsx
|
|
299
|
-
└── step2.middlewares.ts # --> Executes 3rd for /checkout/step2
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
### Middleware Types
|
|
303
|
-
|
|
304
|
-
#### 1. Global Middleware
|
|
305
|
-
```typescript
|
|
306
|
-
// app/pages/middlewares.ts --> Executes 1st for ALL routes
|
|
307
|
-
export default function globalMiddleware(req, res, next) {
|
|
308
|
-
console.log('Global middleware for:', req.url)
|
|
309
|
-
req.startTime = Date.now()
|
|
310
|
-
next()
|
|
311
|
-
}
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
#### 2. Directory Middleware
|
|
315
|
-
```typescript
|
|
316
|
-
// app/pages/products/middlewares.ts --> Executes 2nd for /products/*
|
|
317
|
-
export default function productsMiddleware(req, res, next) {
|
|
318
|
-
console.log('Products middleware for:', req.url)
|
|
319
|
-
req.section = 'products'
|
|
320
|
-
next()
|
|
321
|
-
}
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
#### 3. Page-Specific Middleware
|
|
325
|
-
```typescript
|
|
326
|
-
// app/pages/products/index.middlewares.ts --> Executes 3rd for /products only
|
|
327
|
-
export default function productListMiddleware(req, res, next) {
|
|
328
|
-
console.log('Product list middleware')
|
|
329
|
-
req.page = 'product-list'
|
|
330
|
-
next()
|
|
331
|
-
}
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
#### ❌ Not Supported for Dynamic Routes
|
|
335
|
-
```typescript
|
|
336
|
-
// ❌ app/pages/products/[id].middlewares.ts - NOT supported
|
|
337
|
-
// Dynamic routes cannot have dedicated middleware files
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
### Complete Execution Flow Example
|
|
341
|
-
|
|
342
|
-
For URL `/products/123`:
|
|
343
|
-
|
|
344
|
-
1. **Global**: `app/pages/middlewares.ts` (if exists)
|
|
345
|
-
2. **Directory**: `app/pages/products/middlewares.ts` (if exists)
|
|
346
|
-
3. **Page**: Built-in `getServerSideProps` from `[id].tsx`
|
|
347
|
-
4. **Render**: Component render and HTML generation
|
|
348
|
-
|
|
349
|
-
## 📱 Platform Detection
|
|
350
|
-
|
|
351
|
-
The router automatically detects and serves platform-specific assets:
|
|
352
|
-
|
|
353
|
-
### Detection Capabilities
|
|
354
|
-
|
|
355
|
-
- **Device Type**: `phone`, `tablet`, `desktop`
|
|
356
|
-
- **Operating System**: `ios`, `android`, `windows`, `macos`, `linux`
|
|
357
|
-
- **Environment**: `webview`, `web`, `native`
|
|
358
|
-
- **Category**: `webview.android`, `webview.ios`, `mobile`, etc.
|
|
359
|
-
|
|
360
|
-
### Platform Headers (React Native)
|
|
361
|
-
|
|
362
|
-
React Native clients should send these headers:
|
|
363
|
-
|
|
364
|
-
```javascript
|
|
365
|
-
{
|
|
366
|
-
'x-ressjs-platform': 'webview', // Required
|
|
367
|
-
'x-ressjs-os': 'ios', // Required
|
|
368
|
-
'x-ressjs-device': 'phone', // Required
|
|
369
|
-
'x-ressjs-version': Platform.Version, // Optional
|
|
370
|
-
'x-ressjs-app-version': '1.0.0' // Optional
|
|
371
|
-
}
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
### Asset Resolution Priority
|
|
375
|
-
|
|
376
|
-
For a page like `app/pages/home/index.tsx`:
|
|
377
|
-
|
|
378
|
-
1. **Device + OS Specific**: `index.phone.ios.scss`
|
|
379
|
-
2. **Device Specific**: `index.phone.scss`
|
|
380
|
-
3. **Category Specific**: `index.mobile.scss`
|
|
381
|
-
4. **WebView Specific**: `index.webview.scss`
|
|
382
|
-
5. **Base Fallback**: `index.scss`
|
|
383
|
-
|
|
384
|
-
### Platform CSS Examples
|
|
385
|
-
|
|
386
|
-
```
|
|
387
|
-
app/pages/home/
|
|
388
|
-
├── index.tsx # React component
|
|
389
|
-
├── index.scss # Desktop/base styles
|
|
390
|
-
├── index.mobile.scss # Phone + tablet
|
|
391
|
-
├── index.phone.scss # Phone only
|
|
392
|
-
├── index.tablet.scss # Tablet only
|
|
393
|
-
├── index.webview.scss # All WebView
|
|
394
|
-
├── index.webview.ios.scss # iOS WebView
|
|
395
|
-
├── index.webview.android.scss # Android WebView
|
|
396
|
-
└── index.desktop.linux.scss # Linux desktop
|
|
397
|
-
```
|
|
398
|
-
|
|
399
|
-
## 🎨 getServerSideProps
|
|
400
|
-
|
|
401
|
-
Every page can export a `getServerSideProps` function for server-side data fetching:
|
|
402
|
-
|
|
403
|
-
```typescript
|
|
404
|
-
export async function getServerSideProps(req, res) {
|
|
405
|
-
// Access route parameters (for dynamic routes)
|
|
406
|
-
const { id, category } = req.params
|
|
407
|
-
|
|
408
|
-
// Access query parameters
|
|
409
|
-
const { search, filter } = req.query
|
|
410
|
-
|
|
411
|
-
// Access request headers
|
|
412
|
-
const userAgent = req.headers['user-agent']
|
|
413
|
-
|
|
414
|
-
// Return props for the component
|
|
415
|
-
return {
|
|
416
|
-
props: {
|
|
417
|
-
id,
|
|
418
|
-
data: await fetchData(id),
|
|
419
|
-
timestamp: new Date().toISOString()
|
|
420
|
-
},
|
|
421
|
-
// Optional: HTML modifications
|
|
422
|
-
title: `Product ${id}`,
|
|
423
|
-
html: {
|
|
424
|
-
head: {
|
|
425
|
-
title: `Custom Title`,
|
|
426
|
-
extraTags: ['<meta name="description" content="...">']
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
## 🚀 API Reference
|
|
434
|
-
|
|
435
|
-
### createViteRouter(options)
|
|
436
|
-
|
|
437
|
-
```typescript
|
|
438
|
-
interface ViteRouterOptions {
|
|
439
|
-
enablePlatformDetection?: boolean // Enable platform detection (default: true)
|
|
440
|
-
vite?: any // Vite dev server instance
|
|
441
|
-
manifest?: any // Production manifest
|
|
442
|
-
templateHtml?: string // HTML template
|
|
443
|
-
isProduction?: boolean // Production mode
|
|
444
|
-
renderFunction?: (options: { // Custom render function
|
|
445
|
-
url: string
|
|
446
|
-
platform: string
|
|
447
|
-
req: any
|
|
448
|
-
}) => Promise<string>
|
|
449
|
-
}
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
### createAutoViteServer(options)
|
|
453
|
-
|
|
454
|
-
```typescript
|
|
455
|
-
interface AutoViteServerOptions {
|
|
456
|
-
port?: number // Server port (default: 5173)
|
|
457
|
-
base?: string // Base path (default: '/')
|
|
458
|
-
enablePlatformDetection?: boolean // Enable platform detection (default: true)
|
|
459
|
-
}
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
### Utility Functions
|
|
463
|
-
|
|
464
|
-
```typescript
|
|
465
|
-
import {
|
|
466
|
-
getPages,
|
|
467
|
-
listDetectedPages,
|
|
468
|
-
convertRouteToExpress
|
|
469
|
-
} from '@ressjs/vite-router'
|
|
470
|
-
|
|
471
|
-
// Get all discovered pages with route info
|
|
472
|
-
const pages = getPages()
|
|
473
|
-
// [{ route: '/users/[id]', expressRoute: '/users/:id', file: '...', abs: '...' }]
|
|
474
|
-
|
|
475
|
-
// Convert Next.js route to Express route
|
|
476
|
-
const expressRoute = convertRouteToExpress('/users/[id]') // '/users/:id'
|
|
477
|
-
```
|
|
478
|
-
|
|
479
|
-
## 🔧 Production Build
|
|
13
|
+
## Getting started
|
|
480
14
|
|
|
481
|
-
|
|
15
|
+
The recommended way to start is to generate an app, which comes already configured:
|
|
482
16
|
|
|
483
17
|
```bash
|
|
484
|
-
|
|
485
|
-
vite build --outDir dist/client
|
|
486
|
-
|
|
487
|
-
# 2. Build server bundle
|
|
488
|
-
vite build --ssr --outDir dist/server
|
|
489
|
-
|
|
490
|
-
# 3. Start production server
|
|
491
|
-
NODE_ENV=production node server.js
|
|
492
|
-
```
|
|
493
|
-
|
|
494
|
-
### Example Production Server
|
|
495
|
-
|
|
496
|
-
```typescript
|
|
497
|
-
import express from 'express'
|
|
498
|
-
import { createViteRouter } from '@ressjs/vite-router'
|
|
499
|
-
|
|
500
|
-
const app = express()
|
|
501
|
-
|
|
502
|
-
// Serve static assets
|
|
503
|
-
app.use('/assets', express.static('dist/client/assets'))
|
|
504
|
-
|
|
505
|
-
// Create router with production settings
|
|
506
|
-
const router = createViteRouter({
|
|
507
|
-
isProduction: true,
|
|
508
|
-
enablePlatformDetection: true
|
|
509
|
-
})
|
|
510
|
-
|
|
511
|
-
app.use('/', router)
|
|
512
|
-
app.listen(3000)
|
|
18
|
+
npx @ressjs/create-ress-app my-app
|
|
513
19
|
```
|
|
514
20
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
### Dynamic Route Not Working
|
|
518
|
-
|
|
519
|
-
1. **Check file naming**: Use `[param].tsx`, not `{param}.tsx`
|
|
520
|
-
2. **Verify parameters**: Access via `req.params.param` in `getServerSideProps`
|
|
521
|
-
3. **Build order**: Run `npm run build` after adding new dynamic routes
|
|
522
|
-
|
|
523
|
-
### Middleware Not Executing
|
|
524
|
-
|
|
525
|
-
1. **File naming**: Use `middlewares.ts` (plural) or `page.middlewares.ts`
|
|
526
|
-
2. **Dynamic routes**: Don't create `[param].middlewares.ts` - not supported
|
|
527
|
-
3. **Export**: Use `export default function` format
|
|
528
|
-
|
|
529
|
-
### Platform Detection Issues
|
|
530
|
-
|
|
531
|
-
1. **Headers**: Ensure React Native sends required `x-ressjs-*` headers
|
|
532
|
-
2. **CSS files**: Create platform-specific CSS files if needed
|
|
533
|
-
3. **Case sensitivity**: Use lowercase for OS names (`ios`, `android`)
|
|
534
|
-
|
|
535
|
-
## 📄 License
|
|
536
|
-
|
|
537
|
-
MIT
|
|
21
|
+
Use the `@ressjs/cli` commands (`ress dev`, `ress build`, `ress start`) to run it.
|
|
538
22
|
|
|
539
|
-
|
|
23
|
+
## License
|
|
540
24
|
|
|
541
|
-
|
|
25
|
+
Proprietary. See [LICENSE](./LICENSE).
|
package/dist/client/entry.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { Script, Style } from '@ressjs/assets/client';
|
|
2
|
-
export type { ScriptProps, StyleProps } from '@ressjs/assets/client';
|
|
1
|
+
export { Head, Script, Style } from '@ressjs/assets/client';
|
|
2
|
+
export type { HeadProps, ScriptProps, StyleProps } from '@ressjs/assets/client';
|
package/dist/client/entry.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { Script, Style } from '@ressjs/assets/client';
|
|
1
|
+
export { Head, Script, Style } from '@ressjs/assets/client';
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { Script, Style } from '@ressjs/assets';
|
|
2
|
-
export type { ScriptProps, StyleProps } from '@ressjs/assets';
|
|
1
|
+
export { Head, Script, Style } from '@ressjs/assets/client';
|
|
2
|
+
export type { HeadProps, ScriptProps, StyleProps } from '@ressjs/assets/client';
|
package/dist/client/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Style = exports.Script = void 0;
|
|
4
|
-
//
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Object.defineProperty(exports, "Script", { enumerable: true, get: function () { return
|
|
8
|
-
Object.defineProperty(exports, "Style", { enumerable: true, get: function () { return
|
|
3
|
+
exports.Style = exports.Script = exports.Head = void 0;
|
|
4
|
+
// Compatibility alias. The implementation is owned by @ressjs/assets.
|
|
5
|
+
var client_1 = require("@ressjs/assets/client");
|
|
6
|
+
Object.defineProperty(exports, "Head", { enumerable: true, get: function () { return client_1.Head; } });
|
|
7
|
+
Object.defineProperty(exports, "Script", { enumerable: true, get: function () { return client_1.Script; } });
|
|
8
|
+
Object.defineProperty(exports, "Style", { enumerable: true, get: function () { return client_1.Style; } });
|
package/dist/config/codegen.d.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import type { PlatformConfig } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Tipos generados a partir de lo que el proyecto declara.
|
|
4
|
+
*
|
|
5
|
+
* Sin esto, declarar un token de plataforma propio en `ress.config.ts` funciona
|
|
6
|
+
* en tiempo de ejecución pero el editor no lo conoce: el desarrollador escribe
|
|
7
|
+
* `'kaios'` y no recibe ni sugerencia ni error si lo escribe mal. Los archivos se
|
|
8
|
+
* generan, no se versionan, y se rehacen cuando cambia la configuración que los
|
|
9
|
+
* origina.
|
|
10
|
+
*/
|
|
2
11
|
/**
|
|
3
12
|
* Amplía `PlatformValueMap` de `@ressjs/platform` con los tokens del proyecto.
|
|
4
13
|
*
|
|
@@ -21,3 +30,9 @@ export declare function generateProjectConfigTypes(values: Record<string, unknow
|
|
|
21
30
|
* volvería a generar, en un ciclo que no termina.
|
|
22
31
|
*/
|
|
23
32
|
export declare function writeGeneratedTypes(root: string, files: Record<string, string>): Promise<string[]>;
|
|
33
|
+
/**
|
|
34
|
+
* Genera `types/` sólo para proyectos con `tsconfig.json` cuya configuración se cargó con
|
|
35
|
+
* `loadConfig`. La usan el plugin al arrancar y `ress info`, para que un
|
|
36
|
+
* proyecto recién creado o un clon limpio tengan sus tipos sin levantar nada.
|
|
37
|
+
*/
|
|
38
|
+
export declare function writeProjectTypes(root: string, platform: PlatformConfig): Promise<string[]>;
|