@ressjs/vite-router 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/router.js ADDED
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getPages = void 0;
7
+ exports.createAutoViteServer = createAutoViteServer;
8
+ exports.createViteRouter = createViteRouter;
9
+ exports.listDetectedPages = listDetectedPages;
10
+ const express_1 = require("express");
11
+ const pages_1 = require("./pages");
12
+ const express_2 = __importDefault(require("express"));
13
+ const vite_config_1 = require("./helpers/vite-config");
14
+ const request_handler_1 = require("./helpers/request-handler");
15
+ async function createAutoViteServer(options = {}) {
16
+ const { port = 5173, base = '/', enablePlatformDetection = true } = options;
17
+ const isProduction = process.env.NODE_ENV === 'production';
18
+ const app = (0, express_2.default)();
19
+ const viteConfig = await (0, vite_config_1.setupVite)(isProduction, base);
20
+ if (!isProduction) {
21
+ app.use(viteConfig.vite.middlewares);
22
+ app.use('/dist/.entries', express_2.default.static('dist/.entries'));
23
+ }
24
+ else {
25
+ const prodFactory = (0, vite_config_1.createProdMiddleware)();
26
+ const prodMiddleware = await prodFactory();
27
+ app.use(prodMiddleware);
28
+ }
29
+ const viteRouter = createViteRouter({
30
+ enablePlatformDetection,
31
+ vite: viteConfig.vite,
32
+ templateHtml: viteConfig.templateHtml,
33
+ isProduction
34
+ });
35
+ app.use('/', viteRouter);
36
+ app.use(express_2.default.static('public'));
37
+ const start = () => {
38
+ return app.listen(port, () => {
39
+ const pages = (0, pages_1.getPages)();
40
+ console.log(`🚀 Auto Vite Server started at http://localhost:${port}`);
41
+ console.log(`📄 Auto-detected routes:`);
42
+ pages.forEach(page => {
43
+ console.log(` ${page.route} -> ${page.file}`);
44
+ });
45
+ });
46
+ };
47
+ return { app, vite: viteConfig.vite, start };
48
+ }
49
+ function createViteRouter(options = {}) {
50
+ const needsAutoConfig = !options.vite && !options.templateHtml && options.isProduction !== true;
51
+ if (needsAutoConfig) {
52
+ return createAutoRouter(options);
53
+ }
54
+ return createManualRouter(options);
55
+ }
56
+ function createAutoRouter(options) {
57
+ const { enablePlatformDetection = true, renderFunction } = options;
58
+ const isProduction = process.env.NODE_ENV === 'production';
59
+ let viteConfig = null;
60
+ let renderServer = null;
61
+ let initialized = false;
62
+ const mainRouter = (0, express_1.Router)();
63
+ const initializeIfNeeded = async () => {
64
+ if (initialized)
65
+ return viteConfig;
66
+ const basePath = process.env.BASE || '/';
67
+ viteConfig = await (0, vite_config_1.setupVite)(isProduction, basePath);
68
+ if (!isProduction) {
69
+ mainRouter.use(viteConfig.vite.middlewares);
70
+ }
71
+ else {
72
+ const prodFactory = (0, vite_config_1.createProdMiddleware)();
73
+ const prodMiddleware = await prodFactory();
74
+ mainRouter.use(prodMiddleware);
75
+ }
76
+ initialized = true;
77
+ return viteConfig;
78
+ };
79
+ const pages = (0, pages_1.getPages)();
80
+ pages.forEach(page => {
81
+ mainRouter.get(page.route, async (req, res, next) => {
82
+ await initializeIfNeeded();
83
+ await (0, request_handler_1.processRequest)({ req, res, page, next }, {
84
+ enablePlatformDetection,
85
+ renderFunction,
86
+ viteConfig
87
+ }, renderServer);
88
+ });
89
+ });
90
+ return mainRouter;
91
+ }
92
+ function createManualRouter(options) {
93
+ const { enablePlatformDetection = true, vite, templateHtml = '', isProduction = process.env.NODE_ENV === 'production', renderFunction } = options;
94
+ const router = (0, express_1.Router)();
95
+ const pages = (0, pages_1.getPages)();
96
+ let renderServer = null;
97
+ const viteConfig = {
98
+ vite,
99
+ manifest: {},
100
+ templateHtml,
101
+ isProduction
102
+ };
103
+ pages.forEach(page => {
104
+ router.get(page.route, async (req, res, next) => {
105
+ await (0, request_handler_1.processRequest)({ req, res, page, next }, {
106
+ enablePlatformDetection,
107
+ renderFunction,
108
+ viteConfig
109
+ }, renderServer);
110
+ });
111
+ });
112
+ return router;
113
+ }
114
+ function listDetectedPages() {
115
+ return (0, pages_1.getPages)();
116
+ }
117
+ var pages_2 = require("./pages");
118
+ Object.defineProperty(exports, "getPages", { enumerable: true, get: function () { return pages_2.getPages; } });
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@ressjs/vite-router",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "Express router factory for ress.js with automatic page detection and SSR",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
- "type": "module",
8
7
  "publishConfig": {
9
8
  "access": "public"
10
9
  },
11
10
  "exports": {
12
11
  ".": {
13
12
  "types": "./dist/index.d.ts",
13
+ "require": "./dist/index.js",
14
14
  "import": "./dist/index.js"
15
15
  }
16
16
  },
@@ -21,6 +21,9 @@
21
21
  "build": "tsc",
22
22
  "dev": "tsc --watch",
23
23
  "clean": "rm -rf dist",
24
+ "test": "vitest run",
25
+ "test:watch": "vitest",
26
+ "test:e2e": "vitest run tests/e2e",
24
27
  "prepublishOnly": "npm run build"
25
28
  },
26
29
  "keywords": [
@@ -33,19 +36,26 @@
33
36
  "author": "ressjs team",
34
37
  "license": "MIT",
35
38
  "devDependencies": {
39
+ "@jest/globals": "^29.7.0",
36
40
  "@types/compression": "^1.7.5",
37
- "@types/express": "^5.0.0",
38
- "@types/node": "^22.13.4",
39
- "typescript": "~5.7.3"
41
+ "@types/express": "^5.0.3",
42
+ "@types/jest": "^30.0.0",
43
+ "@types/node": "^22.17.2",
44
+ "axios": "^1.11.0",
45
+ "express": "^5.1.0",
46
+ "jest": "^29.7.0",
47
+ "ts-jest": "^29.4.1",
48
+ "typescript": "~5.7.3",
49
+ "vitest": "^3.2.4"
40
50
  },
41
51
  "dependencies": {
42
- "@ressjs/core": "^0.3.0",
43
- "chokidar": "^4.0.3",
44
52
  "compression": "^1.8.0",
45
- "express": "^5.0.1",
53
+ "fast-glob": "^3.3.3",
46
54
  "sirv": "^3.0.1"
47
55
  },
48
56
  "peerDependencies": {
49
- "vite": "^6.0.0"
57
+ "vite": "^6.0.0",
58
+ "react": "^19.0.0",
59
+ "react-dom": "^19.0.0"
50
60
  }
51
61
  }
@@ -1,33 +0,0 @@
1
- import { PageInfo } from '@ressjs/core';
2
- import { Request as ExpressRequest } from 'express';
3
- export interface EntryGeneratorOptions {
4
- pagesDir: string;
5
- outputDir?: string;
6
- platform?: 'desktop' | 'mobile';
7
- }
8
- export declare class EntryGenerator {
9
- private options;
10
- constructor(options: EntryGeneratorOptions);
11
- /**
12
- * Genera entry-client dinámicos para las páginas detectadas
13
- */
14
- generateDynamicEntries(): Promise<string[]>;
15
- /**
16
- * Detecta el platform basado en el user-agent de la request
17
- */
18
- detectPlatformFromRequest(req: ExpressRequest): 'desktop' | 'mobile';
19
- /**
20
- * Genera entry específico para un platform
21
- */
22
- generatePlatformSpecificEntry(pageRoute: string, platform: 'desktop' | 'mobile', pages: PageInfo[]): Promise<string>;
23
- /**
24
- * Escribe entry files al filesystem
25
- */
26
- writeEntryFiles(entries: {
27
- [key: string]: string;
28
- }): Promise<void>;
29
- /**
30
- * Limpia archivos temporales generados
31
- */
32
- cleanup(): Promise<void>;
33
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"entry-generator.d.ts","sourceRoot":"","sources":["../src/entry-generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,SAAS,CAAA;AAEnD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAA;CAChC;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAiC;gBAEpC,OAAO,EAAE,qBAAqB;IAQ1C;;OAEG;IACG,sBAAsB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAIjD;;OAEG;IACH,yBAAyB,CAAC,GAAG,EAAE,cAAc,GAAG,SAAS,GAAG,QAAQ;IAUpE;;OAEG;IACG,6BAA6B,CACjC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,SAAS,GAAG,QAAQ,EAC9B,KAAK,EAAE,QAAQ,EAAE,GAChB,OAAO,CAAC,MAAM,CAAC;IAuElB;;OAEG;IACG,eAAe,CAAC,OAAO,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAYxE;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAQ/B"}
@@ -1,112 +0,0 @@
1
- import { generateTempEntries } from '@ressjs/core';
2
- export class EntryGenerator {
3
- constructor(options) {
4
- this.options = {
5
- outputDir: 'temp',
6
- platform: 'desktop',
7
- ...options
8
- };
9
- }
10
- /**
11
- * Genera entry-client dinámicos para las páginas detectadas
12
- */
13
- async generateDynamicEntries() {
14
- return generateTempEntries(this.options.outputDir);
15
- }
16
- /**
17
- * Detecta el platform basado en el user-agent de la request
18
- */
19
- detectPlatformFromRequest(req) {
20
- const userAgent = req.headers['user-agent']?.toLowerCase() || '';
21
- // Simple mobile detection
22
- const mobileKeywords = ['mobile', 'android', 'iphone', 'ipad', 'blackberry', 'windows phone'];
23
- const isMobile = mobileKeywords.some(keyword => userAgent.includes(keyword));
24
- return isMobile ? 'mobile' : 'desktop';
25
- }
26
- /**
27
- * Genera entry específico para un platform
28
- */
29
- async generatePlatformSpecificEntry(pageRoute, platform, pages) {
30
- const page = pages.find(p => p.route === pageRoute);
31
- if (!page) {
32
- throw new Error(`Page ${pageRoute} not found`);
33
- }
34
- // Detectar archivos de estilos relacionados con la página
35
- const fs = await import('fs/promises');
36
- const path = await import('path');
37
- const pageDir = path.dirname(page.file);
38
- const baseName = path.basename(page.file, path.extname(page.file));
39
- // Buscar archivos de estilos
40
- const possibleStyles = [
41
- path.join(pageDir, `${baseName}.scss`),
42
- path.join(pageDir, `${baseName}.css`),
43
- path.join(pageDir, `${baseName}.${platform}.scss`),
44
- path.join(pageDir, `${baseName}.${platform}.css`),
45
- path.join(pageDir, 'index.scss'),
46
- path.join(pageDir, 'index.css'),
47
- path.join(pageDir, `index.${platform}.scss`),
48
- path.join(pageDir, `index.${platform}.css`)
49
- ];
50
- const existingStyles = [];
51
- for (const stylePath of possibleStyles) {
52
- try {
53
- await fs.access(stylePath);
54
- existingStyles.push(stylePath);
55
- }
56
- catch {
57
- // Archivo no existe, continuar
58
- }
59
- }
60
- // Separar estilos generales de platform-specific
61
- const generalStyles = existingStyles.filter(style => !style.includes(`.${platform}.`) &&
62
- !style.includes('.mobile.') &&
63
- !style.includes('.desktop.'));
64
- const platformStyles = existingStyles.filter(style => style.includes(`.${platform}.`));
65
- // Generar el entry client dinámicamente
66
- const entryContent = `
67
- import React from 'react'
68
- import { createRoot } from 'react-dom/client'
69
- import Page from '${page.abs}'
70
- ${generalStyles.map(style => `import '${style}'`).join('\n')}
71
- ${platformStyles.map(style => `import '${style}'`).join('\n')}
72
-
73
- // Platform-specific styles
74
- document.documentElement.classList.add('${platform}')
75
-
76
- const container = document.getElementById('root')
77
- if (container) {
78
- const root = createRoot(container)
79
-
80
- // Hydrate con props del servidor si están disponibles
81
- const serverProps = (window as any).__SERVER_PROPS__ || {}
82
-
83
- root.render(React.createElement(Page, serverProps))
84
- }
85
- `;
86
- return entryContent.trim();
87
- }
88
- /**
89
- * Escribe entry files al filesystem
90
- */
91
- async writeEntryFiles(entries) {
92
- const fs = await import('fs/promises');
93
- const path = await import('path');
94
- await fs.mkdir(this.options.outputDir, { recursive: true });
95
- for (const [filename, content] of Object.entries(entries)) {
96
- const filepath = path.join(this.options.outputDir, `${filename}.tsx`);
97
- await fs.writeFile(filepath, content, 'utf-8');
98
- }
99
- }
100
- /**
101
- * Limpia archivos temporales generados
102
- */
103
- async cleanup() {
104
- const fs = await import('fs/promises');
105
- try {
106
- await fs.rm(this.options.outputDir, { recursive: true, force: true });
107
- }
108
- catch (error) {
109
- // Ignorar errores si el directorio no existe
110
- }
111
- }
112
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"entry-generator.js","sourceRoot":"","sources":["../src/entry-generator.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,iBAAiB,EACjB,QAAQ,EACT,MAAM,oBAAoB,CAAA;AAE3B,YAAY,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAGlF,OAAO,EAAE,aAAa,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAA;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAC7E,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACvE,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAGjE,YAAY,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,iBAAiB,EACjB,QAAQ,EACT,MAAM,oBAAoB,CAAA;AAI3B,kDAAkD;AAClD,OAAO,EAAE,aAAa,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAA;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA"}
@@ -1,43 +0,0 @@
1
- import { PageInfo } from '@ressjs/core';
2
- import { Request } from 'express';
3
- export interface RouterOptions {
4
- distPath?: string;
5
- pagesDir?: string;
6
- renderFunction?: (url: string) => Promise<{
7
- html: string;
8
- props: any;
9
- }>;
10
- }
11
- export interface PageRouterInfo extends PageInfo {
12
- entryPath?: string;
13
- }
14
- export declare class PageDetector {
15
- private distPath;
16
- private pagesDir;
17
- constructor(options?: RouterOptions);
18
- /**
19
- * Detecta todas las páginas disponibles
20
- */
21
- getDetectedPages(): PageRouterInfo[];
22
- /**
23
- * Genera entry-clients para todas las páginas
24
- */
25
- generatePageEntries(): Promise<void>;
26
- /**
27
- * Obtiene input para Vite client build
28
- */
29
- getClientBuildInput(): Promise<Record<string, string>>;
30
- /**
31
- * Detecta la plataforma desde el user agent
32
- */
33
- detectPlatform(req: Request): string;
34
- /**
35
- * Encuentra una página por su ruta
36
- */
37
- findPageByRoute(route: string): PageRouterInfo | undefined;
38
- private getEntryPath;
39
- /**
40
- * Encuentra la página que coincide con una ruta específica
41
- */
42
- matchRoute(requestPath: string, pages: PageInfo[]): PageInfo | null;
43
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"page-detector.d.ts","sourceRoot":"","sources":["../src/page-detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8C,QAAQ,EAAE,MAAM,cAAc,CAAA;AACnF,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAIjC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,GAAG,CAAA;KAAE,CAAC,CAAA;CACxE;AAED,MAAM,WAAW,cAAe,SAAQ,QAAQ;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,QAAQ,CAAQ;gBAEZ,OAAO,GAAE,aAAkB;IAKvC;;OAEG;IACI,gBAAgB,IAAI,cAAc,EAAE;IAsB3C;;OAEG;IACU,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjD;;OAEG;IACU,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAInE;;OAEG;IACI,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM;IAO3C;;OAEG;IACI,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAQjE,OAAO,CAAC,YAAY;IAKpB;;OAEG;IACH,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,QAAQ,GAAG,IAAI;CAuBpE"}
@@ -1,91 +0,0 @@
1
- import { generateTempEntries, getClientEntriesInput } from '@ressjs/core';
2
- import glob from 'fast-glob';
3
- import { resolve } from 'path';
4
- export class PageDetector {
5
- constructor(options = {}) {
6
- this.distPath = options.distPath || 'dist';
7
- this.pagesDir = options.pagesDir || 'app/pages';
8
- }
9
- /**
10
- * Detecta todas las páginas disponibles
11
- */
12
- getDetectedPages() {
13
- // Busca tanto page.tsx como page/index.tsx y prioriza el más corto
14
- const files = glob.sync(`${this.pagesDir}/**/*.{tsx,jsx}`);
15
- const seen = new Set();
16
- const pages = [];
17
- for (const file of files) {
18
- let route = file.replace(new RegExp(`^${this.pagesDir}`), '').replace(/\.tsx$|\.jsx$/, '');
19
- route = route.replace(/\/index$/, '') || '/';
20
- // Prioriza page.tsx sobre page/index.tsx
21
- if (!seen.has(route)) {
22
- seen.add(route);
23
- pages.push({ route, file, abs: resolve(file) });
24
- }
25
- }
26
- return pages.map(page => ({
27
- ...page,
28
- entryPath: this.getEntryPath(page)
29
- }));
30
- }
31
- /**
32
- * Genera entry-clients para todas las páginas
33
- */
34
- async generatePageEntries() {
35
- await generateTempEntries(this.distPath);
36
- }
37
- /**
38
- * Obtiene input para Vite client build
39
- */
40
- async getClientBuildInput() {
41
- return await getClientEntriesInput(this.distPath);
42
- }
43
- /**
44
- * Detecta la plataforma desde el user agent
45
- */
46
- detectPlatform(req) {
47
- const ua = req.headers['user-agent'] || '';
48
- if (/mobile|android|iphone|ipad|phone/i.test(ua))
49
- return 'mobile';
50
- if (/linux/i.test(ua))
51
- return 'desktop.linux';
52
- return 'desktop';
53
- }
54
- /**
55
- * Encuentra una página por su ruta
56
- */
57
- findPageByRoute(route) {
58
- const pages = this.getDetectedPages();
59
- return pages.find(page => {
60
- if (page.route === '/')
61
- return route === '/' || route === '';
62
- return route === page.route || route.startsWith(page.route + '/');
63
- });
64
- }
65
- getEntryPath(page) {
66
- const rel = page.file.replace(/^app\/pages\//, '').replace(/\.tsx$|\.jsx$/, '');
67
- return `${this.distPath}/.entries/${rel}__entry-client.tsx`;
68
- }
69
- /**
70
- * Encuentra la página que coincide con una ruta específica
71
- */
72
- matchRoute(requestPath, pages) {
73
- // Normalizar la ruta de request
74
- const normalizedPath = requestPath === '/' ? '/' : requestPath.replace(/\/$/, '');
75
- // Buscar coincidencia exacta primero
76
- let match = pages.find(page => page.route === normalizedPath);
77
- // Si no hay coincidencia exacta, buscar rutas dinámicas o wildcards
78
- if (!match) {
79
- // Para rutas como /page1, /page2, etc.
80
- match = pages.find(page => {
81
- // Convertir ruta de página a regex para matching
82
- const routePattern = page.route
83
- .replace(/\[([^\]]+)\]/g, '([^/]+)') // [param] -> captura
84
- .replace(/\*/g, '.*'); // * -> wildcard
85
- const regex = new RegExp(`^${routePattern}$`);
86
- return regex.test(normalizedPath);
87
- });
88
- }
89
- return match || null;
90
- }
91
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"page-detector.js","sourceRoot":"","sources":["../src/page-detector.ts"],"names":[],"mappings":"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"}
@@ -1,57 +0,0 @@
1
- import { Router } from 'express';
2
- import { PageInfo } from '@ressjs/core';
3
- export interface RouterFactoryOptions {
4
- pagesDir: string;
5
- outputDir?: string;
6
- enableSSR?: boolean;
7
- enablePlatformDetection?: boolean;
8
- staticDir?: string;
9
- }
10
- export interface RouteContext {
11
- page: PageInfo;
12
- platform: 'desktop' | 'mobile';
13
- entry: string;
14
- }
15
- export declare class RouterFactory {
16
- private options;
17
- private pageDetector;
18
- private entryGenerator;
19
- private renderServer;
20
- constructor(options: RouterFactoryOptions);
21
- /**
22
- * Crea un Express Router con todas las rutas automáticas
23
- */
24
- createRouter(): Router;
25
- /**
26
- * Middleware para detectar páginas y preparar context
27
- */
28
- private pageDetectionMiddleware;
29
- /**
30
- * Middleware para Server-Side Rendering
31
- */
32
- private ssrMiddleware;
33
- /**
34
- * Middleware para archivos estáticos
35
- */
36
- private staticMiddleware;
37
- /**
38
- * Inyecta el entry client específico del platform en el HTML
39
- */
40
- private injectClientEntry;
41
- /**
42
- * Limpia archivos temporales
43
- */
44
- cleanup(): Promise<void>;
45
- /**
46
- * Inicializa el router (genera entries iniciales)
47
- */
48
- initialize(): Promise<void>;
49
- }
50
- /**
51
- * Factory function para crear un router fácilmente
52
- */
53
- export declare function createViteRouter(options: RouterFactoryOptions): Router;
54
- /**
55
- * Factory function async para inicializar y crear el router
56
- */
57
- export declare function createInitializedViteRouter(options: RouterFactoryOptions): Promise<Router>;
@@ -1 +0,0 @@
1
- {"version":3,"file":"router-factory.d.ts","sourceRoot":"","sources":["../src/router-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAmC,MAAM,SAAS,CAAA;AAGjE,OAAO,EAAsB,QAAQ,EAAE,MAAM,cAAc,CAAA;AAE3D,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,QAAQ,CAAA;IACd,QAAQ,EAAE,SAAS,GAAG,QAAQ,CAAA;IAC9B,KAAK,EAAE,MAAM,CAAA;CACd;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAgC;IAC/C,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,YAAY,CAAK;gBAEb,OAAO,EAAE,oBAAoB;IAwBzC;;OAEG;IACH,YAAY,IAAI,MAAM;IAiBtB;;OAEG;YACW,uBAAuB;IAiDrC;;OAEG;YACW,aAAa;IA4B3B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAUxB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAqBzB;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAGlC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,CAGtE;AAED;;GAEG;AACH,wBAAsB,2BAA2B,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAIhG"}