@gracile/engine 0.9.0-next.3 → 0.9.0-next.5
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/plugin.d.ts.map +1 -1
- package/dist/plugin.js +42 -254
- package/dist/render/light-dom.d.ts +2 -0
- package/dist/render/light-dom.d.ts.map +1 -0
- package/dist/render/light-dom.js +31 -0
- package/dist/render/route-template-pipeline.d.ts +64 -0
- package/dist/render/route-template-pipeline.d.ts.map +1 -0
- package/dist/render/route-template-pipeline.js +144 -0
- package/dist/render/route-template.d.ts +4 -3
- package/dist/render/route-template.d.ts.map +1 -1
- package/dist/render/route-template.js +17 -88
- package/dist/routes/collect.d.ts +4 -0
- package/dist/routes/collect.d.ts.map +1 -1
- package/dist/routes/collect.js +2 -1
- package/dist/routes/match.d.ts +26 -0
- package/dist/routes/match.d.ts.map +1 -1
- package/dist/routes/match.js +4 -2
- package/dist/routes/render.d.ts.map +1 -1
- package/dist/routes/render.js +1 -0
- package/dist/server/request-pipeline.d.ts +109 -0
- package/dist/server/request-pipeline.d.ts.map +1 -0
- package/dist/server/request-pipeline.js +198 -0
- package/dist/server/request.d.ts +3 -16
- package/dist/server/request.d.ts.map +1 -1
- package/dist/server/request.js +56 -169
- package/dist/test/init.d.ts +2 -0
- package/dist/test/init.d.ts.map +1 -0
- package/dist/test/init.js +7 -0
- package/dist/user-config.d.ts +35 -0
- package/dist/user-config.d.ts.map +1 -1
- package/dist/vite/plugin-client-build.d.ts +16 -0
- package/dist/vite/plugin-client-build.d.ts.map +1 -0
- package/dist/vite/plugin-client-build.js +49 -0
- package/dist/vite/plugin-serve.d.ts +18 -0
- package/dist/vite/plugin-serve.d.ts.map +1 -0
- package/dist/vite/plugin-serve.js +62 -0
- package/dist/vite/plugin-server-build.d.ts +33 -0
- package/dist/vite/plugin-server-build.d.ts.map +1 -0
- package/dist/vite/plugin-server-build.js +157 -0
- package/dist/vite/plugin-shared-state.d.ts +31 -0
- package/dist/vite/plugin-shared-state.d.ts.map +1 -0
- package/dist/vite/plugin-shared-state.js +22 -0
- package/package.json +4 -4
package/dist/server/request.js
CHANGED
|
@@ -1,24 +1,11 @@
|
|
|
1
1
|
import { Readable } from 'node:stream';
|
|
2
|
-
import * as assert from '@gracile/internal-utils/assertions';
|
|
3
2
|
import { getLogger } from '@gracile/internal-utils/logger/helpers';
|
|
4
3
|
import c from 'picocolors';
|
|
5
|
-
// import { GracileError } from '../errors/errors.js';
|
|
6
4
|
import { builtIn404Page, builtInErrorPage } from '../errors/pages.js';
|
|
7
5
|
import { renderRouteTemplate } from '../render/route-template.js';
|
|
8
6
|
import { renderLitTemplate } from '../render/lit-ssr.js';
|
|
9
7
|
import { getRoute } from '../routes/match.js';
|
|
10
|
-
|
|
11
|
-
const PREMISE_REGEXES = {
|
|
12
|
-
properties: /\/__(.*?)\.props\.json$/,
|
|
13
|
-
document: /\/__(.*?)\.doc\.html$/,
|
|
14
|
-
};
|
|
15
|
-
export function isRedirect(response) {
|
|
16
|
-
const location = response.headers.get('location');
|
|
17
|
-
if (response.status >= 300 && response.status <= 303 && location) {
|
|
18
|
-
return { location };
|
|
19
|
-
}
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
8
|
+
import { CONTENT_TYPE_HTML, rewriteHiddenRoutes, resolvePremises, executeHandler, renderWithoutHandler, buildResponse, } from './request-pipeline.js';
|
|
22
9
|
export function createGracileHandler({ vite, routes, routeImports, routeAssets, root, serverMode, gracileConfig, }) {
|
|
23
10
|
const logger = getLogger();
|
|
24
11
|
const middleware = async (request, locals) => {
|
|
@@ -28,16 +15,11 @@ export function createGracileHandler({ vite, routes, routeImports, routeAssets,
|
|
|
28
15
|
emitViteBetterError =
|
|
29
16
|
await import('../errors/create-vite-better-error.js').then(({ emitViteBetterError: error }) => error);
|
|
30
17
|
try {
|
|
31
|
-
// MARK: Rewrite hidden route siblings
|
|
32
|
-
const fullUrl = requestedUrl
|
|
33
|
-
// MARK: Setup premises
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
const allowPremises = Boolean(gracileConfig.pages?.premises?.expose);
|
|
37
|
-
if (allowPremises === false && (propertiesOnly || documentOnly))
|
|
38
|
-
throw new Error('Accessed a page premise but they are not activated. You must enable `pages.premises.expose`.');
|
|
39
|
-
const premises = allowPremises ? { propertiesOnly, documentOnly } : null;
|
|
40
|
-
// MARK: Get route infos
|
|
18
|
+
// MARK: 1. Rewrite hidden route siblings
|
|
19
|
+
const fullUrl = rewriteHiddenRoutes(requestedUrl);
|
|
20
|
+
// MARK: 2. Setup premises
|
|
21
|
+
const premises = resolvePremises(requestedUrl, gracileConfig);
|
|
22
|
+
// MARK: 3. Route resolution + 404 fallback
|
|
41
23
|
const routeOptions = {
|
|
42
24
|
url: fullUrl,
|
|
43
25
|
vite,
|
|
@@ -46,15 +28,12 @@ export function createGracileHandler({ vite, routes, routeImports, routeAssets,
|
|
|
46
28
|
};
|
|
47
29
|
const responseInit = {};
|
|
48
30
|
let routeInfos = await getRoute(routeOptions);
|
|
49
|
-
// MARK: 404
|
|
50
31
|
if (routeInfos === null) {
|
|
51
32
|
responseInit.status = 404;
|
|
52
33
|
const url = new URL('/404/', fullUrl).href;
|
|
53
34
|
const options = { ...routeOptions, url };
|
|
54
|
-
|
|
55
|
-
routeInfos = notFound;
|
|
35
|
+
routeInfos = await getRoute(options);
|
|
56
36
|
}
|
|
57
|
-
// MARK: fallback 404
|
|
58
37
|
if (routeInfos === null) {
|
|
59
38
|
const page = builtIn404Page(new URL(fullUrl).pathname, Boolean(vite));
|
|
60
39
|
return {
|
|
@@ -66,163 +45,49 @@ export function createGracileHandler({ vite, routes, routeImports, routeAssets,
|
|
|
66
45
|
const routeTemplateOptions = {
|
|
67
46
|
url: fullUrl,
|
|
68
47
|
vite,
|
|
69
|
-
mode: 'dev',
|
|
48
|
+
mode: 'dev',
|
|
70
49
|
routeAssets,
|
|
71
50
|
root,
|
|
72
51
|
serverMode,
|
|
73
52
|
routeInfos,
|
|
74
53
|
docOnly: premises?.documentOnly,
|
|
54
|
+
renderInfo: gracileConfig.litSsr?.renderInfo,
|
|
75
55
|
};
|
|
76
56
|
logger.info(`[${c.yellow(method)}] ${c.yellow(fullUrl)}`, {
|
|
77
57
|
timestamp: true,
|
|
78
58
|
});
|
|
59
|
+
// MARK: 4. Handler dispatch
|
|
79
60
|
let output;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
});
|
|
95
|
-
// MARK: Run user middleware
|
|
96
|
-
// NOTE: Experimental
|
|
97
|
-
/// eslint-disable-next-line no-inner-declarations
|
|
98
|
-
// async function useHandler() {}
|
|
99
|
-
// if (vite) {
|
|
100
|
-
// const middleware = await vite
|
|
101
|
-
// .ssrLoadModule('/src/middleware.ts')
|
|
102
|
-
// .catch(() => null)
|
|
103
|
-
// .then((m) => m.default);
|
|
104
|
-
// if (middleware)
|
|
105
|
-
// await middleware(
|
|
106
|
-
// routeContext,
|
|
107
|
-
// async () => {
|
|
108
|
-
// await useHandler();
|
|
109
|
-
// },
|
|
110
|
-
// );
|
|
111
|
-
// else await useHandler();
|
|
112
|
-
// } else {
|
|
113
|
-
// await useHandler();
|
|
114
|
-
// }
|
|
115
|
-
//
|
|
116
|
-
// MARK: Handler(s)
|
|
117
|
-
const hasTopLevelHandler = typeof handler === 'function';
|
|
118
|
-
if (hasTopLevelHandler || method in handler) {
|
|
119
|
-
const handlerWithMethod = hasTopLevelHandler
|
|
120
|
-
? handler
|
|
121
|
-
: handler[method];
|
|
122
|
-
if (typeof handlerWithMethod !== 'function')
|
|
123
|
-
throw new TypeError('Handler must be a function.');
|
|
124
|
-
const handlerOutput = await Promise.resolve(handlerWithMethod(routeContext));
|
|
125
|
-
if (assert.isResponseOrPatchedResponse(handlerOutput))
|
|
126
|
-
output = handlerOutput;
|
|
127
|
-
else {
|
|
128
|
-
routeTemplateOptions.routeInfos.props = hasTopLevelHandler
|
|
129
|
-
? handlerOutput
|
|
130
|
-
: { [method]: handlerOutput };
|
|
131
|
-
if (premises?.documentOnly) {
|
|
132
|
-
const { document } = await renderRouteTemplate(routeTemplateOptions);
|
|
133
|
-
return {
|
|
134
|
-
response: new Response(document, {
|
|
135
|
-
headers: { ...CONTENT_TYPE_HTML },
|
|
136
|
-
}),
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
if (premises?.propertiesOnly)
|
|
140
|
-
return {
|
|
141
|
-
response: Response.json(routeTemplateOptions.routeInfos.props),
|
|
142
|
-
};
|
|
143
|
-
output = await renderRouteTemplate(routeTemplateOptions).then((r) => r.output);
|
|
144
|
-
}
|
|
145
|
-
// MARK: No GET, render page
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
const statusText = `This route doesn't handle the \`${method}\` method!`;
|
|
149
|
-
return {
|
|
150
|
-
response: new Response(statusText, { status: 405, statusText }),
|
|
151
|
-
};
|
|
152
|
-
}
|
|
61
|
+
const handlerResult = await executeHandler({
|
|
62
|
+
routeInfos,
|
|
63
|
+
method,
|
|
64
|
+
request,
|
|
65
|
+
fullUrl,
|
|
66
|
+
locals,
|
|
67
|
+
responseInit,
|
|
68
|
+
premises,
|
|
69
|
+
routeTemplateOptions,
|
|
70
|
+
});
|
|
71
|
+
if (handlerResult.type === 'response')
|
|
72
|
+
return handlerResult.value;
|
|
73
|
+
if (handlerResult.type === 'output') {
|
|
74
|
+
output = handlerResult.value;
|
|
153
75
|
}
|
|
154
76
|
else {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
if (premises?.propertiesOnly)
|
|
164
|
-
return {
|
|
165
|
-
response: Response.json(routeTemplateOptions.routeInfos.props || {}),
|
|
166
|
-
};
|
|
167
|
-
output = await renderRouteTemplate(routeTemplateOptions).then((r) => r.output);
|
|
168
|
-
}
|
|
169
|
-
// MARK: Return response
|
|
170
|
-
// NOTE: try directly with the requestPonyfill. This might not be necessary
|
|
171
|
-
if (assert.isResponseOrPatchedResponse(output)) {
|
|
172
|
-
const redirect = isRedirect(output);
|
|
173
|
-
if (redirect?.location)
|
|
174
|
-
return {
|
|
175
|
-
response: Response.redirect(redirect.location, output.status),
|
|
176
|
-
};
|
|
177
|
-
return { response: output };
|
|
178
|
-
// MARK: Stream page render
|
|
179
|
-
}
|
|
180
|
-
// MARK: Page stream error
|
|
181
|
-
if (output instanceof Readable) {
|
|
182
|
-
responseInit.headers = {
|
|
183
|
-
...responseInit.headers,
|
|
184
|
-
...CONTENT_TYPE_HTML,
|
|
185
|
-
};
|
|
186
|
-
return {
|
|
187
|
-
body: output.on('error', (error) => {
|
|
188
|
-
const errorMessage = `[SSR Error] There was an error while rendering a template chunk on server-side.\n` +
|
|
189
|
-
`It was omitted from the resulting HTML.\n`;
|
|
190
|
-
if (vite) {
|
|
191
|
-
logger.error(errorMessage + error.stack);
|
|
192
|
-
// emitViteBetterError(new GracileError(GracileErrorData.FailedToGlobalLogger), vite);
|
|
193
|
-
const payload = {
|
|
194
|
-
type: 'error',
|
|
195
|
-
// FIXME: Use the emitViteBetterError instead (but flaky for now with streaming)
|
|
196
|
-
// err: new GracileError({}),
|
|
197
|
-
err: {
|
|
198
|
-
name: 'StreamingError',
|
|
199
|
-
message: errorMessage,
|
|
200
|
-
stack: error.stack,
|
|
201
|
-
hint: 'This is often caused by a wrong template location dynamic interpolation.',
|
|
202
|
-
cause: error,
|
|
203
|
-
// highlightedCode: error.message,
|
|
204
|
-
},
|
|
205
|
-
};
|
|
206
|
-
//
|
|
207
|
-
setTimeout(() => {
|
|
208
|
-
// @ts-expect-error ...........
|
|
209
|
-
vite.hot.send(payload);
|
|
210
|
-
// NOTE: Arbitrary value. Lower seems to be too fast, higher is not guaranteed to work.
|
|
211
|
-
}, 200);
|
|
212
|
-
}
|
|
213
|
-
else {
|
|
214
|
-
logger.error(errorMessage);
|
|
215
|
-
}
|
|
216
|
-
}),
|
|
217
|
-
init: responseInit,
|
|
218
|
-
};
|
|
77
|
+
// MARK: 5. Template-only render (no handler)
|
|
78
|
+
const renderResult = await renderWithoutHandler({
|
|
79
|
+
premises,
|
|
80
|
+
routeTemplateOptions,
|
|
81
|
+
});
|
|
82
|
+
if (renderResult && 'response' in renderResult)
|
|
83
|
+
return renderResult;
|
|
84
|
+
output = renderResult;
|
|
219
85
|
}
|
|
220
|
-
|
|
86
|
+
// MARK: 6. Build final response
|
|
87
|
+
return buildResponse({ output, responseInit, vite, logger });
|
|
221
88
|
// MARK: Errors
|
|
222
89
|
}
|
|
223
90
|
catch (error) {
|
|
224
|
-
// const safeError = createSafeError(error);
|
|
225
|
-
// TODO: User defined dev/runtime 500 error
|
|
226
91
|
const ultimateErrorPage = vite && emitViteBetterError
|
|
227
92
|
? await emitViteBetterError({ vite, error: error })
|
|
228
93
|
: await renderLitTemplate(builtInErrorPage(error.name));
|
|
@@ -237,3 +102,25 @@ export function createGracileHandler({ vite, routes, routeImports, routeAssets,
|
|
|
237
102
|
};
|
|
238
103
|
return middleware;
|
|
239
104
|
}
|
|
105
|
+
// MARK: Run user middleware
|
|
106
|
+
// NOTE: Experimental
|
|
107
|
+
/// eslint-disable-next-line no-inner-declarations
|
|
108
|
+
// async function useHandler() {}
|
|
109
|
+
// if (vite) {
|
|
110
|
+
// const middleware = await vite
|
|
111
|
+
// .ssrLoadModule('/src/middleware.ts')
|
|
112
|
+
// .catch(() => null)
|
|
113
|
+
// .then((m) => m.default);
|
|
114
|
+
// if (middleware)
|
|
115
|
+
// await middleware(
|
|
116
|
+
// routeContext,
|
|
117
|
+
// async () => {
|
|
118
|
+
// await useHandler();
|
|
119
|
+
// },
|
|
120
|
+
// );
|
|
121
|
+
// else await useHandler();
|
|
122
|
+
// } else {
|
|
123
|
+
// await useHandler();
|
|
124
|
+
// }
|
|
125
|
+
//
|
|
126
|
+
export { isRedirect, } from './request-pipeline.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/test/init.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Side-effect import: initializes the Gracile logger globally.
|
|
3
|
+
* Import this at the top of any engine unit test that touches modules
|
|
4
|
+
* which call `getLogger()` at module scope.
|
|
5
|
+
*/
|
|
6
|
+
import { createLogger } from '@gracile/internal-utils/logger/helpers';
|
|
7
|
+
createLogger();
|
package/dist/user-config.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RenderInfo } from '@lit-labs/ssr';
|
|
1
2
|
import type { Connect } from 'vite';
|
|
2
3
|
/**
|
|
3
4
|
* @example
|
|
@@ -93,6 +94,40 @@ export interface GracileConfig {
|
|
|
93
94
|
exclude?: string[];
|
|
94
95
|
};
|
|
95
96
|
};
|
|
97
|
+
litSsr?: {
|
|
98
|
+
/**
|
|
99
|
+
* Lets you extend Gracile's SSR pipeline with
|
|
100
|
+
* custom Lit SSR `ElementRenderer` subclasses. This is the foundation for
|
|
101
|
+
* features like [Islands](/docs/add-ons/islands/), which register a renderer
|
|
102
|
+
* for the `<is-land>` custom element to server-render components from other
|
|
103
|
+
* UI frameworks.
|
|
104
|
+
*
|
|
105
|
+
* In most cases, you do **not** set this option manually — add-on plugins
|
|
106
|
+
* (like `gracileIslands()`) register their renderers automatically via the
|
|
107
|
+
* plugin context communication channel. However,
|
|
108
|
+
* you can use it directly for advanced use cases:
|
|
109
|
+
*
|
|
110
|
+
* ```ts
|
|
111
|
+
* import { gracile } from '@gracile/gracile/plugin';
|
|
112
|
+
* import { defineConfig } from 'vite';
|
|
113
|
+
*
|
|
114
|
+
* export default defineConfig({
|
|
115
|
+
* plugins: [
|
|
116
|
+
* gracile({
|
|
117
|
+
* litSsr: {
|
|
118
|
+
* renderInfo: {
|
|
119
|
+
* elementRenderers: [
|
|
120
|
+
* // Your custom ElementRenderer subclass
|
|
121
|
+
* ],
|
|
122
|
+
* },
|
|
123
|
+
* },
|
|
124
|
+
* }),
|
|
125
|
+
* ],
|
|
126
|
+
* });
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
renderInfo?: Partial<RenderInfo>;
|
|
130
|
+
};
|
|
96
131
|
/**
|
|
97
132
|
* Future, unstable features flags.
|
|
98
133
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-config.d.ts","sourceRoot":"","sources":["../src/user-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,WAAW,aAAa;IAC7B;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAE7B;;OAEG;IACH,GAAG,CAAC,EAAE;QACL;;;;;WAKG;QACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE;YAAE,WAAW,EAAE,OAAO,CAAC,eAAe,CAAA;SAAE,KAAK,OAAO,CAAC;KACxE,CAAC;IAEF;;OAEG;IACH,MAAM,CAAC,EAAE;QACR;;WAEG;QACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;IAEF;;OAEG;IACH,KAAK,CAAC,EAAE;QACP;;;;;;;;;;;;;WAaG;QACH,QAAQ,CAAC,EAAE;YACV;;eAEG;YACH,MAAM,CAAC,EAAE,OAAO,CAAC;YAGjB;;eAEG;YACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;YAEnB;;eAEG;YACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;SACnB,CAAC;KACF,CAAC;IAEF;;OAEG;IACH,YAAY,CAAC,EAAE;QACd;;;WAGG;QACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;KAOhC,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"user-config.d.ts","sourceRoot":"","sources":["../src/user-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,WAAW,aAAa;IAC7B;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAE7B;;OAEG;IACH,GAAG,CAAC,EAAE;QACL;;;;;WAKG;QACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE;YAAE,WAAW,EAAE,OAAO,CAAC,eAAe,CAAA;SAAE,KAAK,OAAO,CAAC;KACxE,CAAC;IAEF;;OAEG;IACH,MAAM,CAAC,EAAE;QACR;;WAEG;QACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;IAEF;;OAEG;IACH,KAAK,CAAC,EAAE;QACP;;;;;;;;;;;;;WAaG;QACH,QAAQ,CAAC,EAAE;YACV;;eAEG;YACH,MAAM,CAAC,EAAE,OAAO,CAAC;YAGjB;;eAEG;YACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;YAEnB;;eAEG;YACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;SACnB,CAAC;KACF,CAAC;IACF,MAAM,CAAC,EAAE;QACR;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WA8BG;QACH,UAAU,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;KACjC,CAAC;IAEF;;OAEG;IACH,YAAY,CAAC,EAAE;QACd;;;WAGG;QACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;KAOhC,CAAC;CACF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vite plugin: client-side build configuration.
|
|
3
|
+
*
|
|
4
|
+
* During `vite build`, this spins up a temporary dev server to render
|
|
5
|
+
* all routes into static HTML, then configures Rollup with the
|
|
6
|
+
* generated HTML pages as inputs.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
import { type PluginOption } from 'vite';
|
|
11
|
+
import type { PluginSharedState } from './plugin-shared-state.js';
|
|
12
|
+
export declare function gracileClientBuildPlugin({ state, virtualRoutesForClient, }: {
|
|
13
|
+
state: PluginSharedState;
|
|
14
|
+
virtualRoutesForClient: PluginOption;
|
|
15
|
+
}): PluginOption;
|
|
16
|
+
//# sourceMappingURL=plugin-client-build.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-client-build.d.ts","sourceRoot":"","sources":["../../src/vite/plugin-client-build.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,MAAM,CAAC;AAGvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,wBAAgB,wBAAwB,CAAC,EACxC,KAAK,EACL,sBAAsB,GACtB,EAAE;IACF,KAAK,EAAE,iBAAiB,CAAC;IACzB,sBAAsB,EAAE,YAAY,CAAC;CACrC,GAAG,YAAY,CAkDf"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vite plugin: client-side build configuration.
|
|
3
|
+
*
|
|
4
|
+
* During `vite build`, this spins up a temporary dev server to render
|
|
5
|
+
* all routes into static HTML, then configures Rollup with the
|
|
6
|
+
* generated HTML pages as inputs.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
import { getPluginContext } from '@gracile/internal-utils/plugin-context';
|
|
12
|
+
import { createServer } from 'vite';
|
|
13
|
+
import { buildRoutes } from './build-routes.js';
|
|
14
|
+
export function gracileClientBuildPlugin({ state, virtualRoutesForClient, }) {
|
|
15
|
+
return {
|
|
16
|
+
name: 'vite-plugin-gracile-build',
|
|
17
|
+
apply: 'build',
|
|
18
|
+
async config(viteConfig) {
|
|
19
|
+
const viteServerForClientHtmlBuild = await createServer({
|
|
20
|
+
root: viteConfig.root || process.cwd(),
|
|
21
|
+
server: { middlewareMode: true },
|
|
22
|
+
// NOTE: Stub. KEEP IT!
|
|
23
|
+
optimizeDeps: { include: [] },
|
|
24
|
+
plugins: [virtualRoutesForClient],
|
|
25
|
+
});
|
|
26
|
+
// NOTE: Important. Get the dev. server elements renderers.
|
|
27
|
+
state.gracileConfig.litSsr ??= {};
|
|
28
|
+
state.gracileConfig.litSsr.renderInfo = getPluginContext(viteServerForClientHtmlBuild.config)?.litSsrRenderInfo;
|
|
29
|
+
const htmlPages = await buildRoutes({
|
|
30
|
+
viteServerForBuild: viteServerForClientHtmlBuild,
|
|
31
|
+
root: viteConfig.root || process.cwd(),
|
|
32
|
+
gracileConfig: state.gracileConfig,
|
|
33
|
+
serverMode: state.outputMode === 'server',
|
|
34
|
+
routes: state.routes,
|
|
35
|
+
});
|
|
36
|
+
state.renderedRoutes = htmlPages.renderedRoutes;
|
|
37
|
+
await viteServerForClientHtmlBuild.close();
|
|
38
|
+
return {
|
|
39
|
+
build: {
|
|
40
|
+
rollupOptions: {
|
|
41
|
+
input: htmlPages.inputList,
|
|
42
|
+
plugins: [htmlPages.plugin],
|
|
43
|
+
},
|
|
44
|
+
outDir: join(viteConfig.build?.outDir || 'dist', state.outputMode === 'server' ? 'client' : ''),
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vite plugin: development server middleware.
|
|
3
|
+
*
|
|
4
|
+
* Sets up the Gracile request handler, route watcher, and dev-time
|
|
5
|
+
* logging for `vite dev`.
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
import type { Logger, PluginOption } from 'vite';
|
|
10
|
+
import type { GracileConfig } from '../user-config.js';
|
|
11
|
+
import type { PluginSharedState } from './plugin-shared-state.js';
|
|
12
|
+
export declare function gracileServePlugin({ state, config, logger, resetClientBuiltFlag, }: {
|
|
13
|
+
state: PluginSharedState;
|
|
14
|
+
config: GracileConfig | undefined;
|
|
15
|
+
logger: Logger;
|
|
16
|
+
resetClientBuiltFlag: () => void;
|
|
17
|
+
}): PluginOption;
|
|
18
|
+
//# sourceMappingURL=plugin-serve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-serve.d.ts","sourceRoot":"","sources":["../../src/vite/plugin-serve.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAIjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,wBAAgB,kBAAkB,CAAC,EAClC,KAAK,EACL,MAAM,EACN,MAAM,EACN,oBAAoB,GACpB,EAAE;IACF,KAAK,EAAE,iBAAiB,CAAC;IACzB,MAAM,EAAE,aAAa,GAAG,SAAS,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB,EAAE,MAAM,IAAI,CAAC;CACjC,GAAG,YAAY,CA6Df"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vite plugin: development server middleware.
|
|
3
|
+
*
|
|
4
|
+
* Sets up the Gracile request handler, route watcher, and dev-time
|
|
5
|
+
* logging for `vite dev`.
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
import { getVersion } from '@gracile/internal-utils/version';
|
|
10
|
+
import c from 'picocolors';
|
|
11
|
+
import { createDevelopmentHandler } from '../dev/development.js';
|
|
12
|
+
import { nodeAdapter } from '../server/adapters/node.js';
|
|
13
|
+
export function gracileServePlugin({ state, config, logger, resetClientBuiltFlag, }) {
|
|
14
|
+
return {
|
|
15
|
+
name: 'vite-plugin-gracile-serve-middleware',
|
|
16
|
+
apply: 'serve',
|
|
17
|
+
config(_, environment) {
|
|
18
|
+
if (environment.isPreview)
|
|
19
|
+
return null;
|
|
20
|
+
return {
|
|
21
|
+
// NOTE: Supresses message: `Could not auto-determine entry point from rollupOptions or html files…`
|
|
22
|
+
// FIXME: It's not working when reloading the Vite config.
|
|
23
|
+
// Is user config, putting `optimizeDeps: { include: [] }` solve this.
|
|
24
|
+
optimizeDeps: { include: [] },
|
|
25
|
+
// NOTE: Useful? It breaks preview (expected)
|
|
26
|
+
appType: 'custom',
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
async configureServer(server) {
|
|
30
|
+
// HACK: We know we are in dev here, this will prevent incorrect
|
|
31
|
+
// vite.config hot reloading. Will be removed when adopting env. API.
|
|
32
|
+
resetClientBuiltFlag();
|
|
33
|
+
const version = getVersion();
|
|
34
|
+
logger.info(`${c.cyan(c.italic(c.underline('🧚 Gracile')))}` +
|
|
35
|
+
` ${c.dim(`~`)} ${c.green(`v${version ?? 'X'}`)}`);
|
|
36
|
+
const { handler } = await createDevelopmentHandler({
|
|
37
|
+
routes: state.routes,
|
|
38
|
+
vite: server,
|
|
39
|
+
gracileConfig: state.gracileConfig,
|
|
40
|
+
});
|
|
41
|
+
logger.info(c.dim('Vite development server is starting…'), {
|
|
42
|
+
timestamp: true,
|
|
43
|
+
});
|
|
44
|
+
server.watcher.on('ready', () => {
|
|
45
|
+
setTimeout(() => {
|
|
46
|
+
logger.info('');
|
|
47
|
+
logger.info(c.green('Watching for file changes…'), {
|
|
48
|
+
timestamp: true,
|
|
49
|
+
});
|
|
50
|
+
logger.info('');
|
|
51
|
+
// NOTE: We want it to show after the Vite intro stuff
|
|
52
|
+
}, 100);
|
|
53
|
+
});
|
|
54
|
+
return () => {
|
|
55
|
+
server.middlewares.use((request, response, next) => {
|
|
56
|
+
const locals = config?.dev?.locals?.({ nodeRequest: request });
|
|
57
|
+
Promise.resolve(nodeAdapter(handler, { logger })(request, response, locals)).catch((error) => next(error));
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vite plugins: server-side build pipeline.
|
|
3
|
+
*
|
|
4
|
+
* After the client build completes, these plugins run a nested
|
|
5
|
+
* `vite build` in SSR mode to produce the server entrypoint.
|
|
6
|
+
*
|
|
7
|
+
* Includes:
|
|
8
|
+
* - Client asset filename collector (from the client writeBundle)
|
|
9
|
+
* - Server build trigger (closeBundle)
|
|
10
|
+
* - Virtual entrypoint codegen
|
|
11
|
+
* - Server-to-client asset mover
|
|
12
|
+
*
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
import { type PluginOption } from 'vite';
|
|
16
|
+
import type { PluginSharedState } from './plugin-shared-state.js';
|
|
17
|
+
/**
|
|
18
|
+
* Tracks client bundle assets so the server build can reference them
|
|
19
|
+
* with their hashed filenames.
|
|
20
|
+
*/
|
|
21
|
+
export declare function gracileCollectClientAssetsPlugin({ state, }: {
|
|
22
|
+
state: PluginSharedState;
|
|
23
|
+
}): PluginOption;
|
|
24
|
+
/**
|
|
25
|
+
* After the client build finishes (`closeBundle`), run a nested SSR
|
|
26
|
+
* build that produces the server entrypoint and moves assets back into
|
|
27
|
+
* the client output directory.
|
|
28
|
+
*/
|
|
29
|
+
export declare function gracileServerBuildPlugin({ state, virtualRoutesForClient, }: {
|
|
30
|
+
state: PluginSharedState;
|
|
31
|
+
virtualRoutesForClient: PluginOption;
|
|
32
|
+
}): PluginOption;
|
|
33
|
+
//# sourceMappingURL=plugin-server-build.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-server-build.d.ts","sourceRoot":"","sources":["../../src/vite/plugin-server-build.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,MAAM,CAAC;AAGhD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAIlE;;;GAGG;AACH,wBAAgB,gCAAgC,CAAC,EAChD,KAAK,GACL,EAAE;IACF,KAAK,EAAE,iBAAiB,CAAC;CACzB,GAAG,YAAY,CAYf;AAID;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,EACxC,KAAK,EACL,sBAAsB,GACtB,EAAE;IACF,KAAK,EAAE,iBAAiB,CAAC;IACzB,sBAAsB,EAAE,YAAY,CAAC;CACrC,GAAG,YAAY,CAqEf"}
|