@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,44 @@
|
|
|
1
|
+
import type { CollectedHeadTag, HeadAttributes } from '@ressjs/assets';
|
|
2
|
+
import type { PageRenderingConfig } from '../isr/types';
|
|
3
|
+
export type { CollectedHeadTag, HeadAttributes, HeadProps, HeadTagName } from '@ressjs/assets';
|
|
4
|
+
export interface PageHeadConfig {
|
|
5
|
+
title?: string;
|
|
6
|
+
robots?: RobotsConfig;
|
|
7
|
+
meta?: HeadAttributes[];
|
|
8
|
+
link?: HeadAttributes[];
|
|
9
|
+
script?: Array<HeadAttributes & {
|
|
10
|
+
content?: string;
|
|
11
|
+
}>;
|
|
12
|
+
style?: Array<HeadAttributes & {
|
|
13
|
+
content: string;
|
|
14
|
+
}>;
|
|
15
|
+
base?: HeadAttributes;
|
|
16
|
+
noscript?: Array<{
|
|
17
|
+
content: string;
|
|
18
|
+
}>;
|
|
19
|
+
}
|
|
20
|
+
export interface PageConfigVariant {
|
|
21
|
+
head?: PageHeadConfig;
|
|
22
|
+
htmlAttributes?: HeadAttributes;
|
|
23
|
+
bodyAttributes?: HeadAttributes;
|
|
24
|
+
}
|
|
25
|
+
export interface PageConfig extends PageConfigVariant, PageRenderingConfig {
|
|
26
|
+
/** Overrides selected per request with the same platform vocabulary as page assets. */
|
|
27
|
+
variants?: Record<string, PageConfigVariant>;
|
|
28
|
+
}
|
|
29
|
+
export type { PageRenderingConfig, RenderingMode } from '../isr/types';
|
|
30
|
+
export type RobotsConfig = string | {
|
|
31
|
+
index?: boolean;
|
|
32
|
+
follow?: boolean;
|
|
33
|
+
noarchive?: boolean;
|
|
34
|
+
nosnippet?: boolean;
|
|
35
|
+
noimageindex?: boolean;
|
|
36
|
+
notranslate?: boolean;
|
|
37
|
+
};
|
|
38
|
+
export interface ResolvedPageHead {
|
|
39
|
+
tags: CollectedHeadTag[];
|
|
40
|
+
htmlAttributes: HeadAttributes;
|
|
41
|
+
bodyAttributes: HeadAttributes;
|
|
42
|
+
/** Effective robots directive after pageConfig and <Head> have been merged. */
|
|
43
|
+
robots?: string;
|
|
44
|
+
}
|
|
@@ -1,14 +1,34 @@
|
|
|
1
|
-
import { PlatformInfo } from '../platform';
|
|
1
|
+
import { type PlatformInfo } from '../platform';
|
|
2
|
+
import { type SecurityContext } from '../security';
|
|
3
|
+
import type { AssetIndex, VariantCatalog } from '../variants/types';
|
|
4
|
+
import type { ResolvedPageHead } from '../head/types';
|
|
5
|
+
export { resolvePageAssets } from '@ressjs/assets';
|
|
6
|
+
/**
|
|
7
|
+
* Qué archivos servirle a esta plataforma: elige la variante y busca sus artefactos.
|
|
8
|
+
*
|
|
9
|
+
* Son dos consultas en memoria. El catálogo ya está armado y los artefactos ya
|
|
10
|
+
* están indexados desde que arrancó el servidor, así que servir una página no
|
|
11
|
+
* toca el sistema de archivos ni escribe nada.
|
|
12
|
+
*
|
|
13
|
+
* Si la variante elegida no tiene artefactos construidos, responde los de la
|
|
14
|
+
* base antes que no responder nada.
|
|
15
|
+
*/
|
|
2
16
|
export interface HTMLGenerationContext {
|
|
3
17
|
template: string;
|
|
4
18
|
rendered: any;
|
|
5
19
|
page: any;
|
|
6
|
-
manifest: any;
|
|
7
20
|
platform: string;
|
|
8
21
|
isProduction: boolean;
|
|
9
22
|
platformInfo: PlatformInfo | null;
|
|
10
|
-
|
|
23
|
+
pageHead?: ResolvedPageHead;
|
|
24
|
+
catalog?: VariantCatalog;
|
|
25
|
+
assets?: AssetIndex;
|
|
26
|
+
/** Request-scoped links prepared before rendering (and overridable by middleware). */
|
|
27
|
+
styles?: {
|
|
28
|
+
js: string;
|
|
29
|
+
css: string[];
|
|
30
|
+
};
|
|
31
|
+
/** `false`: HTML y CSS, sin script de entrada ni estado para el navegador. */
|
|
32
|
+
hydrate?: boolean;
|
|
11
33
|
}
|
|
12
|
-
export declare function
|
|
13
|
-
export declare function generateClientCSS(pageFile: string, platformInfo: PlatformInfo | null, manifest: any, isProduction: boolean): string;
|
|
14
|
-
export declare function generateCompleteHTML(context: HTMLGenerationContext): Promise<string>;
|
|
34
|
+
export declare function generateCompleteHTML(context: HTMLGenerationContext, security?: SecurityContext): Promise<string>;
|
|
@@ -1,146 +1,104 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
7
|
-
exports.generateClientCSS = generateClientCSS;
|
|
3
|
+
exports.resolvePageAssets = void 0;
|
|
8
4
|
exports.generateCompleteHTML = generateCompleteHTML;
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
`${rel}__entry-client.${platformInfo.device}.${platformInfo.os}.tsx`,
|
|
23
|
-
// 2. DeviceType: device.tsx
|
|
24
|
-
`${rel}__entry-client.${platformInfo.device}.tsx`,
|
|
25
|
-
// 3. Mobile Fallback: mobile.tsx (only for phone/tablet)
|
|
26
|
-
...(platformInfo.device === 'phone' || platformInfo.device === 'tablet'
|
|
27
|
-
? [`${rel}__entry-client.mobile.tsx`]
|
|
28
|
-
: []),
|
|
29
|
-
// 4. OS General: os.tsx
|
|
30
|
-
`${rel}__entry-client.${platformInfo.os}.tsx`
|
|
31
|
-
];
|
|
32
|
-
// Find first existing entry following priority order
|
|
33
|
-
for (const candidate of priorities) {
|
|
34
|
-
if (isProduction) {
|
|
35
|
-
// In production, check manifest
|
|
36
|
-
const manifestKey = `dist/.entries/${candidate}`;
|
|
37
|
-
if (manifest[manifestKey]) {
|
|
38
|
-
entryKey = candidate;
|
|
39
|
-
break;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
// In development, check if physical file exists
|
|
44
|
-
try {
|
|
45
|
-
await promises_1.default.access(`dist/.entries/${candidate}`);
|
|
46
|
-
entryKey = candidate;
|
|
47
|
-
break;
|
|
48
|
-
}
|
|
49
|
-
catch {
|
|
50
|
-
// File doesn't exist, continue to next priority
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
if (!isProduction) {
|
|
56
|
-
return `/dist/.entries/${entryKey}`;
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
const chunk = manifest[`dist/.entries/${entryKey}`];
|
|
60
|
-
return chunk ? `/${chunk.file}` : null;
|
|
61
|
-
}
|
|
5
|
+
const platform_1 = require("../platform");
|
|
6
|
+
const security_1 = require("../security");
|
|
7
|
+
const assets_1 = require("@ressjs/assets");
|
|
8
|
+
var assets_2 = require("@ressjs/assets");
|
|
9
|
+
Object.defineProperty(exports, "resolvePageAssets", { enumerable: true, get: function () { return assets_2.resolvePageAssets; } });
|
|
10
|
+
/**
|
|
11
|
+
* Plataforma que se asume cuando la detección está desactivada.
|
|
12
|
+
*
|
|
13
|
+
* Es la misma que produce el pipeline cuando nadie declaró nada, de modo que
|
|
14
|
+
* apagar la detección y recibir una petición anónima den el mismo resultado.
|
|
15
|
+
*/
|
|
16
|
+
function fallbackPlatform() {
|
|
17
|
+
return platform_1.DEFAULT_PLATFORM;
|
|
62
18
|
}
|
|
63
|
-
function
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
19
|
+
async function generateCompleteHTML(context, security) {
|
|
20
|
+
const { template, rendered, page, platformInfo, pageHead, catalog, assets, hydrate = true } = context;
|
|
21
|
+
const ctx = security ?? {
|
|
22
|
+
isProduction: context.isProduction,
|
|
23
|
+
options: (0, security_1.resolveSecurityOptions)(),
|
|
24
|
+
route: page?.route ?? '',
|
|
25
|
+
};
|
|
26
|
+
const escapeCtx = { where: '', isProduction: ctx.isProduction, route: ctx.route };
|
|
27
|
+
const nonce = ctx.nonce;
|
|
28
|
+
const platform = platformInfo ?? fallbackPlatform();
|
|
29
|
+
const resolved = context.styles ?? (catalog && assets && page?.pageId
|
|
30
|
+
? (0, assets_1.resolvePageAssets)(page.pageId, platform, catalog, assets)
|
|
31
|
+
: { js: '', css: [] });
|
|
32
|
+
const scriptTag = hydrate && resolved.js
|
|
33
|
+
? `<script type="module"${nonceAttr(nonce)} src="${(0, security_1.escapeAttrValue)(resolved.js)}"></script>`
|
|
34
|
+
: '';
|
|
35
|
+
const cssLinks = resolved.css
|
|
36
|
+
.map((href) => `<link rel="stylesheet" href="${(0, security_1.escapeAttrValue)(href)}">`)
|
|
37
|
+
.join('');
|
|
38
|
+
const pageTags = pageHead?.tags.length
|
|
39
|
+
? (0, security_1.renderHeadTags)(pageHead.tags.map((tag) => ({ tag: tag.type, attrs: tag.attrs, children: tag.content })), escapeCtx, {
|
|
40
|
+
// Page head declarations are application source, like the hydration
|
|
41
|
+
// script itself. CSP still controls whether inline code executes.
|
|
42
|
+
allowScriptTags: ctx.options.head.allowScriptTags,
|
|
43
|
+
extraAllowlist: ['noscript', ...ctx.options.head.extraTagAllowlist],
|
|
44
|
+
nonce,
|
|
45
|
+
})
|
|
46
|
+
: '';
|
|
47
|
+
const headContent = [cssLinks, pageTags].filter(Boolean).join('\n');
|
|
48
|
+
// La plataforma sólo se escribe si la página varía por algo. Si no varía, el
|
|
49
|
+
// documento tiene que ser idéntico para todos —es lo que lo hace cacheable— y
|
|
50
|
+
// el cliente la detecta por su cuenta.
|
|
51
|
+
const varies = (ctx.varyBy?.length ?? 0) > 0;
|
|
52
|
+
const platformTravels = ctx.options.serializePlatform === 'always' ||
|
|
53
|
+
(ctx.options.serializePlatform === 'auto' && varies);
|
|
54
|
+
// El estado que viaja. `__RESS_PAGE__` sólo en desarrollo: es una ruta del
|
|
55
|
+
// sistema de archivos del proyecto y no le aporta nada al cliente.
|
|
56
|
+
//
|
|
57
|
+
// Una página que no hidrata no lleva estado: nadie lo va a leer, y un
|
|
58
|
+
// documento sin JavaScript de página es justamente lo que pidió.
|
|
59
|
+
const blocks = !hydrate ? [] : [
|
|
60
|
+
...(platformTravels ? [{ varName: '__RESS_PLATFORM__', value: platform }] : []),
|
|
61
|
+
{ varName: '__RESS_PROPS__', value: rendered.props || {} },
|
|
62
|
+
{ varName: '__RESS_ROUTE__', value: page?.route ?? '' },
|
|
63
|
+
...(ctx.isProduction ? [] : [{ varName: '__RESS_PAGE__', value: page?.file ?? '' }]),
|
|
64
|
+
];
|
|
65
|
+
const stateScript = blocks.length ? (0, security_1.renderStateScript)(blocks, nonce) : '';
|
|
66
|
+
let html = template;
|
|
67
|
+
if (pageHead?.htmlAttributes)
|
|
68
|
+
html = applyRootAttributes(html, 'html', pageHead.htmlAttributes, escapeCtx);
|
|
69
|
+
if (pageHead?.bodyAttributes)
|
|
70
|
+
html = applyRootAttributes(html, 'body', pageHead.bodyAttributes, escapeCtx);
|
|
71
|
+
if (pageHead?.tags.some((tag) => tag.type === 'title')) {
|
|
72
|
+
html = html.replace(/<title(?:\s[^>]*)?>[\s\S]*?<\/title>/i, '');
|
|
99
73
|
}
|
|
100
|
-
|
|
74
|
+
// Los tres valores insertados acá son contenido dinámico: si se pasaran
|
|
75
|
+
// como string de reemplazo, `$$`, `$&`, `` $` `` y `$'` se interpretarían
|
|
76
|
+
// como patrones especiales de `String.replace` y corromperían el documento.
|
|
77
|
+
// La forma función evita esa interpretación.
|
|
78
|
+
return html
|
|
79
|
+
.replace('<!--app-head-->', () => headContent)
|
|
80
|
+
.replace('<!--app-html-->', () => rendered.html)
|
|
81
|
+
.replace('</body>', () => `${stateScript}${scriptTag}</body>`);
|
|
101
82
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
if (serverSideResult.html.head?.extraTags) {
|
|
122
|
-
headContent += '\n' + serverSideResult.html.head.extraTags.join('\n');
|
|
83
|
+
const nonceAttr = (nonce) => (nonce ? ` nonce="${(0, security_1.escapeAttrValue)(nonce)}"` : '');
|
|
84
|
+
/**
|
|
85
|
+
* Acepta la forma estructurada y descarta el string de HTML crudo.
|
|
86
|
+
*
|
|
87
|
+
* Un array de strings no se puede filtrar sin analizar HTML, y analizarlo para
|
|
88
|
+
* decidir si es seguro es exactamente el problema que la lista de etiquetas
|
|
89
|
+
* admitidas evita. F-004 ya produce la forma estructurada.
|
|
90
|
+
*/
|
|
91
|
+
function applyRootAttributes(html, element, attrs, ctx) {
|
|
92
|
+
return html.replace(new RegExp('<' + element + '([^>]*)>', 'i'), (_opening, existing) => {
|
|
93
|
+
let merged = existing;
|
|
94
|
+
for (const [name, value] of Object.entries(attrs)) {
|
|
95
|
+
const rendered = (0, security_1.renderAttrs)({ [name]: value }, { ...ctx, where: '<' + element + '>' });
|
|
96
|
+
if (!rendered)
|
|
97
|
+
continue;
|
|
98
|
+
const escapedName = name.replace(/[.*+?^$()|[\]\\{}]/g, '\\$&');
|
|
99
|
+
const present = new RegExp('\\s' + escapedName + '(?:\\s*=\\s*(?:"[^"]*"|\'[^\']*\'|[^\\s>]+))?', 'i');
|
|
100
|
+
merged = present.test(merged) ? merged.replace(present, () => ' ' + rendered) : merged + ' ' + rendered;
|
|
123
101
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
let html = template;
|
|
129
|
-
if (htmlAttributes)
|
|
130
|
-
html = html.replace('<html', `<html ${htmlAttributes}`);
|
|
131
|
-
if (bodyAttributes)
|
|
132
|
-
html = html.replace('<body', `<body ${bodyAttributes}`);
|
|
133
|
-
if (pageTitle)
|
|
134
|
-
html = html.replace(/<title>.*?<\/title>/i, pageTitle);
|
|
135
|
-
html = html
|
|
136
|
-
.replace('<!--app-head-->', headContent)
|
|
137
|
-
.replace('<!--app-html-->', rendered.html)
|
|
138
|
-
.replace('</body>', `<script>
|
|
139
|
-
window.__INITIAL_PROPS__=${JSON.stringify(rendered.props || {})};
|
|
140
|
-
window.__PAGE_ROUTE__=${JSON.stringify(page.route)};
|
|
141
|
-
window.__PAGE_FILE__=${JSON.stringify(page.file)};
|
|
142
|
-
</script>
|
|
143
|
-
${scriptTag}
|
|
144
|
-
</body>`);
|
|
145
|
-
return html;
|
|
102
|
+
return '<' + element + merged + '>';
|
|
103
|
+
});
|
|
146
104
|
}
|
|
@@ -1,65 +1,76 @@
|
|
|
1
1
|
import { Request, RequestHandler, Response } from 'express';
|
|
2
|
+
import type { ModuleLoader } from '../runtime/module-loader';
|
|
3
|
+
import type { MiddlewareEntry } from '../routes/types';
|
|
4
|
+
import type { PageConfig } from '../head/types';
|
|
5
|
+
export type { PageConfig, PageConfigVariant, PageHeadConfig, RobotsConfig } from '../head/types';
|
|
2
6
|
export interface MiddlewareInfo {
|
|
3
7
|
route: string;
|
|
4
8
|
file: string;
|
|
5
9
|
abs: string;
|
|
6
10
|
type: 'page-specific' | 'folder-global';
|
|
7
11
|
depth: number;
|
|
12
|
+
/** Chunk de servidor registrado por el build. Sólo en producción. */
|
|
13
|
+
buildChunk?: string;
|
|
8
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Si un middleware de carpeta con alcance `scope` aplica a `route`.
|
|
17
|
+
*
|
|
18
|
+
* Se compara por segmentos: `admin/middlewares.ts` protege `/admin` y
|
|
19
|
+
* `/admin/x`, pero no `/administrator`, que sólo comparte el prefijo de texto.
|
|
20
|
+
* La raíz aplica a todo.
|
|
21
|
+
*/
|
|
22
|
+
export declare function middlewareAppliesTo(scope: string, route: string): boolean;
|
|
23
|
+
/** Lo que el build escribe en el manifest por cada middleware. */
|
|
24
|
+
export declare function toMiddlewareEntry(info: MiddlewareInfo): MiddlewareEntry;
|
|
25
|
+
/** Los middlewares tal como los registró el build, listos para cargar. */
|
|
26
|
+
export declare function middlewaresFromManifest(entries: readonly MiddlewareEntry[]): MiddlewareInfo[];
|
|
9
27
|
export interface ServerSideResult {
|
|
10
28
|
props?: Record<string, any>;
|
|
11
|
-
|
|
12
|
-
html?: {
|
|
13
|
-
head?: {
|
|
14
|
-
title?: string;
|
|
15
|
-
attributes?: Record<string, string>;
|
|
16
|
-
extraTags?: string[];
|
|
17
|
-
};
|
|
18
|
-
body?: {
|
|
19
|
-
attributes?: Record<string, string>;
|
|
20
|
-
};
|
|
21
|
-
};
|
|
29
|
+
pageConfig?: PageConfig;
|
|
22
30
|
}
|
|
23
31
|
export interface PageModule {
|
|
24
32
|
default?: React.ComponentType<any>;
|
|
33
|
+
/** Configuración estática: el router la lee al armar la ruta, antes de cualquier petición. */
|
|
34
|
+
pageConfig?: PageConfig;
|
|
25
35
|
getServerSideProps?: (req: Request, res: Response) => Promise<ServerSideResult> | ServerSideResult;
|
|
26
36
|
errorMiddleware?: (err: any, req: Request, res: Response, next: any) => void;
|
|
27
37
|
}
|
|
28
38
|
/**
|
|
29
39
|
* Busca archivos de middlewares tanto específicos por página como globales por carpeta
|
|
30
40
|
*/
|
|
31
|
-
export declare function getMiddlewares(
|
|
41
|
+
export declare function getMiddlewares(options?: {
|
|
42
|
+
cwd?: string;
|
|
43
|
+
}): MiddlewareInfo[];
|
|
32
44
|
/**
|
|
33
45
|
* Carga middlewares para una página específica y los convierte en middlewares de Express
|
|
34
46
|
*/
|
|
35
|
-
export declare function loadPageMiddlewares(pageRoute: string,
|
|
47
|
+
export declare function loadPageMiddlewares(pageRoute: string, loader?: ModuleLoader, middlewares?: readonly MiddlewareInfo[]): Promise<RequestHandler[]>;
|
|
36
48
|
/**
|
|
37
49
|
* Carga el módulo completo de una página
|
|
38
50
|
*/
|
|
39
|
-
export declare function loadPageModule(pageFile: string,
|
|
51
|
+
export declare function loadPageModule(pageFile: string, loader?: ModuleLoader): Promise<PageModule | null>;
|
|
40
52
|
/**
|
|
41
53
|
* Convierte getServerSideProps en un middleware de Express
|
|
42
54
|
*/
|
|
43
|
-
export declare function createGetServerSidePropsMiddleware(pageModule: PageModule): RequestHandler;
|
|
55
|
+
export declare function createGetServerSidePropsMiddleware(pageModule: PageModule, file?: string): RequestHandler;
|
|
44
56
|
/**
|
|
45
57
|
* Creates a unified error handler for a specific page route
|
|
46
58
|
* This replaces the old createPageErrorMiddleware with a more useful approach
|
|
47
59
|
*/
|
|
48
|
-
export declare function createPageErrorHandler(pageFile: string,
|
|
60
|
+
export declare function createPageErrorHandler(pageFile: string, loader?: ModuleLoader, middlewares?: readonly MiddlewareInfo[]): (err: any, req: any, res: any, next: any) => Promise<any>;
|
|
49
61
|
/**
|
|
50
62
|
* Creates a dynamic middleware handler that reloads middlewares on each request in development
|
|
51
63
|
* This enables HMR for middlewares
|
|
52
64
|
* I FUCKING HATE THIS FUNCTION BUT IT SEEMS TO WORK
|
|
53
65
|
*/
|
|
54
|
-
export declare function createDynamicPageMiddlewares(pageRoute: string, pageFile: string, vite?: any): RequestHandler;
|
|
55
66
|
/**
|
|
56
67
|
* 1. Resuelve middlewares previos al getServerSideProps
|
|
57
68
|
*/
|
|
58
|
-
export declare function getPagePrevMiddlewares(pageRoute: string,
|
|
69
|
+
export declare function getPagePrevMiddlewares(pageRoute: string, loader?: ModuleLoader): Promise<RequestHandler[]>;
|
|
59
70
|
/**
|
|
60
71
|
* 2. Convierte getServerSideProps a middleware
|
|
61
72
|
*/
|
|
62
|
-
export declare function getServerSidePropsAsMiddleware(pageFile: string,
|
|
73
|
+
export declare function getServerSidePropsAsMiddleware(pageFile: string, loader?: ModuleLoader): Promise<RequestHandler>;
|
|
63
74
|
/**
|
|
64
75
|
* 3. Error middleware con fallback automático y jerarquía
|
|
65
76
|
* Orden de prioridad (el más específico gana):
|
|
@@ -67,6 +78,6 @@ export declare function getServerSidePropsAsMiddleware(pageFile: string, vite?:
|
|
|
67
78
|
* 2. errorMiddleware en [page].middlewares.ts
|
|
68
79
|
* 3. errorMiddleware en carpeta/middlewares.ts
|
|
69
80
|
* 4. errorMiddleware en root middlewares.ts (más general)
|
|
70
|
-
* 5.
|
|
81
|
+
* 5. ninguno: null, para que el llamador delegue con next(err)
|
|
71
82
|
*/
|
|
72
|
-
export declare function getErrorMiddleware(pageFile: string,
|
|
83
|
+
export declare function getErrorMiddleware(pageFile: string, loader?: ModuleLoader, middlewares?: readonly MiddlewareInfo[]): Promise<any>;
|