@ressjs/vite-router 0.5.0 → 0.6.0-experimental.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +41 -31
  2. package/dist/client/entry.d.mts +2 -0
  3. package/dist/client/entry.mjs +1 -0
  4. package/dist/client/index.d.ts +2 -0
  5. package/dist/client/index.js +8 -0
  6. package/dist/config/base-path.d.ts +44 -0
  7. package/dist/config/base-path.js +100 -0
  8. package/dist/config/codegen.d.ts +23 -0
  9. package/dist/config/codegen.js +118 -0
  10. package/dist/config/define.d.ts +8 -0
  11. package/dist/config/define.js +12 -0
  12. package/dist/config/env.d.ts +19 -0
  13. package/dist/config/env.js +40 -0
  14. package/dist/config/index.d.ts +18 -0
  15. package/dist/config/index.js +44 -0
  16. package/dist/config/load.d.ts +26 -0
  17. package/dist/config/load.js +73 -0
  18. package/dist/config/middleware.d.ts +18 -0
  19. package/dist/config/middleware.js +79 -0
  20. package/dist/config/rules.d.ts +48 -0
  21. package/dist/config/rules.js +149 -0
  22. package/dist/config/types.d.ts +164 -0
  23. package/dist/config/types.js +2 -0
  24. package/dist/config/validate.d.ts +19 -0
  25. package/dist/config/validate.js +105 -0
  26. package/dist/config/watch.d.ts +41 -0
  27. package/dist/config/watch.js +132 -0
  28. package/dist/fs/module-extensions.d.ts +82 -0
  29. package/dist/fs/module-extensions.js +196 -0
  30. package/dist/helpers/html-generator.d.ts +22 -5
  31. package/dist/helpers/html-generator.js +89 -120
  32. package/dist/helpers/middlewares.d.ts +7 -7
  33. package/dist/helpers/middlewares.js +51 -103
  34. package/dist/helpers/request-handler.d.ts +2 -2
  35. package/dist/helpers/request-handler.js +118 -25
  36. package/dist/index.d.ts +30 -3
  37. package/dist/index.js +70 -8
  38. package/dist/pages.d.ts +10 -9
  39. package/dist/pages.js +42 -261
  40. package/dist/platform.d.ts +11 -14
  41. package/dist/platform.js +18 -102
  42. package/dist/plugin/environments.d.ts +66 -0
  43. package/dist/plugin/environments.js +72 -0
  44. package/dist/plugin/index.d.ts +54 -0
  45. package/dist/plugin/index.js +178 -0
  46. package/dist/plugin/virtual-entries.d.ts +26 -0
  47. package/dist/plugin/virtual-entries.js +80 -0
  48. package/dist/render.d.ts +23 -2
  49. package/dist/render.js +40 -53
  50. package/dist/router.d.ts +32 -13
  51. package/dist/router.js +147 -146
  52. package/dist/routes/dispatcher.d.ts +37 -0
  53. package/dist/routes/dispatcher.js +69 -0
  54. package/dist/routes/manifest.d.ts +17 -0
  55. package/dist/routes/manifest.js +56 -0
  56. package/dist/routes/match.d.ts +20 -0
  57. package/dist/routes/match.js +75 -0
  58. package/dist/routes/parse.d.ts +31 -0
  59. package/dist/routes/parse.js +114 -0
  60. package/dist/routes/rank.d.ts +12 -0
  61. package/dist/routes/rank.js +49 -0
  62. package/dist/routes/router.d.ts +44 -0
  63. package/dist/routes/router.js +81 -0
  64. package/dist/routes/scan.d.ts +16 -0
  65. package/dist/routes/scan.js +82 -0
  66. package/dist/routes/types.d.ts +85 -0
  67. package/dist/routes/types.js +13 -0
  68. package/dist/runtime/dev-server.d.ts +62 -0
  69. package/dist/runtime/dev-server.js +94 -0
  70. package/dist/runtime/module-loader.d.ts +55 -0
  71. package/dist/runtime/module-loader.js +122 -0
  72. package/dist/runtime/prod-server.d.ts +42 -0
  73. package/dist/runtime/prod-server.js +142 -0
  74. package/dist/runtime/template.d.ts +10 -0
  75. package/dist/runtime/template.js +33 -0
  76. package/dist/security/client-props.d.ts +25 -0
  77. package/dist/security/client-props.js +50 -0
  78. package/dist/security/config.d.ts +130 -0
  79. package/dist/security/config.js +73 -0
  80. package/dist/security/csp.d.ts +53 -0
  81. package/dist/security/csp.js +118 -0
  82. package/dist/security/dev-hardening.d.ts +46 -0
  83. package/dist/security/dev-hardening.js +65 -0
  84. package/dist/security/errors.d.ts +37 -0
  85. package/dist/security/errors.js +84 -0
  86. package/dist/security/escape.d.ts +40 -0
  87. package/dist/security/escape.js +90 -0
  88. package/dist/security/head-tags.d.ts +32 -0
  89. package/dist/security/head-tags.js +111 -0
  90. package/dist/security/headers.d.ts +62 -0
  91. package/dist/security/headers.js +187 -0
  92. package/dist/security/index.d.ts +24 -0
  93. package/dist/security/index.js +47 -0
  94. package/dist/security/serialize.d.ts +48 -0
  95. package/dist/security/serialize.js +146 -0
  96. package/dist/variants/assets.d.ts +23 -0
  97. package/dist/variants/assets.js +78 -0
  98. package/dist/variants/catalog.d.ts +33 -0
  99. package/dist/variants/catalog.js +79 -0
  100. package/dist/variants/platform-tokens.d.ts +9 -0
  101. package/dist/variants/platform-tokens.js +15 -0
  102. package/dist/variants/resolve.d.ts +40 -0
  103. package/dist/variants/resolve.js +90 -0
  104. package/dist/variants/suffix.d.ts +8 -0
  105. package/dist/variants/suffix.js +12 -0
  106. package/dist/variants/types.d.ts +69 -0
  107. package/dist/variants/types.js +2 -0
  108. package/package.json +22 -10
  109. package/dist/helpers/vite-config.d.ts +0 -10
  110. package/dist/helpers/vite-config.js +0 -90
package/README.md CHANGED
@@ -19,37 +19,47 @@ npm install @ressjs/vite-router
19
19
  - **🚀 Production Ready**: Optimized builds with manifest-based asset loading
20
20
  - **📝 TypeScript**: Full TypeScript support with comprehensive type definitions
21
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
+
22
49
  ## Quick Start
23
50
 
24
51
  ### Vite Configuration
25
52
 
26
53
  Create a `vite.config.ts` file in your project root:
27
54
 
28
- ```typescript
55
+ ```ts
29
56
  import { defineConfig } from 'vite'
30
57
  import react from '@vitejs/plugin-react'
31
- import { getClientEntriesInput, getViteSSRInput } from '@ressjs/vite-router'
32
-
33
- const isSSR = !!process.env.VITE_SSR_BUILD
58
+ import { ressPlugin } from '@ressjs/vite-router/plugin'
34
59
 
35
- export default defineConfig(async () => ({
36
- plugins: [react()],
37
- server: {
38
- watch: {
39
- ignored: ['**/dist/.entries/**'] // Ignore generated entries
40
- }
41
- },
42
- build: {
43
- manifest: true,
44
- outDir: isSSR ? 'dist/server' : 'dist/client',
45
- rollupOptions: {
46
- input: isSSR
47
- ? getViteSSRInput() // SSR entry point
48
- : await getClientEntriesInput(), // Auto-generated client entries
49
- },
50
- ssr: isSSR,
51
- },
52
- }))
60
+ export default defineConfig({
61
+ plugins: [react(), ressPlugin()],
62
+ })
53
63
  ```
54
64
 
55
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.
@@ -113,10 +123,8 @@ Add these scripts to your `package.json`:
113
123
  {
114
124
  "scripts": {
115
125
  "dev": "node server.js",
116
- "build": "npm run build:client && npm run build:server",
117
- "build:client": "vite build",
118
- "build:server": "VITE_SSR_BUILD=true vite build",
119
- "preview": "NODE_ENV=production node server.js",
126
+ "build": "vite build",
127
+ "preview": "NODE_ENV=production node server.js",
120
128
  "type-check": "tsc --noEmit"
121
129
  },
122
130
  "dependencies": {
@@ -146,10 +154,8 @@ For full-stack TypeScript projects with backend APIs, use this enhanced configur
146
154
  "type": "module",
147
155
  "scripts": {
148
156
  "dev": "PORT=3000 vite-node server.ts",
149
- "build": "npm run build:client && npm run build:server",
150
- "build:client": "vite build --outDir dist/client",
151
- "build:server": "cross-env VITE_SSR_BUILD=1 vite build --ssr --outDir dist/server",
152
- "preview": "cross-env NODE_ENV=production PORT=3000 tsx server.ts",
157
+ "build": "vite build",
158
+ "preview": "cross-env NODE_ENV=production PORT=3000 tsx server.ts",
153
159
  "start": "npm run build && npm run preview"
154
160
  },
155
161
  "dependencies": {
@@ -186,7 +192,7 @@ For full-stack TypeScript projects with backend APIs, use this enhanced configur
186
192
  - Require additional Express middleware and routes
187
193
 
188
194
  **Key Points**:
189
- - **`VITE_SSR_BUILD=true`**: Environment variable that tells Vite config to build for SSR
195
+ - **Un solo `vite build`**: el plugin declara los entornos de cliente y servidor, y ambos se construyen en una sola invocación.
190
196
  - **Separate builds**: Client and server are built separately with different entry points
191
197
  - **Auto-generated entries**: `getClientEntriesInput()` discovers all page/platform combinations
192
198
 
@@ -529,3 +535,7 @@ app.listen(3000)
529
535
  ## 📄 License
530
536
 
531
537
  MIT
538
+
539
+ ### `index.html` opcional
540
+
541
+ El router usa `index.html` del proyecto como shell cuando existe. Si no existe, usa una plantilla interna mínima con el contenedor `#root`; el SSR, los estilos y el entry cliente se inyectan igual. Mantener `index.html` permite personalizar el documento.
@@ -0,0 +1,2 @@
1
+ export { Script, Style } from '@ressjs/assets/client';
2
+ export type { ScriptProps, StyleProps } from '@ressjs/assets/client';
@@ -0,0 +1 @@
1
+ export { Script, Style } from '@ressjs/assets/client';
@@ -0,0 +1,2 @@
1
+ export { Script, Style } from '@ressjs/assets';
2
+ export type { ScriptProps, StyleProps } from '@ressjs/assets';
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Style = exports.Script = void 0;
4
+ // CJS compatibility entry. The ESM entrypoint is `entry.mts` and uses the
5
+ // browser-oriented `@ressjs/assets/client` export.
6
+ var assets_1 = require("@ressjs/assets");
7
+ Object.defineProperty(exports, "Script", { enumerable: true, get: function () { return assets_1.Script; } });
8
+ Object.defineProperty(exports, "Style", { enumerable: true, get: function () { return assets_1.Style; } });
@@ -0,0 +1,44 @@
1
+ import type { TrailingSlashMode } from './types';
2
+ /**
3
+ * Prefijo de ruta y barra final.
4
+ *
5
+ * Las dos reglas describen la **misma URL escrita de distintas maneras**, así que
6
+ * se aplican antes que cualquier otra cosa del pipeline: a partir de ahí, el
7
+ * manifest de rutas, las redirecciones y las reescrituras ven una sola forma de
8
+ * cada petición y no tienen que contemplar variantes.
9
+ */
10
+ /**
11
+ * La forma canónica de una ruta según la política de barra final, o `undefined`
12
+ * si ya lo es.
13
+ *
14
+ * Devolver `undefined` en vez de la misma cadena es lo que permite a quien llama
15
+ * distinguir «hay que redirigir» de «no hay nada que hacer» sin comparar strings.
16
+ */
17
+ export declare function canonicalTrailingSlash(pathname: string, mode: TrailingSlashMode): string | undefined;
18
+ /**
19
+ * Quita el prefijo de ruta.
20
+ *
21
+ * Devuelve `undefined` cuando la URL no cae bajo el prefijo: eso no es una ruta
22
+ * que esta aplicación atienda, y responder algo sería atender el sitio entero por
23
+ * dos direcciones distintas.
24
+ */
25
+ export declare function stripBasePath(pathname: string, basePath: string): string | undefined;
26
+ /**
27
+ * Antepone el prefijo a una ruta de la aplicación.
28
+ *
29
+ * Se usa para todo lo que el framework emite hacia el navegador —enlaces,
30
+ * artefactos, destinos de redirección—: una URL generada sin prefijo apunta
31
+ * afuera de la aplicación.
32
+ */
33
+ export declare function withBasePath(pathname: string, basePath: string): string;
34
+ /**
35
+ * El prefijo con el que se sirven los artefactos.
36
+ *
37
+ * `assets.cdnPrefix` gana sobre el prefijo de ruta porque describe otro origen:
38
+ * cuando existe, los artefactos no salen de este servidor y el prefijo de ruta
39
+ * no les aplica.
40
+ */
41
+ export declare function assetPrefixFor(options: {
42
+ basePath: string;
43
+ cdnPrefix?: string;
44
+ }): string;
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.canonicalTrailingSlash = canonicalTrailingSlash;
4
+ exports.stripBasePath = stripBasePath;
5
+ exports.withBasePath = withBasePath;
6
+ exports.assetPrefixFor = assetPrefixFor;
7
+ /**
8
+ * Prefijo de ruta y barra final.
9
+ *
10
+ * Las dos reglas describen la **misma URL escrita de distintas maneras**, así que
11
+ * se aplican antes que cualquier otra cosa del pipeline: a partir de ahí, el
12
+ * manifest de rutas, las redirecciones y las reescrituras ven una sola forma de
13
+ * cada petición y no tienen que contemplar variantes.
14
+ */
15
+ /**
16
+ * La forma canónica de una ruta según la política de barra final, o `undefined`
17
+ * si ya lo es.
18
+ *
19
+ * Devolver `undefined` en vez de la misma cadena es lo que permite a quien llama
20
+ * distinguir «hay que redirigir» de «no hay nada que hacer» sin comparar strings.
21
+ */
22
+ function canonicalTrailingSlash(pathname, mode) {
23
+ if (mode === 'ignore')
24
+ return undefined;
25
+ // La raíz es `/` en las dos políticas: no tiene una forma sin barra.
26
+ if (pathname === '/' || pathname === '')
27
+ return undefined;
28
+ const hasSlash = pathname.endsWith('/');
29
+ if (mode === 'never') {
30
+ if (!hasSlash)
31
+ return undefined;
32
+ const stripped = pathname.replace(/\/+$/, '');
33
+ return stripped === '' ? '/' : stripped;
34
+ }
35
+ if (hasSlash)
36
+ return undefined;
37
+ // Un último segmento con punto es un archivo —`/logo.svg`, `/robots.txt`—, y
38
+ // agregarle barra lo convierte en una ruta que no existe.
39
+ if (looksLikeFile(pathname))
40
+ return undefined;
41
+ return pathname + '/';
42
+ }
43
+ function looksLikeFile(pathname) {
44
+ const last = pathname.slice(pathname.lastIndexOf('/') + 1);
45
+ return last.includes('.');
46
+ }
47
+ /**
48
+ * Quita el prefijo de ruta.
49
+ *
50
+ * Devuelve `undefined` cuando la URL no cae bajo el prefijo: eso no es una ruta
51
+ * que esta aplicación atienda, y responder algo sería atender el sitio entero por
52
+ * dos direcciones distintas.
53
+ */
54
+ function stripBasePath(pathname, basePath) {
55
+ if (!basePath)
56
+ return pathname;
57
+ if (pathname === basePath)
58
+ return '/';
59
+ if (pathname.startsWith(basePath + '/'))
60
+ return pathname.slice(basePath.length);
61
+ return undefined;
62
+ }
63
+ /**
64
+ * Antepone el prefijo a una ruta de la aplicación.
65
+ *
66
+ * Se usa para todo lo que el framework emite hacia el navegador —enlaces,
67
+ * artefactos, destinos de redirección—: una URL generada sin prefijo apunta
68
+ * afuera de la aplicación.
69
+ */
70
+ function withBasePath(pathname, basePath) {
71
+ if (!basePath)
72
+ return pathname;
73
+ // Una URL absoluta —un CDN, otro dominio— ya dice dónde vive: no se le
74
+ // antepone nada.
75
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(pathname) || pathname.startsWith('//'))
76
+ return pathname;
77
+ if (!pathname.startsWith('/'))
78
+ return basePath + '/' + pathname;
79
+ if (pathname === '/')
80
+ return basePath + '/';
81
+ return basePath + pathname;
82
+ }
83
+ /**
84
+ * El prefijo con el que se sirven los artefactos.
85
+ *
86
+ * `assets.cdnPrefix` gana sobre el prefijo de ruta porque describe otro origen:
87
+ * cuando existe, los artefactos no salen de este servidor y el prefijo de ruta
88
+ * no les aplica.
89
+ */
90
+ function assetPrefixFor(options) {
91
+ const prefix = options.cdnPrefix?.trim();
92
+ if (prefix)
93
+ return prefix.replace(/\/+$/, '') + '/';
94
+ // La raíz ya termina en `/`; agregar otra barra produce `//assets/...`,
95
+ // que el navegador interpreta como una URL de protocolo relativo hacia el
96
+ // host `assets` y deja fuera tanto el CSS como el entry de hidratación.
97
+ if (!options.basePath || options.basePath === '/')
98
+ return '/';
99
+ return options.basePath.replace(/\/+$/, '') + '/';
100
+ }
@@ -0,0 +1,23 @@
1
+ import type { PlatformConfig } from './types';
2
+ /**
3
+ * Amplía `PlatformValueMap` de `@ressjs/platform` con los tokens del proyecto.
4
+ *
5
+ * Se agrupa por eje porque la interfaz tiene una clave por eje, y declararla dos
6
+ * veces con tipos distintos es un error de compilación.
7
+ */
8
+ export declare function generatePlatformTypes(platform: PlatformConfig): string;
9
+ /**
10
+ * Amplía `ProjectConfig` de `@ressjs/config` con la forma de los valores resueltos.
11
+ *
12
+ * Se infiere de lo que la resolución produjo y no del archivo fuente: es lo que
13
+ * el proyecto va a leer realmente, capas incluidas.
14
+ */
15
+ export declare function generateProjectConfigTypes(values: Record<string, unknown>): string;
16
+ /**
17
+ * Escribe los dos archivos si cambiaron.
18
+ *
19
+ * Compara antes de escribir porque el observador de desarrollo mira el sistema de
20
+ * archivos: reescribir el mismo contenido dispararía una recarga que a su vez
21
+ * volvería a generar, en un ciclo que no termina.
22
+ */
23
+ export declare function writeGeneratedTypes(root: string, files: Record<string, string>): Promise<string[]>;
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generatePlatformTypes = generatePlatformTypes;
4
+ exports.generateProjectConfigTypes = generateProjectConfigTypes;
5
+ exports.writeGeneratedTypes = writeGeneratedTypes;
6
+ /**
7
+ * Tipos generados a partir de lo que el proyecto declara.
8
+ *
9
+ * Sin esto, declarar un token de plataforma propio en `ress.config.ts` funciona
10
+ * en tiempo de ejecución pero el editor no lo conoce: el desarrollador escribe
11
+ * `'kaios'` y no recibe ni sugerencia ni error si lo escribe mal. Los archivos se
12
+ * generan, no se versionan, y se rehacen cuando cambia la configuración que los
13
+ * origina.
14
+ */
15
+ const BANNER = '// Generado por ress.js a partir de la configuración del proyecto.\n' +
16
+ '// No editar a mano ni versionar: se rehace en cada arranque.\n';
17
+ /**
18
+ * Amplía `PlatformValueMap` de `@ressjs/platform` con los tokens del proyecto.
19
+ *
20
+ * Se agrupa por eje porque la interfaz tiene una clave por eje, y declararla dos
21
+ * veces con tipos distintos es un error de compilación.
22
+ */
23
+ function generatePlatformTypes(platform) {
24
+ const byAxis = new Map();
25
+ for (const value of platform.values ?? []) {
26
+ if (!value?.token || !value?.axis)
27
+ continue;
28
+ const tokens = byAxis.get(value.axis) ?? [];
29
+ if (!tokens.includes(value.token))
30
+ tokens.push(value.token);
31
+ byAxis.set(value.axis, tokens);
32
+ }
33
+ if (byAxis.size === 0) {
34
+ // Un archivo vacío igual se escribe: si el proyecto quitó sus tokens, dejar
35
+ // el anterior mantendría en el autocompletado valores que ya no existen.
36
+ return BANNER + 'export {}\n';
37
+ }
38
+ const fields = [...byAxis.entries()]
39
+ .sort(([a], [b]) => a.localeCompare(b))
40
+ .map(([axis, tokens]) => ` ${axis}: ${tokens.map(quote).join(' | ')}`)
41
+ .join('\n');
42
+ return (BANNER +
43
+ "declare module '@ressjs/platform' {\n" +
44
+ ' interface PlatformValueMap {\n' +
45
+ fields +
46
+ '\n }\n}\n\nexport {}\n');
47
+ }
48
+ /**
49
+ * Amplía `ProjectConfig` de `@ressjs/config` con la forma de los valores resueltos.
50
+ *
51
+ * Se infiere de lo que la resolución produjo y no del archivo fuente: es lo que
52
+ * el proyecto va a leer realmente, capas incluidas.
53
+ */
54
+ function generateProjectConfigTypes(values) {
55
+ const keys = Object.keys(values).sort();
56
+ if (keys.length === 0)
57
+ return BANNER + 'export {}\n';
58
+ const fields = keys.map((key) => ` ${propertyName(key)}: ${typeOf(values[key])}`).join('\n');
59
+ return (BANNER +
60
+ "declare module '@ressjs/config' {\n" +
61
+ ' interface ProjectConfig {\n' +
62
+ fields +
63
+ '\n }\n}\n\nexport {}\n');
64
+ }
65
+ /**
66
+ * El tipo de un valor, a un nivel de profundidad razonable.
67
+ *
68
+ * No se intenta reconstruir la forma exacta de una estructura anidada: el
69
+ * objetivo es autocompletar nombres de clave, y un tipo aproximado que se escribe
70
+ * en un archivo generado es mejor que uno exacto que nadie puede leer.
71
+ */
72
+ function typeOf(value) {
73
+ if (value === null || value === undefined)
74
+ return 'unknown';
75
+ if (Array.isArray(value)) {
76
+ const inner = value.length ? typeOf(value[0]) : 'unknown';
77
+ return `${inner}[]`;
78
+ }
79
+ if (typeof value === 'object') {
80
+ const entries = Object.entries(value);
81
+ if (!entries.length)
82
+ return 'Record<string, unknown>';
83
+ return ('{ ' + entries.map(([k, v]) => `${propertyName(k)}: ${typeOf(v)}`).join('; ') + ' }');
84
+ }
85
+ if (typeof value === 'function')
86
+ return '(...args: never[]) => unknown';
87
+ return typeof value;
88
+ }
89
+ /** Una clave que no es un identificador válido va entre comillas. */
90
+ function propertyName(key) {
91
+ return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? key : quote(key);
92
+ }
93
+ function quote(value) {
94
+ return JSON.stringify(value);
95
+ }
96
+ /**
97
+ * Escribe los dos archivos si cambiaron.
98
+ *
99
+ * Compara antes de escribir porque el observador de desarrollo mira el sistema de
100
+ * archivos: reescribir el mismo contenido dispararía una recarga que a su vez
101
+ * volvería a generar, en un ciclo que no termina.
102
+ */
103
+ async function writeGeneratedTypes(root, files) {
104
+ const { writeFile, mkdir, readFile } = await import('node:fs/promises');
105
+ const path = await import('node:path');
106
+ const dir = path.join(root, 'types');
107
+ const written = [];
108
+ for (const [name, content] of Object.entries(files)) {
109
+ const target = path.join(dir, name);
110
+ const previous = await readFile(target, 'utf-8').catch(() => undefined);
111
+ if (previous === content)
112
+ continue;
113
+ await mkdir(dir, { recursive: true });
114
+ await writeFile(target, content, 'utf-8');
115
+ written.push(target);
116
+ }
117
+ return written;
118
+ }
@@ -0,0 +1,8 @@
1
+ import type { RessConfig } from './types';
2
+ /**
3
+ * Declara la configuración del framework.
4
+ *
5
+ * No transforma nada: existe para que el editor conozca la forma del objeto
6
+ * mientras se escribe, en vez de descubrir el error al arrancar.
7
+ */
8
+ export declare function defineConfig(config: RessConfig): RessConfig;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defineConfig = defineConfig;
4
+ /**
5
+ * Declara la configuración del framework.
6
+ *
7
+ * No transforma nada: existe para que el editor conozca la forma del objeto
8
+ * mientras se escribe, en vez de descubrir el error al arrancar.
9
+ */
10
+ function defineConfig(config) {
11
+ return config;
12
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Variables de entorno que llegan al navegador.
3
+ *
4
+ * Por lista explícita y nunca por prefijo. Un prefijo hace que agregar una
5
+ * variable la publique sin que nadie tome esa decisión, y el modo de fallo —una
6
+ * credencial dentro del paquete que se descarga— es grave y silencioso.
7
+ *
8
+ * El reemplazo es en tiempo de build: lo que no está declarado no queda como
9
+ * `undefined` en el navegador, queda como código que nunca se generó.
10
+ */
11
+ export interface PublicEnvOptions {
12
+ /** De dónde se leen los valores. Se inyecta para poder probarlo. */
13
+ env?: Record<string, string | undefined>;
14
+ /** Si faltar una variable detiene el arranque. En build, sí. */
15
+ strict?: boolean;
16
+ }
17
+ export declare function publicEnvDefines(publicEnv: readonly string[], options?: PublicEnvOptions): Record<string, string>;
18
+ /** Los valores publicados, para inspeccionarlos o serializarlos. */
19
+ export declare function publicEnvValues(publicEnv: readonly string[], env?: Record<string, string | undefined>): Record<string, string>;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.publicEnvDefines = publicEnvDefines;
4
+ exports.publicEnvValues = publicEnvValues;
5
+ function publicEnvDefines(publicEnv, options = {}) {
6
+ const env = options.env ?? process.env;
7
+ const missing = [];
8
+ const defines = {};
9
+ for (const name of publicEnv) {
10
+ const value = env[name];
11
+ if (value === undefined) {
12
+ missing.push(name);
13
+ continue;
14
+ }
15
+ const literal = JSON.stringify(value);
16
+ // Las dos formas: el código de la aplicación suele escribir `process.env.X`
17
+ // por costumbre, y el de Vite `import.meta.env.X`. Reemplazar una sola deja
18
+ // la otra sin definir en el navegador, que es exactamente el error difícil
19
+ // de ver.
20
+ defines[`process.env.${name}`] = literal;
21
+ defines[`import.meta.env.${name}`] = literal;
22
+ }
23
+ if (missing.length && options.strict !== false) {
24
+ throw new Error(`[ress] \`publicEnv\` declara ${missing.length === 1 ? 'una variable que no existe' : 'variables que no existen'}: ` +
25
+ missing.join(', ') +
26
+ '. Exponer una variable inexistente es casi siempre un error de tipeo, y ' +
27
+ 'el navegador recibiría el nombre sin valor.');
28
+ }
29
+ return defines;
30
+ }
31
+ /** Los valores publicados, para inspeccionarlos o serializarlos. */
32
+ function publicEnvValues(publicEnv, env = process.env) {
33
+ const values = {};
34
+ for (const name of publicEnv) {
35
+ const value = env[name];
36
+ if (value !== undefined)
37
+ values[name] = value;
38
+ }
39
+ return values;
40
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Configuración del framework.
3
+ *
4
+ * `ress.config` declara el comportamiento; `@ressjs/config` declara los valores
5
+ * que cambian según dónde corre la aplicación. Son dos superficies distintas
6
+ * resueltas por el mismo motor, y sólo la primera la lee el router.
7
+ */
8
+ export { loadConfig, normalizeBasePath } from './load';
9
+ export { defineConfig } from './define';
10
+ export { assetPrefixFor, canonicalTrailingSlash, stripBasePath, withBasePath, } from './base-path';
11
+ export { applyParams, compileRules, matchRule, parseRulePattern } from './rules';
12
+ export type { CompiledRule, CompiledRules } from './rules';
13
+ export { createConfigMiddleware } from './middleware';
14
+ export { publicEnvDefines, publicEnvValues } from './env';
15
+ export { generateProjectConfigTypes, generatePlatformTypes, writeGeneratedTypes } from './codegen';
16
+ export { changedKeys, isConfigLayer, restartReason, watchConfig, HOT_KEYS, RESTART_REASONS } from './watch';
17
+ export { validateConfig, validateRules } from './validate';
18
+ export type { AssetsConfig, DevConfig, HeaderRule, ModeOverrides, PlatformConfig, RedirectRule, ResolvedConfig, RessConfig, RessServerConfig, RewriteRule, TrailingSlashMode, } from './types';
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ /**
3
+ * Configuración del framework.
4
+ *
5
+ * `ress.config` declara el comportamiento; `@ressjs/config` declara los valores
6
+ * que cambian según dónde corre la aplicación. Son dos superficies distintas
7
+ * resueltas por el mismo motor, y sólo la primera la lee el router.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.validateRules = exports.validateConfig = exports.RESTART_REASONS = exports.HOT_KEYS = exports.watchConfig = exports.restartReason = exports.isConfigLayer = exports.changedKeys = exports.writeGeneratedTypes = exports.generatePlatformTypes = exports.generateProjectConfigTypes = exports.publicEnvValues = exports.publicEnvDefines = exports.createConfigMiddleware = exports.parseRulePattern = exports.matchRule = exports.compileRules = exports.applyParams = exports.withBasePath = exports.stripBasePath = exports.canonicalTrailingSlash = exports.assetPrefixFor = exports.defineConfig = exports.normalizeBasePath = exports.loadConfig = void 0;
11
+ var load_1 = require("./load");
12
+ Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return load_1.loadConfig; } });
13
+ Object.defineProperty(exports, "normalizeBasePath", { enumerable: true, get: function () { return load_1.normalizeBasePath; } });
14
+ var define_1 = require("./define");
15
+ Object.defineProperty(exports, "defineConfig", { enumerable: true, get: function () { return define_1.defineConfig; } });
16
+ var base_path_1 = require("./base-path");
17
+ Object.defineProperty(exports, "assetPrefixFor", { enumerable: true, get: function () { return base_path_1.assetPrefixFor; } });
18
+ Object.defineProperty(exports, "canonicalTrailingSlash", { enumerable: true, get: function () { return base_path_1.canonicalTrailingSlash; } });
19
+ Object.defineProperty(exports, "stripBasePath", { enumerable: true, get: function () { return base_path_1.stripBasePath; } });
20
+ Object.defineProperty(exports, "withBasePath", { enumerable: true, get: function () { return base_path_1.withBasePath; } });
21
+ var rules_1 = require("./rules");
22
+ Object.defineProperty(exports, "applyParams", { enumerable: true, get: function () { return rules_1.applyParams; } });
23
+ Object.defineProperty(exports, "compileRules", { enumerable: true, get: function () { return rules_1.compileRules; } });
24
+ Object.defineProperty(exports, "matchRule", { enumerable: true, get: function () { return rules_1.matchRule; } });
25
+ Object.defineProperty(exports, "parseRulePattern", { enumerable: true, get: function () { return rules_1.parseRulePattern; } });
26
+ var middleware_1 = require("./middleware");
27
+ Object.defineProperty(exports, "createConfigMiddleware", { enumerable: true, get: function () { return middleware_1.createConfigMiddleware; } });
28
+ var env_1 = require("./env");
29
+ Object.defineProperty(exports, "publicEnvDefines", { enumerable: true, get: function () { return env_1.publicEnvDefines; } });
30
+ Object.defineProperty(exports, "publicEnvValues", { enumerable: true, get: function () { return env_1.publicEnvValues; } });
31
+ var codegen_1 = require("./codegen");
32
+ Object.defineProperty(exports, "generateProjectConfigTypes", { enumerable: true, get: function () { return codegen_1.generateProjectConfigTypes; } });
33
+ Object.defineProperty(exports, "generatePlatformTypes", { enumerable: true, get: function () { return codegen_1.generatePlatformTypes; } });
34
+ Object.defineProperty(exports, "writeGeneratedTypes", { enumerable: true, get: function () { return codegen_1.writeGeneratedTypes; } });
35
+ var watch_1 = require("./watch");
36
+ Object.defineProperty(exports, "changedKeys", { enumerable: true, get: function () { return watch_1.changedKeys; } });
37
+ Object.defineProperty(exports, "isConfigLayer", { enumerable: true, get: function () { return watch_1.isConfigLayer; } });
38
+ Object.defineProperty(exports, "restartReason", { enumerable: true, get: function () { return watch_1.restartReason; } });
39
+ Object.defineProperty(exports, "watchConfig", { enumerable: true, get: function () { return watch_1.watchConfig; } });
40
+ Object.defineProperty(exports, "HOT_KEYS", { enumerable: true, get: function () { return watch_1.HOT_KEYS; } });
41
+ Object.defineProperty(exports, "RESTART_REASONS", { enumerable: true, get: function () { return watch_1.RESTART_REASONS; } });
42
+ var validate_1 = require("./validate");
43
+ Object.defineProperty(exports, "validateConfig", { enumerable: true, get: function () { return validate_1.validateConfig; } });
44
+ Object.defineProperty(exports, "validateRules", { enumerable: true, get: function () { return validate_1.validateRules; } });
@@ -0,0 +1,26 @@
1
+ import type { ResolvedConfig } from './types';
2
+ /**
3
+ * Lee la configuración del proyecto y la deja lista para consultar.
4
+ *
5
+ * **Una sola superficie**: la carpeta `config/`, con un archivo por modo.
6
+ *
7
+ * ```
8
+ * config/default.js ← lo común, opcional
9
+ * config/development.js
10
+ * config/production.js
11
+ * config/test.js
12
+ * config/local.js ← esta máquina; no se sube
13
+ * ```
14
+ *
15
+ * Cada archivo exporta por defecto un objeto con **todo**: `basePath`,
16
+ * `redirects`, `publicEnv`, `dev.hmr`, `security`, y también los valores propios
17
+ * del proyecto —la URL de una API, una clave—. Se fusionan `default` → el modo
18
+ * activo → `local`, y la última capa que declara una clave gana.
19
+ *
20
+ * Antes esto estaban partido en dos archivos distintos, `ress.config` para el
21
+ * comportamiento y `config/` para los valores. Eran dos lugares donde buscar la
22
+ * misma respuesta —"¿de dónde sale este valor?"— y dos formas de declararla.
23
+ */
24
+ export declare function loadConfig(root?: string, mode?: string): Promise<ResolvedConfig>;
25
+ /** `'/app/'` y `'app'` describen lo mismo: se guardan como `'/app'`. */
26
+ export declare function normalizeBasePath(basePath: string): string;