@ressjs/vite-router 0.5.2 → 0.6.0-rc.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/LICENSE +69 -0
- package/README.md +9 -515
- package/dist/client/entry.d.mts +2 -0
- package/dist/client/entry.mjs +1 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.js +8 -0
- package/dist/config/base-path.d.ts +44 -0
- package/dist/config/base-path.js +100 -0
- package/dist/config/codegen.d.ts +29 -0
- package/dist/config/codegen.js +131 -0
- package/dist/config/define.d.ts +8 -0
- package/dist/config/define.js +12 -0
- package/dist/config/env.d.ts +19 -0
- package/dist/config/env.js +40 -0
- package/dist/config/index.d.ts +18 -0
- package/dist/config/index.js +46 -0
- package/dist/config/load.d.ts +28 -0
- package/dist/config/load.js +82 -0
- package/dist/config/middleware.d.ts +18 -0
- package/dist/config/middleware.js +79 -0
- package/dist/config/rules.d.ts +59 -0
- package/dist/config/rules.js +162 -0
- package/dist/config/types.d.ts +189 -0
- package/dist/config/types.js +2 -0
- package/dist/config/validate.d.ts +19 -0
- package/dist/config/validate.js +143 -0
- package/dist/config/watch.d.ts +53 -0
- package/dist/config/watch.js +163 -0
- package/dist/fs/module-extensions.d.ts +105 -0
- package/dist/fs/module-extensions.js +213 -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 +26 -6
- package/dist/helpers/html-generator.js +96 -138
- package/dist/helpers/middlewares.d.ts +32 -21
- package/dist/helpers/middlewares.js +181 -159
- 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 +15 -2
- package/dist/helpers/request-handler.js +164 -27
- package/dist/index.d.ts +35 -3
- package/dist/index.js +77 -8
- package/dist/isr/capture.d.ts +79 -0
- package/dist/isr/capture.js +222 -0
- package/dist/isr/handler.d.ts +49 -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 +41 -0
- package/dist/isr/response.js +128 -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/pages.d.ts +10 -9
- package/dist/pages.js +42 -261
- package/dist/platform.d.ts +11 -14
- package/dist/platform.js +18 -102
- package/dist/plugin/environments.d.ts +68 -0
- package/dist/plugin/environments.js +74 -0
- package/dist/plugin/index.d.ts +59 -0
- package/dist/plugin/index.js +195 -0
- package/dist/plugin/route-manifest.d.ts +19 -0
- package/dist/plugin/route-manifest.js +55 -0
- package/dist/plugin/virtual-entries.d.ts +26 -0
- package/dist/plugin/virtual-entries.js +80 -0
- package/dist/render.d.ts +39 -2
- package/dist/render.js +75 -77
- package/dist/router.d.ts +32 -13
- package/dist/router.js +180 -146
- package/dist/routes/dispatcher.d.ts +58 -0
- package/dist/routes/dispatcher.js +70 -0
- package/dist/routes/manifest.d.ts +17 -0
- package/dist/routes/manifest.js +62 -0
- package/dist/routes/match.d.ts +20 -0
- package/dist/routes/match.js +75 -0
- package/dist/routes/module.d.ts +14 -0
- package/dist/routes/module.js +30 -0
- package/dist/routes/parse.d.ts +31 -0
- package/dist/routes/parse.js +114 -0
- package/dist/routes/rank.d.ts +12 -0
- package/dist/routes/rank.js +49 -0
- package/dist/routes/router.d.ts +54 -0
- package/dist/routes/router.js +153 -0
- package/dist/routes/scan.d.ts +26 -0
- package/dist/routes/scan.js +98 -0
- package/dist/routes/types.d.ts +114 -0
- package/dist/routes/types.js +17 -0
- package/dist/runtime/dev-server.d.ts +64 -0
- package/dist/runtime/dev-server.js +94 -0
- package/dist/runtime/dev-styles.d.ts +13 -0
- package/dist/runtime/dev-styles.js +50 -0
- package/dist/runtime/module-loader.d.ts +55 -0
- package/dist/runtime/module-loader.js +122 -0
- package/dist/runtime/prod-server.d.ts +55 -0
- package/dist/runtime/prod-server.js +188 -0
- package/dist/runtime/template.d.ts +10 -0
- package/dist/runtime/template.js +33 -0
- package/dist/security/client-props.d.ts +25 -0
- package/dist/security/client-props.js +51 -0
- package/dist/security/config.d.ts +121 -0
- package/dist/security/config.js +77 -0
- package/dist/security/csp.d.ts +53 -0
- package/dist/security/csp.js +118 -0
- package/dist/security/dev-hardening.d.ts +46 -0
- package/dist/security/dev-hardening.js +65 -0
- package/dist/security/errors.d.ts +37 -0
- package/dist/security/errors.js +84 -0
- package/dist/security/escape.d.ts +40 -0
- package/dist/security/escape.js +90 -0
- package/dist/security/head-tags.d.ts +32 -0
- package/dist/security/head-tags.js +156 -0
- package/dist/security/headers.d.ts +76 -0
- package/dist/security/headers.js +278 -0
- package/dist/security/index.d.ts +24 -0
- package/dist/security/index.js +49 -0
- package/dist/security/serialize.d.ts +48 -0
- package/dist/security/serialize.js +146 -0
- package/dist/variants/assets.d.ts +33 -0
- package/dist/variants/assets.js +144 -0
- package/dist/variants/catalog.d.ts +33 -0
- package/dist/variants/catalog.js +79 -0
- package/dist/variants/platform-tokens.d.ts +9 -0
- package/dist/variants/platform-tokens.js +15 -0
- package/dist/variants/resolve.d.ts +40 -0
- package/dist/variants/resolve.js +90 -0
- package/dist/variants/suffix.d.ts +8 -0
- package/dist/variants/suffix.js +12 -0
- package/dist/variants/types.d.ts +72 -0
- package/dist/variants/types.js +2 -0
- package/package.json +23 -11
- package/dist/helpers/vite-config.d.ts +0 -10
- package/dist/helpers/vite-config.js +0 -90
package/dist/pages.js
CHANGED
|
@@ -1,54 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
4
|
};
|
|
38
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
6
|
exports.convertRouteToExpress = convertRouteToExpress;
|
|
40
7
|
exports.getPages = getPages;
|
|
41
|
-
exports.getViteInput = getViteInput;
|
|
42
8
|
exports.getViteSSRInput = getViteSSRInput;
|
|
43
|
-
exports.loadManifest = loadManifest;
|
|
44
|
-
exports.getCompiledProdPage = getCompiledProdPage;
|
|
45
|
-
exports.resolvePlatformCSS = resolvePlatformCSS;
|
|
46
|
-
exports.generateTempEntries = generateTempEntries;
|
|
47
|
-
exports.generateSingleEntry = generateSingleEntry;
|
|
48
|
-
exports.getClientEntriesInput = getClientEntriesInput;
|
|
49
|
-
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
50
9
|
const node_path_1 = __importDefault(require("node:path"));
|
|
51
10
|
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
11
|
+
const catalog_1 = require("./variants/catalog");
|
|
12
|
+
const module_extensions_1 = require("./fs/module-extensions");
|
|
52
13
|
/**
|
|
53
14
|
* Convierte rutas estilo Next.js con parámetros dinámicos a formato Express
|
|
54
15
|
* Ejemplos:
|
|
@@ -59,241 +20,61 @@ const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
|
59
20
|
function convertRouteToExpress(route) {
|
|
60
21
|
return route.replace(/\[([^\]]+)\]/g, ':$1');
|
|
61
22
|
}
|
|
62
|
-
function getPages() {
|
|
63
|
-
|
|
64
|
-
|
|
23
|
+
function getPages(policy = (0, module_extensions_1.getExtensionPolicy)()) {
|
|
24
|
+
const files = fast_glob_1.default
|
|
25
|
+
.sync((0, module_extensions_1.pageGlob)(policy))
|
|
26
|
+
.filter((file) => (0, module_extensions_1.isPageFile)(file, policy))
|
|
27
|
+
.sort();
|
|
28
|
+
// Dos archivos que definen la misma página son ambiguos: cuál gana dependería
|
|
29
|
+
// del orden del sistema de archivos, que cambia entre sistemas operativos.
|
|
30
|
+
//
|
|
31
|
+
// En desarrollo se avisa y se sigue con el primero, para no dejar el servidor
|
|
32
|
+
// caído mientras alguien renombra un archivo; al construir se falla.
|
|
33
|
+
(0, module_extensions_1.assertNoModuleCollision)(files, 'app/pages', {
|
|
34
|
+
strict: process.env.NODE_ENV === 'production',
|
|
35
|
+
});
|
|
65
36
|
const seen = new Set();
|
|
66
37
|
const pages = [];
|
|
67
38
|
for (const file of files) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
39
|
+
// `page1.tsx` y `page1/index.tsx` describen la misma URL. Gana el primero
|
|
40
|
+
// por orden alfabético, que es estable.
|
|
41
|
+
const route = ('/' + (0, module_extensions_1.pageIdOf)(file)).replace(/\/index$/, '') || '/';
|
|
42
|
+
if (seen.has(route))
|
|
43
|
+
continue;
|
|
44
|
+
seen.add(route);
|
|
45
|
+
pages.push({
|
|
46
|
+
route,
|
|
47
|
+
expressRoute: convertRouteToExpress(route),
|
|
48
|
+
file,
|
|
49
|
+
abs: node_path_1.default.resolve(file),
|
|
50
|
+
pageId: (0, catalog_1.pageIdFromFile)(file),
|
|
51
|
+
});
|
|
76
52
|
}
|
|
77
53
|
return pages;
|
|
78
54
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Entradas del entorno de servidor: las páginas más sus middlewares.
|
|
57
|
+
*
|
|
58
|
+
* El entorno de cliente no aparece acá: sus entradas salen del catálogo de
|
|
59
|
+
* variantes, porque una página produce una por cada plataforma que atiende.
|
|
60
|
+
*/
|
|
61
|
+
function getViteSSRInput() {
|
|
82
62
|
const input = {};
|
|
83
|
-
for (const page of
|
|
84
|
-
input[
|
|
63
|
+
for (const page of getPages()) {
|
|
64
|
+
input[(0, module_extensions_1.pageIdOf)(page.file)] = page.abs;
|
|
85
65
|
}
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
// Para Vite SSR: input incluyendo páginas + middlewares
|
|
89
|
-
function getViteSSRInput() {
|
|
90
|
-
const input = getViteInput(); // Empezar con las páginas
|
|
91
|
-
// Agregar TODOS los middlewares: .middlewares.ts y middlewares.ts
|
|
92
|
-
const middlewareFiles = fast_glob_1.default.sync('app/pages/**/{middlewares,*.middlewares}.{ts,js}');
|
|
66
|
+
const middlewareFiles = (0, module_extensions_1.middlewareGlobs)((0, module_extensions_1.getExtensionPolicy)()).flatMap((g) => fast_glob_1.default.sync(g));
|
|
93
67
|
for (const middlewareFile of middlewareFiles) {
|
|
94
|
-
|
|
95
|
-
|
|
68
|
+
// La clave define dónde queda el artefacto, así que tiene que coincidir con
|
|
69
|
+
// lo que `toCompiledPath` busca al importarlo en producción. Con la
|
|
70
|
+
// extensión adentro se emitía `algo.middlewares.tsx.js` y la carga fallaba.
|
|
71
|
+
input[(0, module_extensions_1.pageIdOf)(middlewareFile)] = node_path_1.default.resolve(middlewareFile);
|
|
96
72
|
}
|
|
97
73
|
return input;
|
|
98
74
|
}
|
|
99
|
-
async function loadManifest(distPath = 'dist') {
|
|
100
|
-
const assetsDir = node_path_1.default.join(distPath, 'server/.vite');
|
|
101
|
-
const files = await promises_1.default.readdir(assetsDir);
|
|
102
|
-
const manifestFile = files.find(f => /^manifest-.*\.js$/.test(f));
|
|
103
|
-
if (!manifestFile)
|
|
104
|
-
throw new Error('No manifest file found in dist/server/assets');
|
|
105
|
-
// Import dinámico del manifest
|
|
106
|
-
const manifest = (await Promise.resolve(`${node_path_1.default.join(assetsDir, manifestFile)}`).then(s => __importStar(require(s)))).default;
|
|
107
|
-
return manifest;
|
|
108
|
-
}
|
|
109
75
|
/**
|
|
110
76
|
* Convierte una ruta de página TypeScript a su equivalente compilado en producción
|
|
111
77
|
*
|
|
112
78
|
* @param pageFile - Ruta del archivo de página (relativa: "app/pages/pokedex/index.tsx" o absoluta: "/path/to/app/pages/pokedex/index.tsx")
|
|
113
79
|
* @returns Ruta absoluta del archivo compilado (ej: "/path/to/project/dist/server/pokedex/index.js")
|
|
114
80
|
*/
|
|
115
|
-
function getCompiledProdPage(pageFile) {
|
|
116
|
-
if (!pageFile.endsWith('.tsx')) {
|
|
117
|
-
throw new Error(`getCompiledProdPage expects a .tsx file, got: ${pageFile}`);
|
|
118
|
-
}
|
|
119
|
-
// Si es una ruta absoluta, extraer solo la parte relativa
|
|
120
|
-
let relativePath;
|
|
121
|
-
if (node_path_1.default.isAbsolute(pageFile)) {
|
|
122
|
-
// Buscar la parte después de "app/pages/" or "app\pages\" (Windows-compatible)
|
|
123
|
-
const normalizedPath = pageFile.replace(/\\/g, '/');
|
|
124
|
-
const appPagesIndex = normalizedPath.indexOf('app/pages/');
|
|
125
|
-
if (appPagesIndex === -1) {
|
|
126
|
-
throw new Error(`Absolute path must contain "app/pages/", got: ${pageFile}`);
|
|
127
|
-
}
|
|
128
|
-
relativePath = normalizedPath.substring(appPagesIndex);
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
relativePath = pageFile;
|
|
132
|
-
}
|
|
133
|
-
// Convertir app/pages/pokedex/index.tsx a dist/server/pokedex/index.js
|
|
134
|
-
// También convierte [id] a _id_ para rutas dinámicas
|
|
135
|
-
const compiledRelativePath = relativePath
|
|
136
|
-
.replace(/^app\/pages\//, '') // Quitar prefijo app/pages/
|
|
137
|
-
.replace(/\.tsx$/, '.js') // Cambiar extensión .tsx a .js
|
|
138
|
-
.replace(/\[([^\]]+)\]/g, '_$1_'); // Convertir [id] a _id_
|
|
139
|
-
return node_path_1.default.resolve(process.cwd(), 'dist', 'server', compiledRelativePath);
|
|
140
|
-
}
|
|
141
|
-
async function fileExists(file) {
|
|
142
|
-
try {
|
|
143
|
-
await promises_1.default.access(file);
|
|
144
|
-
return true;
|
|
145
|
-
}
|
|
146
|
-
catch {
|
|
147
|
-
return false;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Platform-aware CSS resolution
|
|
152
|
-
* Busca CSS files con prioridades basadas en platform detection
|
|
153
|
-
*/
|
|
154
|
-
// Función helper para determinar si es probablemente un dispositivo móvil
|
|
155
|
-
function isProbablyMobile(platform) {
|
|
156
|
-
// Mobile si es phone/tablet, o webview (que suele ser mobile), o category native (React Native)
|
|
157
|
-
return platform.device === 'phone' ||
|
|
158
|
-
platform.device === 'tablet' ||
|
|
159
|
-
platform.category === 'webview' ||
|
|
160
|
-
platform.category === 'native';
|
|
161
|
-
}
|
|
162
|
-
async function resolvePlatformCSS(basePath, platform) {
|
|
163
|
-
// Orden de prioridad corregido: OS first → device+OS → device → mobile condicional
|
|
164
|
-
const priorities = [];
|
|
165
|
-
// 1. OS específico primero: android.scss, ios.scss
|
|
166
|
-
priorities.push(`${basePath}.${platform.os}.scss`);
|
|
167
|
-
// Para webview, agregar combinaciones específicas después del OS
|
|
168
|
-
if (platform.category === 'webview') {
|
|
169
|
-
// 2. webview.os.scss (ej: webview.android.scss, webview.ios.scss)
|
|
170
|
-
priorities.push(`${basePath}.webview.${platform.os}.scss`);
|
|
171
|
-
// 3. webview.scss general
|
|
172
|
-
priorities.push(`${basePath}.webview.scss`);
|
|
173
|
-
}
|
|
174
|
-
// Para native o web, agregar combinaciones device.os
|
|
175
|
-
if (platform.category === 'native' || platform.category === 'web') {
|
|
176
|
-
// 2. device.os.scss (ej: phone.android.scss, tablet.ios.scss)
|
|
177
|
-
priorities.push(`${basePath}.${platform.device}.${platform.os}.scss`);
|
|
178
|
-
}
|
|
179
|
-
// 3. Device específico: phone.scss, tablet.scss, desktop.scss
|
|
180
|
-
priorities.push(`${basePath}.${platform.device}.scss`);
|
|
181
|
-
// 4. Mobile fallback SOLO si es probablemente móvil
|
|
182
|
-
if (isProbablyMobile(platform)) {
|
|
183
|
-
priorities.push(`${basePath}.mobile.scss`);
|
|
184
|
-
}
|
|
185
|
-
// 5. Fallback final
|
|
186
|
-
priorities.push(`${basePath}.scss`);
|
|
187
|
-
// Retorna el primer archivo que exista
|
|
188
|
-
for (const file of priorities) {
|
|
189
|
-
if (await fileExists(file)) {
|
|
190
|
-
return file;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
// Si ninguno existe, retorna el CSS base
|
|
194
|
-
return `${basePath}.scss`;
|
|
195
|
-
}
|
|
196
|
-
async function generateTempEntries(distPath = 'dist', platformInfo) {
|
|
197
|
-
const pages = getPages();
|
|
198
|
-
const entriesDir = node_path_1.default.resolve(distPath, '.entries');
|
|
199
|
-
// Solo crea el directorio si no existe, no lo borra
|
|
200
|
-
await promises_1.default.mkdir(entriesDir, { recursive: true });
|
|
201
|
-
const promises = pages.map(async (page) => {
|
|
202
|
-
// Sanitizar nombre: convertir [id] a _id_ para nombres de archivo
|
|
203
|
-
const rel = page.file
|
|
204
|
-
.replace(/^app\/pages\//, '')
|
|
205
|
-
.replace(/\.tsx$|\.jsx$/, '')
|
|
206
|
-
.replace(/\//g, '__')
|
|
207
|
-
.replace(/\[([^\]]+)\]/g, '_$1_');
|
|
208
|
-
if (platformInfo && platformInfo.device !== 'desktop') {
|
|
209
|
-
// Solo genera entry específico para mobile devices (phone, tablet)
|
|
210
|
-
const basePath = page.file.replace(/\.(tsx|jsx)$/, '');
|
|
211
|
-
const platformCSS = await resolvePlatformCSS(basePath, platformInfo);
|
|
212
|
-
// Generar entry específico con el CSS resuelto (puede ser base o específico)
|
|
213
|
-
const platformSuffix = `${platformInfo.device}.${platformInfo.os}`;
|
|
214
|
-
const entryPath = node_path_1.default.join(entriesDir, rel + `__entry-client.${platformSuffix}.tsx`);
|
|
215
|
-
await generateSingleEntry(page, entryPath, platformCSS);
|
|
216
|
-
return [entryPath];
|
|
217
|
-
}
|
|
218
|
-
else {
|
|
219
|
-
// Lógica mejorada: busca dinámicamente todos los archivos CSS específicos
|
|
220
|
-
const basePath = page.file.replace(/\.(tsx|jsx)$/, '');
|
|
221
|
-
const baseScss = basePath + '.scss';
|
|
222
|
-
const results = [];
|
|
223
|
-
// Genera entry-client base (desktop) - solo CSS base
|
|
224
|
-
const entryPath = node_path_1.default.join(entriesDir, rel + '__entry-client.tsx');
|
|
225
|
-
await generateSingleEntry(page, entryPath, baseScss);
|
|
226
|
-
results.push(entryPath);
|
|
227
|
-
// Buscar dinámicamente todos los archivos CSS específicos de plataforma
|
|
228
|
-
const glob = await Promise.resolve().then(() => __importStar(require('fast-glob')));
|
|
229
|
-
const cssFiles = await glob.default(`${basePath}.*.scss`);
|
|
230
|
-
for (const cssFile of cssFiles) {
|
|
231
|
-
// Extraer el sufijo del archivo CSS (ej: mobile, webview.android, desktop.linux)
|
|
232
|
-
const suffix = cssFile
|
|
233
|
-
.replace(basePath + '.', '')
|
|
234
|
-
.replace('.scss', '');
|
|
235
|
-
// Generar entry-client específico
|
|
236
|
-
const specificEntryPath = node_path_1.default.join(entriesDir, rel + `__entry-client.${suffix}.tsx`);
|
|
237
|
-
await generateSingleEntry(page, specificEntryPath, cssFile);
|
|
238
|
-
results.push(specificEntryPath);
|
|
239
|
-
}
|
|
240
|
-
return results;
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
const entryFiles = await Promise.all(promises);
|
|
244
|
-
return entryFiles.flat().filter(Boolean);
|
|
245
|
-
}
|
|
246
|
-
async function generateSingleEntry(page, entryPath, preferredScssFile) {
|
|
247
|
-
// Verifica si el archivo ya existe y es más reciente que el archivo fuente
|
|
248
|
-
try {
|
|
249
|
-
const entryStat = await promises_1.default.stat(entryPath);
|
|
250
|
-
const pageStat = await promises_1.default.stat(page.abs);
|
|
251
|
-
if (entryStat.mtime > pageStat.mtime) {
|
|
252
|
-
return; // El entry ya existe y está actualizado
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
catch {
|
|
256
|
-
// El archivo no existe, continúa con la generación
|
|
257
|
-
}
|
|
258
|
-
const importPath = node_path_1.default.relative(node_path_1.default.dirname(entryPath), page.abs).replace(/\\/g, '/');
|
|
259
|
-
// Lógica de fallback: intenta cargar el CSS preferido, si no existe carga el base
|
|
260
|
-
let scssToImport = '';
|
|
261
|
-
let scssImport = '';
|
|
262
|
-
if (await fileExists(preferredScssFile)) {
|
|
263
|
-
// Existe el CSS específico, usarlo
|
|
264
|
-
scssToImport = preferredScssFile;
|
|
265
|
-
}
|
|
266
|
-
else {
|
|
267
|
-
// No existe el CSS específico, usar el CSS base como fallback
|
|
268
|
-
const baseScss = page.file.replace(/\.(tsx|jsx)$/, '.scss');
|
|
269
|
-
if (await fileExists(baseScss)) {
|
|
270
|
-
scssToImport = baseScss;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
if (scssToImport) {
|
|
274
|
-
const scssImportPath = node_path_1.default.relative(node_path_1.default.dirname(entryPath), scssToImport).replace(/\\/g, '/');
|
|
275
|
-
scssImport = `import "${scssImportPath.startsWith('.') ? scssImportPath : './' + scssImportPath}";`;
|
|
276
|
-
}
|
|
277
|
-
const template = `
|
|
278
|
-
${scssImport}
|
|
279
|
-
import { StrictMode } from "react";
|
|
280
|
-
import { hydrateRoot } from "react-dom/client";
|
|
281
|
-
import Page from "${importPath.startsWith('.') ? importPath : './' + importPath}";
|
|
282
|
-
const props = window.__INITIAL_PROPS__ || {};
|
|
283
|
-
hydrateRoot(document.getElementById("root"), <StrictMode><Page {...props} /></StrictMode>);
|
|
284
|
-
`.trim();
|
|
285
|
-
await promises_1.default.mkdir(node_path_1.default.dirname(entryPath), { recursive: true });
|
|
286
|
-
await promises_1.default.writeFile(entryPath, template);
|
|
287
|
-
}
|
|
288
|
-
async function getClientEntriesInput(distPath = 'dist') {
|
|
289
|
-
await generateTempEntries(distPath);
|
|
290
|
-
// Incluir todos los entry-clients: base, mobile, desktop.linux
|
|
291
|
-
const entryFiles = fast_glob_1.default.sync(`${distPath}/.entries/**/*__entry-client*.tsx`);
|
|
292
|
-
const input = {};
|
|
293
|
-
for (const file of entryFiles) {
|
|
294
|
-
// Mantener el nombre completo del archivo como key para diferenciar las plataformas
|
|
295
|
-
const key = file.replace(new RegExp(`^${distPath}/\\.entries/`), '');
|
|
296
|
-
input[key] = node_path_1.default.resolve(file);
|
|
297
|
-
}
|
|
298
|
-
return input;
|
|
299
|
-
}
|
package/dist/platform.d.ts
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Detección de plataforma.
|
|
3
|
+
*
|
|
4
|
+
* La implementación vive en `@ressjs/platform`, que no depende del router ni de
|
|
5
|
+
* Vite: así el puente del WebView, el cliente y cualquier consumidor externo
|
|
6
|
+
* pueden preguntarle lo mismo sin arrastrar el framework entero.
|
|
7
|
+
*
|
|
8
|
+
* Este archivo existe para que `import { detectPlatform } from '@ressjs/vite-router'`
|
|
9
|
+
* siga funcionando.
|
|
4
10
|
*/
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
device: 'phone' | 'tablet' | 'desktop';
|
|
9
|
-
version?: string;
|
|
10
|
-
appVersion?: string;
|
|
11
|
-
source: 'headers' | 'user-agent';
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Detecta plataforma usando headers custom + User-Agent fallback
|
|
15
|
-
*/
|
|
16
|
-
export declare function detectPlatform(userAgent: string, headers?: any): PlatformInfo;
|
|
11
|
+
export { detect, detectPlatform, DEFAULT_PLATFORM } from '@ressjs/platform';
|
|
12
|
+
export { hasCapability, isHandheld, isTV, isWebView } from '@ressjs/platform';
|
|
13
|
+
export type { NativeAppInfo, PlatformDevice, PlatformInfo, PlatformOS } from '@ressjs/platform';
|
package/dist/platform.js
CHANGED
|
@@ -1,106 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Detección de plataforma.
|
|
4
|
+
*
|
|
5
|
+
* La implementación vive en `@ressjs/platform`, que no depende del router ni de
|
|
6
|
+
* Vite: así el puente del WebView, el cliente y cualquier consumidor externo
|
|
7
|
+
* pueden preguntarle lo mismo sin arrastrar el framework entero.
|
|
8
|
+
*
|
|
9
|
+
* Este archivo existe para que `import { detectPlatform } from '@ressjs/vite-router'`
|
|
10
|
+
* siga funcionando.
|
|
5
11
|
*/
|
|
6
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.detectPlatform =
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
function
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
os: ressHeaders['x-rn-platform'] || 'android',
|
|
18
|
-
device: 'phone', // React Native es típicamente mobile
|
|
19
|
-
version: ressHeaders['x-rn-version'],
|
|
20
|
-
source: 'headers'
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
// 2. WebView headers detection
|
|
24
|
-
if (ressHeaders['x-webview'] === 'true' || ressHeaders['x-ressjs-platform'] === 'webview') {
|
|
25
|
-
const os = ressHeaders['x-platform'] || ressHeaders['x-ressjs-os'] || 'android';
|
|
26
|
-
return {
|
|
27
|
-
category: 'webview',
|
|
28
|
-
os: os,
|
|
29
|
-
device: ressHeaders['x-ressjs-device'] || 'phone',
|
|
30
|
-
version: ressHeaders['x-ressjs-version'],
|
|
31
|
-
appVersion: ressHeaders['x-ressjs-app-version'],
|
|
32
|
-
source: 'headers'
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
// 3. Ress.js specific headers (original logic)
|
|
36
|
-
if (ressHeaders['x-ressjs-platform'] === 'webview') {
|
|
37
|
-
return {
|
|
38
|
-
category: 'webview',
|
|
39
|
-
os: ressHeaders['x-ressjs-os'] || 'android',
|
|
40
|
-
device: ressHeaders['x-ressjs-device'] || 'phone',
|
|
41
|
-
version: ressHeaders['x-ressjs-version'],
|
|
42
|
-
appVersion: ressHeaders['x-ressjs-app-version'],
|
|
43
|
-
source: 'headers'
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
// 4. User-Agent fallback detection
|
|
47
|
-
return detectFromUserAgent(userAgent);
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Detección por User-Agent (navegadores estándar)
|
|
51
|
-
*/
|
|
52
|
-
function detectFromUserAgent(userAgent) {
|
|
53
|
-
const ua = userAgent.toLowerCase();
|
|
54
|
-
// SPECIAL CASE: React Native
|
|
55
|
-
if (ua.includes('reactnative')) {
|
|
56
|
-
let os = 'android';
|
|
57
|
-
if (ua.includes('ios')) {
|
|
58
|
-
os = 'ios';
|
|
59
|
-
}
|
|
60
|
-
else if (ua.includes('android')) {
|
|
61
|
-
os = 'android';
|
|
62
|
-
}
|
|
63
|
-
return {
|
|
64
|
-
category: 'native',
|
|
65
|
-
os,
|
|
66
|
-
device: 'phone', // React Native siempre mobile
|
|
67
|
-
source: 'user-agent'
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
// Detectar OS
|
|
71
|
-
let os = 'unknown';
|
|
72
|
-
if (ua.includes('iphone') || ua.includes('ipad') || ua.includes('ios')) {
|
|
73
|
-
os = 'ios';
|
|
74
|
-
}
|
|
75
|
-
else if (ua.includes('android')) {
|
|
76
|
-
os = 'android';
|
|
77
|
-
}
|
|
78
|
-
else if (ua.includes('windows')) {
|
|
79
|
-
os = 'windows';
|
|
80
|
-
}
|
|
81
|
-
else if (ua.includes('macintosh') || ua.includes('mac os x')) {
|
|
82
|
-
os = 'macos';
|
|
83
|
-
}
|
|
84
|
-
else if (ua.includes('linux')) {
|
|
85
|
-
os = 'linux';
|
|
86
|
-
}
|
|
87
|
-
// Detectar device type
|
|
88
|
-
let device = 'desktop';
|
|
89
|
-
if (ua.includes('ipad')) {
|
|
90
|
-
device = 'tablet';
|
|
91
|
-
}
|
|
92
|
-
else if (ua.includes('mobile') || ua.includes('phone')) {
|
|
93
|
-
device = 'phone';
|
|
94
|
-
}
|
|
95
|
-
else if (ua.includes('tablet')) {
|
|
96
|
-
device = 'tablet';
|
|
97
|
-
}
|
|
98
|
-
// Detectar category (web vs webview)
|
|
99
|
-
let category = 'web';
|
|
100
|
-
return {
|
|
101
|
-
category,
|
|
102
|
-
os,
|
|
103
|
-
device,
|
|
104
|
-
source: 'user-agent'
|
|
105
|
-
};
|
|
106
|
-
}
|
|
13
|
+
exports.isWebView = exports.isTV = exports.isHandheld = exports.hasCapability = exports.DEFAULT_PLATFORM = exports.detectPlatform = exports.detect = void 0;
|
|
14
|
+
var platform_1 = require("@ressjs/platform");
|
|
15
|
+
Object.defineProperty(exports, "detect", { enumerable: true, get: function () { return platform_1.detect; } });
|
|
16
|
+
Object.defineProperty(exports, "detectPlatform", { enumerable: true, get: function () { return platform_1.detectPlatform; } });
|
|
17
|
+
Object.defineProperty(exports, "DEFAULT_PLATFORM", { enumerable: true, get: function () { return platform_1.DEFAULT_PLATFORM; } });
|
|
18
|
+
var platform_2 = require("@ressjs/platform");
|
|
19
|
+
Object.defineProperty(exports, "hasCapability", { enumerable: true, get: function () { return platform_2.hasCapability; } });
|
|
20
|
+
Object.defineProperty(exports, "isHandheld", { enumerable: true, get: function () { return platform_2.isHandheld; } });
|
|
21
|
+
Object.defineProperty(exports, "isTV", { enumerable: true, get: function () { return platform_2.isTV; } });
|
|
22
|
+
Object.defineProperty(exports, "isWebView", { enumerable: true, get: function () { return platform_2.isWebView; } });
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declaración de los entornos de build de ress.js.
|
|
3
|
+
*
|
|
4
|
+
* Cliente y servidor se describen como entornos de Vite, de modo que una sola
|
|
5
|
+
* invocación de build produzca ambos.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Directorios de salida.
|
|
9
|
+
*
|
|
10
|
+
* Es la única declaración: la comparten el build y el runtime de producción, que
|
|
11
|
+
* es lo que garantiza que el servidor busque donde el build escribió.
|
|
12
|
+
*/
|
|
13
|
+
/** Archivo con el identificador del build, junto a `route-manifest.json`. */
|
|
14
|
+
export declare const BUILD_ID_FILE = "BUILD_ID";
|
|
15
|
+
export declare const OUT_DIR: {
|
|
16
|
+
/** Raíz de salida. El manifest de rutas vive acá, junto a los dos entornos. */
|
|
17
|
+
readonly base: "dist";
|
|
18
|
+
readonly client: "dist/client";
|
|
19
|
+
readonly ssr: "dist/server";
|
|
20
|
+
};
|
|
21
|
+
export interface EnvironmentInputs {
|
|
22
|
+
client: Record<string, string>;
|
|
23
|
+
ssr: Record<string, string>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Construye la porción de configuración de Vite que aporta el framework.
|
|
27
|
+
*
|
|
28
|
+
* Se devuelve desde el hook `config` del plugin, de modo que Vite la fusione con
|
|
29
|
+
* la configuración del usuario según sus reglas normales: lo que el usuario
|
|
30
|
+
* declare se aplica encima sin que el framework lo pise.
|
|
31
|
+
*
|
|
32
|
+
* Las entradas llegan resueltas desde afuera. Quién las enumera es un detalle
|
|
33
|
+
* interno del framework, no algo que el proyecto consumidor deba declarar en su
|
|
34
|
+
* `vite.config.ts`.
|
|
35
|
+
*/
|
|
36
|
+
export declare function defineEnvironments(inputs?: EnvironmentInputs): {
|
|
37
|
+
environments: {
|
|
38
|
+
client: {
|
|
39
|
+
build: {
|
|
40
|
+
outDir: "dist/client";
|
|
41
|
+
manifest: boolean;
|
|
42
|
+
rolldownOptions: {
|
|
43
|
+
input: Record<string, string>;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
ssr: {
|
|
48
|
+
build: {
|
|
49
|
+
outDir: "dist/server";
|
|
50
|
+
ssr: boolean;
|
|
51
|
+
rolldownOptions: {
|
|
52
|
+
input: Record<string, string>;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
builder: {
|
|
58
|
+
/**
|
|
59
|
+
* Secuencial, y en este orden: el build de servidor necesita el manifest
|
|
60
|
+
* que produce el de cliente para poder resolver assets por página. En
|
|
61
|
+
* paralelo, el servidor podría leer un manifest incompleto o inexistente.
|
|
62
|
+
*/
|
|
63
|
+
buildApp: (builder: {
|
|
64
|
+
environments: Record<string, unknown>;
|
|
65
|
+
build: (env: unknown) => Promise<unknown>;
|
|
66
|
+
}) => Promise<void>;
|
|
67
|
+
};
|
|
68
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Declaración de los entornos de build de ress.js.
|
|
4
|
+
*
|
|
5
|
+
* Cliente y servidor se describen como entornos de Vite, de modo que una sola
|
|
6
|
+
* invocación de build produzca ambos.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.OUT_DIR = exports.BUILD_ID_FILE = void 0;
|
|
10
|
+
exports.defineEnvironments = defineEnvironments;
|
|
11
|
+
/**
|
|
12
|
+
* Directorios de salida.
|
|
13
|
+
*
|
|
14
|
+
* Es la única declaración: la comparten el build y el runtime de producción, que
|
|
15
|
+
* es lo que garantiza que el servidor busque donde el build escribió.
|
|
16
|
+
*/
|
|
17
|
+
/** Archivo con el identificador del build, junto a `route-manifest.json`. */
|
|
18
|
+
exports.BUILD_ID_FILE = 'BUILD_ID';
|
|
19
|
+
exports.OUT_DIR = {
|
|
20
|
+
/** Raíz de salida. El manifest de rutas vive acá, junto a los dos entornos. */
|
|
21
|
+
base: 'dist',
|
|
22
|
+
client: 'dist/client',
|
|
23
|
+
ssr: 'dist/server',
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Construye la porción de configuración de Vite que aporta el framework.
|
|
27
|
+
*
|
|
28
|
+
* Se devuelve desde el hook `config` del plugin, de modo que Vite la fusione con
|
|
29
|
+
* la configuración del usuario según sus reglas normales: lo que el usuario
|
|
30
|
+
* declare se aplica encima sin que el framework lo pise.
|
|
31
|
+
*
|
|
32
|
+
* Las entradas llegan resueltas desde afuera. Quién las enumera es un detalle
|
|
33
|
+
* interno del framework, no algo que el proyecto consumidor deba declarar en su
|
|
34
|
+
* `vite.config.ts`.
|
|
35
|
+
*/
|
|
36
|
+
function defineEnvironments(inputs = { client: {}, ssr: {} }) {
|
|
37
|
+
const clientOutDir = exports.OUT_DIR.client;
|
|
38
|
+
const ssrOutDir = exports.OUT_DIR.ssr;
|
|
39
|
+
return {
|
|
40
|
+
environments: {
|
|
41
|
+
client: {
|
|
42
|
+
build: {
|
|
43
|
+
outDir: clientOutDir,
|
|
44
|
+
// El manifest del cliente es lo que permite al servidor resolver, en
|
|
45
|
+
// producción, qué artefacto corresponde a cada página y variante.
|
|
46
|
+
manifest: true,
|
|
47
|
+
rolldownOptions: {
|
|
48
|
+
input: inputs.client,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
ssr: {
|
|
53
|
+
build: {
|
|
54
|
+
outDir: ssrOutDir,
|
|
55
|
+
ssr: true,
|
|
56
|
+
rolldownOptions: {
|
|
57
|
+
input: inputs.ssr,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
builder: {
|
|
63
|
+
/**
|
|
64
|
+
* Secuencial, y en este orden: el build de servidor necesita el manifest
|
|
65
|
+
* que produce el de cliente para poder resolver assets por página. En
|
|
66
|
+
* paralelo, el servidor podría leer un manifest incompleto o inexistente.
|
|
67
|
+
*/
|
|
68
|
+
buildApp: async (builder) => {
|
|
69
|
+
await builder.build(builder.environments.client);
|
|
70
|
+
await builder.build(builder.environments.ssr);
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|