@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
|
@@ -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,29 @@
|
|
|
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[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Genera `types/` para un proyecto cuya configuración ya se cargó con
|
|
26
|
+
* `loadConfig`. La usan el plugin al arrancar y `ress info`, para que un
|
|
27
|
+
* proyecto recién creado o un clon limpio tengan sus tipos sin levantar nada.
|
|
28
|
+
*/
|
|
29
|
+
export declare function writeProjectTypes(root: string, platform: PlatformConfig): Promise<string[]>;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generatePlatformTypes = generatePlatformTypes;
|
|
4
|
+
exports.generateProjectConfigTypes = generateProjectConfigTypes;
|
|
5
|
+
exports.writeGeneratedTypes = writeGeneratedTypes;
|
|
6
|
+
exports.writeProjectTypes = writeProjectTypes;
|
|
7
|
+
/**
|
|
8
|
+
* Tipos generados a partir de lo que el proyecto declara.
|
|
9
|
+
*
|
|
10
|
+
* Sin esto, declarar un token de plataforma propio en `ress.config.ts` funciona
|
|
11
|
+
* en tiempo de ejecución pero el editor no lo conoce: el desarrollador escribe
|
|
12
|
+
* `'kaios'` y no recibe ni sugerencia ni error si lo escribe mal. Los archivos se
|
|
13
|
+
* generan, no se versionan, y se rehacen cuando cambia la configuración que los
|
|
14
|
+
* origina.
|
|
15
|
+
*/
|
|
16
|
+
const BANNER = '// Generado por ress.js a partir de la configuración del proyecto.\n' +
|
|
17
|
+
'// No editar a mano ni versionar: se rehace en cada arranque.\n';
|
|
18
|
+
/**
|
|
19
|
+
* Amplía `PlatformValueMap` de `@ressjs/platform` con los tokens del proyecto.
|
|
20
|
+
*
|
|
21
|
+
* Se agrupa por eje porque la interfaz tiene una clave por eje, y declararla dos
|
|
22
|
+
* veces con tipos distintos es un error de compilación.
|
|
23
|
+
*/
|
|
24
|
+
function generatePlatformTypes(platform) {
|
|
25
|
+
const byAxis = new Map();
|
|
26
|
+
for (const value of platform.values ?? []) {
|
|
27
|
+
if (!value?.token || !value?.axis)
|
|
28
|
+
continue;
|
|
29
|
+
const tokens = byAxis.get(value.axis) ?? [];
|
|
30
|
+
if (!tokens.includes(value.token))
|
|
31
|
+
tokens.push(value.token);
|
|
32
|
+
byAxis.set(value.axis, tokens);
|
|
33
|
+
}
|
|
34
|
+
if (byAxis.size === 0) {
|
|
35
|
+
// Un archivo vacío igual se escribe: si el proyecto quitó sus tokens, dejar
|
|
36
|
+
// el anterior mantendría en el autocompletado valores que ya no existen.
|
|
37
|
+
return BANNER + 'export {}\n';
|
|
38
|
+
}
|
|
39
|
+
const fields = [...byAxis.entries()]
|
|
40
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
41
|
+
.map(([axis, tokens]) => ` ${axis}: ${tokens.map(quote).join(' | ')}`)
|
|
42
|
+
.join('\n');
|
|
43
|
+
return (BANNER +
|
|
44
|
+
"declare module '@ressjs/platform' {\n" +
|
|
45
|
+
' interface PlatformValueMap {\n' +
|
|
46
|
+
fields +
|
|
47
|
+
'\n }\n}\n\nexport {}\n');
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Amplía `ProjectConfig` de `@ressjs/config` con la forma de los valores resueltos.
|
|
51
|
+
*
|
|
52
|
+
* Se infiere de lo que la resolución produjo y no del archivo fuente: es lo que
|
|
53
|
+
* el proyecto va a leer realmente, capas incluidas.
|
|
54
|
+
*/
|
|
55
|
+
function generateProjectConfigTypes(values) {
|
|
56
|
+
const keys = Object.keys(values).sort();
|
|
57
|
+
if (keys.length === 0)
|
|
58
|
+
return BANNER + 'export {}\n';
|
|
59
|
+
const fields = keys.map((key) => ` ${propertyName(key)}: ${typeOf(values[key])}`).join('\n');
|
|
60
|
+
return (BANNER +
|
|
61
|
+
"declare module '@ressjs/config' {\n" +
|
|
62
|
+
' interface ProjectConfig {\n' +
|
|
63
|
+
fields +
|
|
64
|
+
'\n }\n}\n\nexport {}\n');
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* El tipo de un valor, a un nivel de profundidad razonable.
|
|
68
|
+
*
|
|
69
|
+
* No se intenta reconstruir la forma exacta de una estructura anidada: el
|
|
70
|
+
* objetivo es autocompletar nombres de clave, y un tipo aproximado que se escribe
|
|
71
|
+
* en un archivo generado es mejor que uno exacto que nadie puede leer.
|
|
72
|
+
*/
|
|
73
|
+
function typeOf(value) {
|
|
74
|
+
if (value === null || value === undefined)
|
|
75
|
+
return 'unknown';
|
|
76
|
+
if (Array.isArray(value)) {
|
|
77
|
+
const inner = value.length ? typeOf(value[0]) : 'unknown';
|
|
78
|
+
return `${inner}[]`;
|
|
79
|
+
}
|
|
80
|
+
if (typeof value === 'object') {
|
|
81
|
+
const entries = Object.entries(value);
|
|
82
|
+
if (!entries.length)
|
|
83
|
+
return 'Record<string, unknown>';
|
|
84
|
+
return ('{ ' + entries.map(([k, v]) => `${propertyName(k)}: ${typeOf(v)}`).join('; ') + ' }');
|
|
85
|
+
}
|
|
86
|
+
if (typeof value === 'function')
|
|
87
|
+
return '(...args: never[]) => unknown';
|
|
88
|
+
return typeof value;
|
|
89
|
+
}
|
|
90
|
+
/** Una clave que no es un identificador válido va entre comillas. */
|
|
91
|
+
function propertyName(key) {
|
|
92
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? key : quote(key);
|
|
93
|
+
}
|
|
94
|
+
function quote(value) {
|
|
95
|
+
return JSON.stringify(value);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Escribe los dos archivos si cambiaron.
|
|
99
|
+
*
|
|
100
|
+
* Compara antes de escribir porque el observador de desarrollo mira el sistema de
|
|
101
|
+
* archivos: reescribir el mismo contenido dispararía una recarga que a su vez
|
|
102
|
+
* volvería a generar, en un ciclo que no termina.
|
|
103
|
+
*/
|
|
104
|
+
async function writeGeneratedTypes(root, files) {
|
|
105
|
+
const { writeFile, mkdir, readFile } = await import('node:fs/promises');
|
|
106
|
+
const path = await import('node:path');
|
|
107
|
+
const dir = path.join(root, 'types');
|
|
108
|
+
const written = [];
|
|
109
|
+
for (const [name, content] of Object.entries(files)) {
|
|
110
|
+
const target = path.join(dir, name);
|
|
111
|
+
const previous = await readFile(target, 'utf-8').catch(() => undefined);
|
|
112
|
+
if (previous === content)
|
|
113
|
+
continue;
|
|
114
|
+
await mkdir(dir, { recursive: true });
|
|
115
|
+
await writeFile(target, content, 'utf-8');
|
|
116
|
+
written.push(target);
|
|
117
|
+
}
|
|
118
|
+
return written;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Genera `types/` para un proyecto cuya configuración ya se cargó con
|
|
122
|
+
* `loadConfig`. La usan el plugin al arrancar y `ress info`, para que un
|
|
123
|
+
* proyecto recién creado o un clon limpio tengan sus tipos sin levantar nada.
|
|
124
|
+
*/
|
|
125
|
+
async function writeProjectTypes(root, platform) {
|
|
126
|
+
const { resolved } = await import('@ressjs/config');
|
|
127
|
+
return writeGeneratedTypes(root, {
|
|
128
|
+
'ress-platform.d.ts': generatePlatformTypes(platform),
|
|
129
|
+
'ress-config.d.ts': generateProjectConfigTypes(resolved()),
|
|
130
|
+
});
|
|
131
|
+
}
|
|
@@ -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, resolveIsrConfig } 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, writeProjectTypes } from './codegen';
|
|
16
|
+
export { changedKeys, isConfigLayer, restartReason, watchConfig, HOT_KEYS, RESTART_REASONS } from './watch';
|
|
17
|
+
export { validateConfig, validateRules } from './validate';
|
|
18
|
+
export type { AssetsConfig, IsrConfig, ResolvedIsrConfig, HeaderRule, ModeOverrides, PlatformConfig, RedirectRule, ResolvedConfig, RessConfig, RessServerConfig, RewriteRule, TrailingSlashMode, } from './types';
|
|
@@ -0,0 +1,46 @@
|
|
|
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.writeProjectTypes = 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.resolveIsrConfig = 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
|
+
Object.defineProperty(exports, "resolveIsrConfig", { enumerable: true, get: function () { return load_1.resolveIsrConfig; } });
|
|
15
|
+
var define_1 = require("./define");
|
|
16
|
+
Object.defineProperty(exports, "defineConfig", { enumerable: true, get: function () { return define_1.defineConfig; } });
|
|
17
|
+
var base_path_1 = require("./base-path");
|
|
18
|
+
Object.defineProperty(exports, "assetPrefixFor", { enumerable: true, get: function () { return base_path_1.assetPrefixFor; } });
|
|
19
|
+
Object.defineProperty(exports, "canonicalTrailingSlash", { enumerable: true, get: function () { return base_path_1.canonicalTrailingSlash; } });
|
|
20
|
+
Object.defineProperty(exports, "stripBasePath", { enumerable: true, get: function () { return base_path_1.stripBasePath; } });
|
|
21
|
+
Object.defineProperty(exports, "withBasePath", { enumerable: true, get: function () { return base_path_1.withBasePath; } });
|
|
22
|
+
var rules_1 = require("./rules");
|
|
23
|
+
Object.defineProperty(exports, "applyParams", { enumerable: true, get: function () { return rules_1.applyParams; } });
|
|
24
|
+
Object.defineProperty(exports, "compileRules", { enumerable: true, get: function () { return rules_1.compileRules; } });
|
|
25
|
+
Object.defineProperty(exports, "matchRule", { enumerable: true, get: function () { return rules_1.matchRule; } });
|
|
26
|
+
Object.defineProperty(exports, "parseRulePattern", { enumerable: true, get: function () { return rules_1.parseRulePattern; } });
|
|
27
|
+
var middleware_1 = require("./middleware");
|
|
28
|
+
Object.defineProperty(exports, "createConfigMiddleware", { enumerable: true, get: function () { return middleware_1.createConfigMiddleware; } });
|
|
29
|
+
var env_1 = require("./env");
|
|
30
|
+
Object.defineProperty(exports, "publicEnvDefines", { enumerable: true, get: function () { return env_1.publicEnvDefines; } });
|
|
31
|
+
Object.defineProperty(exports, "publicEnvValues", { enumerable: true, get: function () { return env_1.publicEnvValues; } });
|
|
32
|
+
var codegen_1 = require("./codegen");
|
|
33
|
+
Object.defineProperty(exports, "generateProjectConfigTypes", { enumerable: true, get: function () { return codegen_1.generateProjectConfigTypes; } });
|
|
34
|
+
Object.defineProperty(exports, "generatePlatformTypes", { enumerable: true, get: function () { return codegen_1.generatePlatformTypes; } });
|
|
35
|
+
Object.defineProperty(exports, "writeGeneratedTypes", { enumerable: true, get: function () { return codegen_1.writeGeneratedTypes; } });
|
|
36
|
+
Object.defineProperty(exports, "writeProjectTypes", { enumerable: true, get: function () { return codegen_1.writeProjectTypes; } });
|
|
37
|
+
var watch_1 = require("./watch");
|
|
38
|
+
Object.defineProperty(exports, "changedKeys", { enumerable: true, get: function () { return watch_1.changedKeys; } });
|
|
39
|
+
Object.defineProperty(exports, "isConfigLayer", { enumerable: true, get: function () { return watch_1.isConfigLayer; } });
|
|
40
|
+
Object.defineProperty(exports, "restartReason", { enumerable: true, get: function () { return watch_1.restartReason; } });
|
|
41
|
+
Object.defineProperty(exports, "watchConfig", { enumerable: true, get: function () { return watch_1.watchConfig; } });
|
|
42
|
+
Object.defineProperty(exports, "HOT_KEYS", { enumerable: true, get: function () { return watch_1.HOT_KEYS; } });
|
|
43
|
+
Object.defineProperty(exports, "RESTART_REASONS", { enumerable: true, get: function () { return watch_1.RESTART_REASONS; } });
|
|
44
|
+
var validate_1 = require("./validate");
|
|
45
|
+
Object.defineProperty(exports, "validateConfig", { enumerable: true, get: function () { return validate_1.validateConfig; } });
|
|
46
|
+
Object.defineProperty(exports, "validateRules", { enumerable: true, get: function () { return validate_1.validateRules; } });
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { IsrConfig, ResolvedConfig, ResolvedIsrConfig } 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`, `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
|
+
/** Los valores por defecto de la caché incremental, en un solo lugar. */
|
|
26
|
+
export declare function resolveIsrConfig(declared?: IsrConfig): ResolvedIsrConfig;
|
|
27
|
+
/** `'/app/'` y `'app'` describen lo mismo: se guardan como `'/app'`. */
|
|
28
|
+
export declare function normalizeBasePath(basePath: string): string;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadConfig = loadConfig;
|
|
4
|
+
exports.resolveIsrConfig = resolveIsrConfig;
|
|
5
|
+
exports.normalizeBasePath = normalizeBasePath;
|
|
6
|
+
const config_1 = require("@ressjs/config");
|
|
7
|
+
const validate_1 = require("./validate");
|
|
8
|
+
/**
|
|
9
|
+
* Lee la configuración del proyecto y la deja lista para consultar.
|
|
10
|
+
*
|
|
11
|
+
* **Una sola superficie**: la carpeta `config/`, con un archivo por modo.
|
|
12
|
+
*
|
|
13
|
+
* ```
|
|
14
|
+
* config/default.js ← lo común, opcional
|
|
15
|
+
* config/development.js
|
|
16
|
+
* config/production.js
|
|
17
|
+
* config/test.js
|
|
18
|
+
* config/local.js ← esta máquina; no se sube
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Cada archivo exporta por defecto un objeto con **todo**: `basePath`,
|
|
22
|
+
* `redirects`, `publicEnv`, `security`, y también los valores propios
|
|
23
|
+
* del proyecto —la URL de una API, una clave—. Se fusionan `default` → el modo
|
|
24
|
+
* activo → `local`, y la última capa que declara una clave gana.
|
|
25
|
+
*
|
|
26
|
+
* Antes esto estaban partido en dos archivos distintos, `ress.config` para el
|
|
27
|
+
* comportamiento y `config/` para los valores. Eran dos lugares donde buscar la
|
|
28
|
+
* misma respuesta —"¿de dónde sale este valor?"— y dos formas de declararla.
|
|
29
|
+
*/
|
|
30
|
+
async function loadConfig(root = process.cwd(), mode = process.env.NODE_ENV === 'production' ? 'production' : 'development') {
|
|
31
|
+
// La misma resolución que lee el código de la aplicación con
|
|
32
|
+
// `import { config } from '@ressjs/config'`: un solo objeto, resuelto una vez.
|
|
33
|
+
const declared = (await (0, config_1.resolveConfig)(root, mode));
|
|
34
|
+
(0, validate_1.validateConfig)(declared);
|
|
35
|
+
return resolve(declared);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Completa lo que el proyecto no declaró.
|
|
39
|
+
*
|
|
40
|
+
* Se hace una vez al arrancar y no por consulta: así el resto del framework lee
|
|
41
|
+
* `config.security` sin `?.` ni `??` en cada uso, y los valores por defecto están
|
|
42
|
+
* escritos en un solo lugar.
|
|
43
|
+
*/
|
|
44
|
+
async function resolve(declared) {
|
|
45
|
+
return {
|
|
46
|
+
// Sin barra final: se agrega al componer, y tenerla en el valor guardado
|
|
47
|
+
// obliga a recordar si ya está en cada concatenación.
|
|
48
|
+
basePath: normalizeBasePath(declared.basePath ?? ''),
|
|
49
|
+
trailingSlash: declared.trailingSlash ?? 'ignore',
|
|
50
|
+
// Las tres son funciones para que el proyecto pueda leer un archivo o
|
|
51
|
+
// consultar algo al arrancar. Se invocan una vez, acá.
|
|
52
|
+
redirects: (await declared.redirects?.()) ?? [],
|
|
53
|
+
rewrites: (await declared.rewrites?.()) ?? [],
|
|
54
|
+
headers: (await declared.headers?.()) ?? [],
|
|
55
|
+
publicEnv: declared.publicEnv ?? [],
|
|
56
|
+
extensions: declared.extensions ?? {},
|
|
57
|
+
platform: declared.platform ?? {},
|
|
58
|
+
security: declared.security ?? {},
|
|
59
|
+
assets: declared.assets ?? {},
|
|
60
|
+
isr: resolveIsrConfig(declared.isr),
|
|
61
|
+
server: declared.server ?? {},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/** Los valores por defecto de la caché incremental, en un solo lugar. */
|
|
65
|
+
function resolveIsrConfig(declared = {}) {
|
|
66
|
+
return {
|
|
67
|
+
maxEntries: declared.maxEntries ?? 500,
|
|
68
|
+
maxBytes: declared.maxBytes ?? 50 * 1024 * 1024,
|
|
69
|
+
generationTimeoutMs: declared.generationTimeoutMs ?? 30_000,
|
|
70
|
+
dev: declared.dev ?? false,
|
|
71
|
+
sharedCache: declared.sharedCache ?? 'auto',
|
|
72
|
+
...(declared.previewSecret !== undefined ? { previewSecret: declared.previewSecret } : {}),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/** `'/app/'` y `'app'` describen lo mismo: se guardan como `'/app'`. */
|
|
76
|
+
function normalizeBasePath(basePath) {
|
|
77
|
+
const trimmed = basePath.trim();
|
|
78
|
+
if (!trimmed || trimmed === '/')
|
|
79
|
+
return '';
|
|
80
|
+
const withLeading = trimmed.startsWith('/') ? trimmed : '/' + trimmed;
|
|
81
|
+
return withLeading.replace(/\/+$/, '');
|
|
82
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type CompiledRules } from './rules';
|
|
2
|
+
import type { ResolvedConfig } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Lo que la configuración aporta al pipeline de petición.
|
|
5
|
+
*
|
|
6
|
+
* El orden es fijo y está en el plan:
|
|
7
|
+
*
|
|
8
|
+
* 1. barra final — para que todo lo que sigue vea una sola forma de cada URL
|
|
9
|
+
* 2. prefijo de ruta — para que el manifest trabaje siempre sin prefijo
|
|
10
|
+
* 3. redirecciones — si alguna coincide, se responde y se termina
|
|
11
|
+
* 4. reescrituras — cambian la ruta a resolver, no la que el navegador muestra
|
|
12
|
+
* 5. cabeceras — al escribir la respuesta, sin pisar las del framework
|
|
13
|
+
*/
|
|
14
|
+
export interface ConfigMiddlewareOptions {
|
|
15
|
+
/** Reglas ya compiladas. Se compilan una vez al arrancar, no por petición. */
|
|
16
|
+
compiled?: CompiledRules;
|
|
17
|
+
}
|
|
18
|
+
export declare function createConfigMiddleware(config: ResolvedConfig, options?: ConfigMiddlewareOptions): (req: any, res: any, next: (err?: unknown) => void) => void;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createConfigMiddleware = createConfigMiddleware;
|
|
4
|
+
const base_path_1 = require("./base-path");
|
|
5
|
+
const rules_1 = require("./rules");
|
|
6
|
+
function createConfigMiddleware(config, options = {}) {
|
|
7
|
+
const rules = options.compiled ?? (0, rules_1.compileRules)(config);
|
|
8
|
+
const { basePath, trailingSlash } = config;
|
|
9
|
+
return function configMiddleware(req, res, next) {
|
|
10
|
+
const url = req.url ?? '/';
|
|
11
|
+
const cut = url.search(/[?#]/);
|
|
12
|
+
const pathname = cut === -1 ? url : url.slice(0, cut);
|
|
13
|
+
const suffix = cut === -1 ? '' : url.slice(cut);
|
|
14
|
+
const canonical = (0, base_path_1.canonicalTrailingSlash)(pathname, trailingSlash);
|
|
15
|
+
if (canonical !== undefined) {
|
|
16
|
+
// 308: el navegador y los intermediarios tienen que conservar el método.
|
|
17
|
+
// Un 301 convierte un POST en GET al repetir.
|
|
18
|
+
return redirect(res, 308, canonical + suffix);
|
|
19
|
+
}
|
|
20
|
+
const inner = (0, base_path_1.stripBasePath)(pathname, basePath);
|
|
21
|
+
if (inner === undefined) {
|
|
22
|
+
// Fuera del prefijo no hay aplicación: se marca para que ni los artefactos
|
|
23
|
+
// ni las páginas la atiendan. Sin la marca, declarar un prefijo dejaba el
|
|
24
|
+
// sitio servido por dos direcciones distintas a la vez, que es justo lo
|
|
25
|
+
// que un prefijo existe para evitar.
|
|
26
|
+
req.ressOutsideBasePath = true;
|
|
27
|
+
return next();
|
|
28
|
+
}
|
|
29
|
+
// La URL original queda a mano: los mensajes de error y los enlaces
|
|
30
|
+
// canónicos hablan de lo que el navegador pidió, no de lo que quedó
|
|
31
|
+
// después de quitar el prefijo.
|
|
32
|
+
req.ressOriginalUrl ??= url;
|
|
33
|
+
req.ressBasePath = basePath;
|
|
34
|
+
req.url = inner + suffix;
|
|
35
|
+
const redirection = (0, rules_1.matchRule)(rules.redirects, inner);
|
|
36
|
+
if (redirection) {
|
|
37
|
+
const target = (0, rules_1.applyParams)(redirection.compiled.rule.destination, redirection.params);
|
|
38
|
+
return redirect(res, redirection.compiled.rule.permanent ? 308 : 307, absolute(target) ? target : (0, base_path_1.withBasePath)(target, basePath) + suffix);
|
|
39
|
+
}
|
|
40
|
+
const rewrite = (0, rules_1.matchRule)(rules.rewrites, inner);
|
|
41
|
+
if (rewrite) {
|
|
42
|
+
// Sólo cambia lo que el servidor resuelve: `req.url` es interno, y la
|
|
43
|
+
// barra de direcciones del navegador no se entera.
|
|
44
|
+
req.url = (0, rules_1.applyParams)(rewrite.compiled.rule.destination, rewrite.params) + suffix;
|
|
45
|
+
}
|
|
46
|
+
applyHeaderRules(rules, inner, res);
|
|
47
|
+
next();
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function absolute(target) {
|
|
51
|
+
return /^[a-z][a-z0-9+.-]*:\/\//i.test(target) || target.startsWith('//');
|
|
52
|
+
}
|
|
53
|
+
function redirect(res, status, location) {
|
|
54
|
+
res.statusCode = status;
|
|
55
|
+
res.setHeader('Location', location);
|
|
56
|
+
res.end();
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Las cabeceras declaradas se escriben al enviar, no ahora.
|
|
60
|
+
*
|
|
61
|
+
* Ponerlas ya las dejaría expuestas a que el framework las pisara después; y
|
|
62
|
+
* ponerlas después de las suyas es justamente la regla: complementan lo que el
|
|
63
|
+
* framework decidió, no lo corrigen. Por eso sólo se escribe lo que nadie fijó.
|
|
64
|
+
*/
|
|
65
|
+
function applyHeaderRules(rules, pathname, res) {
|
|
66
|
+
const match = (0, rules_1.matchRule)(rules.headers, pathname);
|
|
67
|
+
if (!match)
|
|
68
|
+
return;
|
|
69
|
+
const write = res.writeHead?.bind(res);
|
|
70
|
+
if (!write)
|
|
71
|
+
return;
|
|
72
|
+
res.writeHead = (...args) => {
|
|
73
|
+
for (const { key, value } of match.compiled.rule.headers) {
|
|
74
|
+
if (res.getHeader?.(key) === undefined)
|
|
75
|
+
res.setHeader(key, value);
|
|
76
|
+
}
|
|
77
|
+
return write(...args);
|
|
78
|
+
};
|
|
79
|
+
}
|