lovable-ssr 0.1.13 → 0.1.14
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/ssr/render.d.ts +6 -0
- package/dist/ssr/render.d.ts.map +1 -1
- package/dist/ssr/render.js +9 -6
- package/dist/ssr/server.d.ts.map +1 -1
- package/dist/ssr/server.js +40 -9
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -1
package/dist/ssr/render.d.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
+
import { RequestContext } from '../types.js';
|
|
2
3
|
export interface RenderResult {
|
|
3
4
|
html: string;
|
|
4
5
|
preloadedData: Record<string, unknown>;
|
|
5
6
|
}
|
|
6
7
|
export interface RenderOptions {
|
|
7
8
|
wrap?: (children: ReactNode) => ReactNode;
|
|
9
|
+
/**
|
|
10
|
+
* Contexto opcional da request (ex.: cookies, headers).
|
|
11
|
+
* O servidor pode preencher isso e o getData recebe via params.request.
|
|
12
|
+
*/
|
|
13
|
+
requestContext?: RequestContext;
|
|
8
14
|
}
|
|
9
15
|
/**
|
|
10
16
|
* Renders the app for a single URL. Called once per request with that request's URL.
|
package/dist/ssr/render.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/ssr/render.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/ssr/render.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,SAAS,CAAC;IAC1C;;;OAGG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED;;;GAGG;AACH,wBAAsB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CA4CxF"}
|
package/dist/ssr/render.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { renderToString } from 'react-dom/server';
|
|
3
3
|
import { StaticRouter } from 'react-router-dom/server';
|
|
4
|
-
import RouterService from '../router/RouterService.js';
|
|
5
|
-
import { RouteDataProvider } from '../router/RouteDataContext.js';
|
|
6
4
|
import { AppRoutes } from '../components/AppRoutes.js';
|
|
5
|
+
import { RouteDataProvider } from '../router/RouteDataContext.js';
|
|
6
|
+
import RouterService from '../router/RouterService.js';
|
|
7
7
|
/**
|
|
8
8
|
* Renders the app for a single URL. Called once per request with that request's URL.
|
|
9
9
|
* getData is invoked only for the route that matches this URL (never for all routes).
|
|
@@ -12,12 +12,15 @@ export async function render(url, options) {
|
|
|
12
12
|
const fullUrl = new URL(url, 'http://localhost');
|
|
13
13
|
const pathname = fullUrl.pathname || '/';
|
|
14
14
|
const matchedRoute = RouterService.matchRoute(pathname);
|
|
15
|
-
const params = matchedRoute
|
|
16
|
-
routeParams
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
const params = matchedRoute
|
|
16
|
+
? RouterService.routeParams(matchedRoute.path, pathname)
|
|
17
|
+
: {
|
|
18
|
+
routeParams: {},
|
|
19
|
+
searchParams: {},
|
|
20
|
+
};
|
|
19
21
|
const searchParams = matchedRoute ? RouterService.searchParams(fullUrl.search) : {};
|
|
20
22
|
params.searchParams = searchParams;
|
|
23
|
+
params.request = options?.requestContext;
|
|
21
24
|
let preloadedData = { is_success: true };
|
|
22
25
|
const getData = matchedRoute?.Component?.getData;
|
|
23
26
|
if (typeof getData === 'function') {
|
package/dist/ssr/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/ssr/server.ts"],"names":[],"mappings":"AAGA,OAAgB,EAAE,KAAK,OAAO,EAAkD,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/ssr/server.ts"],"names":[],"mappings":"AAGA,OAAgB,EAAE,KAAK,OAAO,EAAkD,MAAM,SAAS,CAAC;AAKhG,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,yFAAyF;IACzF,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wGAAwG;IACxG,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAkPD,wBAAsB,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC;IACtE,MAAM,EAAE,MAAM,OAAO,CAAC;IACtB,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;CACxD,CAAC,CAOD;AAED;qDACqD;AACrD,wBAAgB,SAAS,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,QAO7D"}
|
package/dist/ssr/server.js
CHANGED
|
@@ -74,7 +74,7 @@ class SsrServer {
|
|
|
74
74
|
if (!RouterService.isSsrRoute(pathname)) {
|
|
75
75
|
return await this.renderSpa(url, res);
|
|
76
76
|
}
|
|
77
|
-
return await this.renderSsr(url, res);
|
|
77
|
+
return await this.renderSsr(url, res, req);
|
|
78
78
|
}
|
|
79
79
|
catch (e) {
|
|
80
80
|
if (this.vite) {
|
|
@@ -93,29 +93,60 @@ class SsrServer {
|
|
|
93
93
|
const template = this.readTemplate(path.join(this.config.root, 'dist', 'index.html'));
|
|
94
94
|
return res.status(200).set({ 'Content-Type': 'text/html' }).send(template);
|
|
95
95
|
}
|
|
96
|
-
async renderSsr(url, res) {
|
|
96
|
+
async renderSsr(url, res, req) {
|
|
97
97
|
const { template, render } = await this.getSsrRenderer();
|
|
98
98
|
if (process.env.NODE_ENV !== 'production' && process.env.LOVABLE_SSR_DEBUG) {
|
|
99
99
|
console.log('[lovable-ssr] render(url)', url);
|
|
100
100
|
}
|
|
101
101
|
let appHtml;
|
|
102
102
|
let preloadedData;
|
|
103
|
+
// Constrói um contexto simples de request (cookies raw + headers) para o getData.
|
|
104
|
+
const cookiesRaw = req.headers.cookie ?? '';
|
|
105
|
+
const cookies = {};
|
|
106
|
+
if (cookiesRaw) {
|
|
107
|
+
cookiesRaw.split(';').forEach((part) => {
|
|
108
|
+
const [k, ...rest] = part.split('=');
|
|
109
|
+
if (!k)
|
|
110
|
+
return;
|
|
111
|
+
const key = k.trim();
|
|
112
|
+
if (!key)
|
|
113
|
+
return;
|
|
114
|
+
const value = rest.join('=').trim();
|
|
115
|
+
cookies[key] = decodeURIComponent(value);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
const requestContext = {
|
|
119
|
+
cookiesRaw,
|
|
120
|
+
cookies,
|
|
121
|
+
headers: req.headers,
|
|
122
|
+
method: req.method,
|
|
123
|
+
url: req.originalUrl,
|
|
124
|
+
};
|
|
103
125
|
if (this.isProd) {
|
|
104
126
|
const cacheKey = this.normalizeCacheKey(url);
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
127
|
+
const hasCookies = !!cookiesRaw;
|
|
128
|
+
// Evita cachear respostas personalizadas por cookies (ex.: auth).
|
|
129
|
+
if (!hasCookies) {
|
|
130
|
+
const cached = this._ssrCache.get(cacheKey);
|
|
131
|
+
if (cached) {
|
|
132
|
+
appHtml = cached.html;
|
|
133
|
+
preloadedData = cached.preloadedData;
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
const result = await render(url, { requestContext });
|
|
137
|
+
appHtml = typeof result.html === 'string' ? result.html : '';
|
|
138
|
+
preloadedData = result.preloadedData ?? {};
|
|
139
|
+
this._ssrCache.set(cacheKey, { html: appHtml, preloadedData });
|
|
140
|
+
}
|
|
109
141
|
}
|
|
110
142
|
else {
|
|
111
|
-
const result = await render(url);
|
|
143
|
+
const result = await render(url, { requestContext });
|
|
112
144
|
appHtml = typeof result.html === 'string' ? result.html : '';
|
|
113
145
|
preloadedData = result.preloadedData ?? {};
|
|
114
|
-
this._ssrCache.set(cacheKey, { html: appHtml, preloadedData });
|
|
115
146
|
}
|
|
116
147
|
}
|
|
117
148
|
else {
|
|
118
|
-
const result = await render(url);
|
|
149
|
+
const result = await render(url, { requestContext });
|
|
119
150
|
appHtml = typeof result.html === 'string' ? result.html : '';
|
|
120
151
|
preloadedData = result.preloadedData ?? {};
|
|
121
152
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IncomingHttpHeaders } from 'node:http';
|
|
1
2
|
import type React from 'react';
|
|
2
3
|
export type ComponentWithGetData = React.ComponentType<any> & {
|
|
3
4
|
getData?: (params?: Record<'routeParams' | 'searchParams', Record<string, string>>) => Promise<Record<string, unknown>>;
|
|
@@ -7,4 +8,11 @@ export type RouteConfig = {
|
|
|
7
8
|
Component: ComponentWithGetData;
|
|
8
9
|
isSSR: boolean;
|
|
9
10
|
};
|
|
11
|
+
export type RequestContext = {
|
|
12
|
+
cookiesRaw: string;
|
|
13
|
+
cookies: Record<string, string>;
|
|
14
|
+
headers: IncomingHttpHeaders;
|
|
15
|
+
method: string;
|
|
16
|
+
url: string;
|
|
17
|
+
};
|
|
10
18
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,MAAM,oBAAoB,GAAG,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG;IAC5D,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,aAAa,GAAG,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACzH,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,oBAAoB,CAAC;IAChC,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,MAAM,oBAAoB,GAAG,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG;IAC5D,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,aAAa,GAAG,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACzH,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,oBAAoB,CAAC;IAChC,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AACF,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,OAAO,EAAE,mBAAmB,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb,CAAC"}
|