@solidjs/vite-plugin 3.0.0-next.28 → 3.0.0-next.29
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 +21 -0
- package/README.md +56 -1
- package/dist/cjs/index.cjs +85 -10
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.mjs +85 -10
- package/dist/esm/index.mjs.map +1 -1
- package/dist/types/src/ssr/index.d.ts +5 -0
- package/package.json +1 -1
- package/virtual-solid-manifest.d.ts +21 -1
package/dist/esm/index.mjs
CHANGED
|
@@ -910,7 +910,15 @@ function serverFunctions(options = {}, internal = {}) {
|
|
|
910
910
|
// the same value (config merges per key), but the handler graph cannot
|
|
911
911
|
// depend on that: in dev, a mutation from an already-open page can be
|
|
912
912
|
// the first request after a server restart.
|
|
913
|
-
`configureServerFunctionsServer({ provideEvent: provideRequestEvent, endpoint: ${JSON.stringify(resolvedEndpoint)}${components ? ', transformResult: frameTransformResult, transformFlightResult: frameTransformFlightResult, transformDirectResult: frameTransformDirectResult' : ''} });`, `export const endpoint = ${JSON.stringify(resolvedEndpoint)};`,
|
|
913
|
+
`configureServerFunctionsServer({ provideEvent: provideRequestEvent, endpoint: ${JSON.stringify(resolvedEndpoint)}${components ? ', transformResult: frameTransformResult, transformFlightResult: frameTransformFlightResult, transformDirectResult: frameTransformDirectResult' : ''} });`, `export const endpoint = ${JSON.stringify(resolvedEndpoint)};`,
|
|
914
|
+
// `options.event` is the same wrapper->event extension seam the SSR
|
|
915
|
+
// handler's handleRequest carries (conventionally `nativeEvent`, the
|
|
916
|
+
// platform's raw request object). The runtime's standalone handler
|
|
917
|
+
// creates its own event (`{ request, locals }`) with no init
|
|
918
|
+
// parameter, so the extension threads through its existing
|
|
919
|
+
// `createEvent` option instead — spread before `...options` so an
|
|
920
|
+
// explicit host-provided createEvent still wins.
|
|
921
|
+
`export function handleServerFunctionRequest(request, options) {`, ` const { event: eventInit, ...rest } = options || {};`, ` return handle(request, {`, ` provideEvent: provideRequestEvent,`, ` ...(eventInit ? { createEvent: (req) => ({ request: req, locals: {}, ...eventInit }) } : {}),`, ` ...rest,`, ` });`, `}`].join('\n');
|
|
914
922
|
}
|
|
915
923
|
|
|
916
924
|
// Function IDs are `xxHash32(root-relative path)-<count>` (see compile.ts),
|
|
@@ -994,7 +1002,15 @@ function serverFunctions(options = {}, internal = {}) {
|
|
|
994
1002
|
// middleware chain and one stub-backed request event front the
|
|
995
1003
|
// endpoint exactly as they front page SSR.
|
|
996
1004
|
const handler = await server.ssrLoadModule(internal.ssrHandler ?? HANDLER_ID$1);
|
|
997
|
-
|
|
1005
|
+
// Both dispatch shapes carry the raw Node request on the event
|
|
1006
|
+
// (the `options.event` seam), matching the SSR dev middleware
|
|
1007
|
+
// and what a production Node entry passes.
|
|
1008
|
+
const dispatchOptions = {
|
|
1009
|
+
event: {
|
|
1010
|
+
nativeEvent: req
|
|
1011
|
+
}
|
|
1012
|
+
};
|
|
1013
|
+
const response = internal.ssrHandler ? await handler.handleRequest(webRequestFromNode(req, dispatchUrl), dispatchOptions) : await handler.handleServerFunctionRequest(webRequestFromNode(req, dispatchUrl), dispatchOptions);
|
|
998
1014
|
await sendWebResponse(res, response);
|
|
999
1015
|
})().catch(error => {
|
|
1000
1016
|
if (error instanceof Error) server.ssrFixStacktrace(error);
|
|
@@ -1566,7 +1582,14 @@ function startServe(options, internal = {}) {
|
|
|
1566
1582
|
// The runtime's response-head lifecycle: commit at shell flush,
|
|
1567
1583
|
// pre-flush Location as a real redirect, post-flush Location as the
|
|
1568
1584
|
// script fallback; the transform injects the doctype/head pieces.
|
|
1569
|
-
` return createSSRResponse(result, event, {`, ` responseInit: options.responseInit,`, ` nonce: options.nonce,`, ` transformChunk: createHtmlChunkTransform(clientEntry, options.devHead),`, ` });`, `}`, ``, `export async function handleRequest(request, options = {}) {`,
|
|
1585
|
+
` return createSSRResponse(result, event, {`, ` responseInit: options.responseInit,`, ` nonce: options.nonce,`, ` transformChunk: createHtmlChunkTransform(clientEntry, options.devHead),`, ` });`, `}`, ``, `export async function handleRequest(request, options = {}) {`,
|
|
1586
|
+
// `options.event` is the public wrapper->event extension seam: extra
|
|
1587
|
+
// fields (conventionally `nativeEvent`, the platform's raw request
|
|
1588
|
+
// object) spread over the event's defaults at creation, so hosts and
|
|
1589
|
+
// custom server entries can extend what getRequestEvent() answers
|
|
1590
|
+
// with — no new convention beyond createRequestEvent's own init
|
|
1591
|
+
// parameter (spreading undefined is a no-op).
|
|
1592
|
+
` const event = createRequestEvent(request, options.event);`,
|
|
1570
1593
|
// Middleware runs inside the request scope, after event creation —
|
|
1571
1594
|
// getRequestEvent() answers in middleware exactly as in app code, and
|
|
1572
1595
|
// nothing reaches the wire until the outermost middleware returns.
|
|
@@ -1781,7 +1804,14 @@ function startServe(options, internal = {}) {
|
|
|
1781
1804
|
// server-function endpoint) and hands the URL to application
|
|
1782
1805
|
// code, so restore the base — the deployed production handler
|
|
1783
1806
|
// receives base-prefixed URLs and preview must match it.
|
|
1784
|
-
const response = await handler.handleRequest(webRequestFromNode(req, joinBase(base, req.url || '/'))
|
|
1807
|
+
const response = await handler.handleRequest(webRequestFromNode(req, joinBase(base, req.url || '/')),
|
|
1808
|
+
// Same event extension the dev middleware and a production
|
|
1809
|
+
// Node entry pass: the raw Node request as `nativeEvent`.
|
|
1810
|
+
{
|
|
1811
|
+
event: {
|
|
1812
|
+
nativeEvent: req
|
|
1813
|
+
}
|
|
1814
|
+
});
|
|
1785
1815
|
// Preview's compression middleware buffers whole responses;
|
|
1786
1816
|
// opting HTML out keeps SSR streaming observable, matching
|
|
1787
1817
|
// production behavior.
|
|
@@ -1833,7 +1863,14 @@ function startServe(options, internal = {}) {
|
|
|
1833
1863
|
// deployed handler receives base-prefixed requests).
|
|
1834
1864
|
const response = await handler.handleRequest(webRequestFromNode(req, joinBase(base, req.url || '/')), {
|
|
1835
1865
|
devHead,
|
|
1836
|
-
pageRequest
|
|
1866
|
+
pageRequest,
|
|
1867
|
+
// The raw Node request on the event, matching what a
|
|
1868
|
+
// production Node server entry passes through the
|
|
1869
|
+
// `options.event` seam — getRequestEvent().nativeEvent
|
|
1870
|
+
// answers the same in dev as deployed.
|
|
1871
|
+
event: {
|
|
1872
|
+
nativeEvent: req
|
|
1873
|
+
}
|
|
1837
1874
|
});
|
|
1838
1875
|
// A non-page request the chain never handled: the terminal
|
|
1839
1876
|
// dispatch answered with the marked 404 — hand it back to
|
|
@@ -1914,6 +1951,11 @@ function startServe(options, internal = {}) {
|
|
|
1914
1951
|
// time work, secrets rotate without a rebuild, and no secret value exists
|
|
1915
1952
|
// in any dist artifact. Build-time server-value failures downgrade to a
|
|
1916
1953
|
// warning (boot enforces); dev failures stay hard errors — dev IS runtime.
|
|
1954
|
+
// Boot validation is synchronous by design: the generated server module
|
|
1955
|
+
// contains no top-level await (a TLA chunk forces esnext on downstream
|
|
1956
|
+
// bundlers — Nitro's node-server preset rejects it), which is why async
|
|
1957
|
+
// validators are rejected for `server` keys (client keys may stay async;
|
|
1958
|
+
// they are awaited at build time where the values are baked).
|
|
1917
1959
|
//
|
|
1918
1960
|
// A failed validation fails the build; in dev it renders Vite's error
|
|
1919
1961
|
// overlay with the per-key report (the virtual modules throw it on load)
|
|
@@ -2184,7 +2226,23 @@ function startEnv(option) {
|
|
|
2184
2226
|
for (const side of ['server', 'client']) {
|
|
2185
2227
|
for (const [key, validator] of Object.entries(schema[side] ?? {})) {
|
|
2186
2228
|
let result = validator['~standard'].validate(raw[key]);
|
|
2187
|
-
if (result instanceof Promise)
|
|
2229
|
+
if (result instanceof Promise) {
|
|
2230
|
+
// Async validation is fine for `client` keys — their values are
|
|
2231
|
+
// baked right here at build time, where awaiting costs nothing.
|
|
2232
|
+
// `server` keys validate process.env at boot through generated
|
|
2233
|
+
// code that is deliberately synchronous (a top-level await in the
|
|
2234
|
+
// server env chunk forces esnext on every downstream bundle
|
|
2235
|
+
// target — Nitro's node-server preset rejects it outright), so a
|
|
2236
|
+
// Promise-returning server validator could only ever fail at
|
|
2237
|
+
// deploy boot. Async-ness is a property of the schema, not the
|
|
2238
|
+
// value, so fail fast here with the fix in the message. Boot
|
|
2239
|
+
// still backstops (schemas whose sync prefix short-circuits at
|
|
2240
|
+
// build time can go async on real values).
|
|
2241
|
+
if (side === 'server') {
|
|
2242
|
+
throw new Error(`[@solidjs/vite-plugin] server env var "${key}" in ${envFile} uses an async ` + `validator (validate() returned a Promise). Server env is validated ` + `synchronously at boot — the generated module contains no top-level ` + `await, so server bundles work on non-esnext targets — which async ` + `validators cannot do. Make the validator synchronous (drop async ` + `refinements/transforms), or run the async check in application code.`);
|
|
2243
|
+
}
|
|
2244
|
+
result = await result;
|
|
2245
|
+
}
|
|
2188
2246
|
if (result.issues && result.issues.length) {
|
|
2189
2247
|
for (const issue of result.issues) {
|
|
2190
2248
|
const at = (issue.path ?? []).map(segment => typeof segment === 'object' && segment !== null && 'key' in segment ? String(segment.key) : String(segment)).join('.');
|
|
@@ -2261,6 +2319,16 @@ function startEnv(option) {
|
|
|
2261
2319
|
// means. Platform-injected vars that don't exist at build time work,
|
|
2262
2320
|
// secrets rotate without a rebuild, and no secret value exists in any
|
|
2263
2321
|
// dist artifact.
|
|
2322
|
+
//
|
|
2323
|
+
// The generated code is deliberately free of top-level await. Module
|
|
2324
|
+
// init is the only point where "validated and frozen before any
|
|
2325
|
+
// importer's body runs" can be guaranteed — user server modules read
|
|
2326
|
+
// `env.KEY` at their own top level — and the only async thing here is
|
|
2327
|
+
// Standard Schema's option to return a Promise from validate(). A TLA
|
|
2328
|
+
// chunk breaks every downstream bundler with a non-esnext target
|
|
2329
|
+
// (Nitro's node-server preset in practice), so validation runs
|
|
2330
|
+
// synchronously and a Promise-returning server validator is itself a
|
|
2331
|
+
// boot issue (build/config time rejects it earlier when detectable).
|
|
2264
2332
|
function serverEnvModuleCode(loaded) {
|
|
2265
2333
|
const serverKeys = Object.keys(loaded.schema.server ?? {});
|
|
2266
2334
|
const baked = `const __env = ${JSON.stringify(loaded.client)};`;
|
|
@@ -2271,7 +2339,7 @@ function startEnv(option) {
|
|
|
2271
2339
|
};
|
|
2272
2340
|
}
|
|
2273
2341
|
return {
|
|
2274
|
-
code: [`// Generated by @solidjs/vite-plugin (start.env) — server env.`, `// Server values are read from process.env and validated at boot;`, `// client (public) values are baked at build time.`, `import __schema from ${JSON.stringify(envFileAbs)};`, baked, `const __issues = [];`, `for (const __key of ${JSON.stringify(serverKeys)}) {`, `
|
|
2342
|
+
code: [`// Generated by @solidjs/vite-plugin (start.env) — server env.`, `// Server values are read from process.env and validated at boot;`, `// client (public) values are baked at build time. Boot validation is`, `// synchronous on purpose: a top-level await here would force esnext`, `// on every downstream bundle target (Nitro's node-server preset and`, `// anything else below esnext rejects a TLA chunk outright).`, `import __schema from ${JSON.stringify(envFileAbs)};`, baked, `const __issues = [];`, `for (const __key of ${JSON.stringify(serverKeys)}) {`, ` const __result = __schema.server[__key]['~standard'].validate(process.env[__key]);`, ` if (__result && typeof __result.then === 'function') {`, ` __issues.push(' \\u2717 ' + __key + ': validator returned a Promise \\u2014 async validators are not supported for server keys (boot validation is synchronous so the server bundle carries no top-level await); make this validator synchronous');`, ` } else if (__result.issues && __result.issues.length) {`, ` for (const __issue of __result.issues) __issues.push(' \\u2717 ' + __key + ': ' + __issue.message);`, ` } else {`, ` __env[__key] = __result.value;`, ` }`, `}`, `if (__issues.length) {`, ` throw new Error(`, ` '[@solidjs/vite-plugin] server env validation failed at boot (' + __issues.length +`, ` ' issue' + (__issues.length === 1 ? '' : 's') + ') \\u2014 schema: ' + ${JSON.stringify(envFile)} +`, ` '\\n\\n' + __issues.join('\\n') +`, ` '\\n\\nServer env is read from process.env at boot, not baked at build time: set the ' +`, ` 'variables in the server process environment.'`, ` );`, `}`, `export const env = Object.freeze(__env);`, `export default env;`].join('\n'),
|
|
2275
2343
|
moduleType: 'js'
|
|
2276
2344
|
};
|
|
2277
2345
|
}
|
|
@@ -2947,12 +3015,19 @@ function solidPlugin(options = {}) {
|
|
|
2947
3015
|
exclude: solidPkgsConfig.optimizeDeps.exclude,
|
|
2948
3016
|
// Vite 8+ uses Rolldown for dependency scanning. Rolldown defaults to
|
|
2949
3017
|
// React's automatic JSX runtime for .tsx files, injecting a
|
|
2950
|
-
// react/jsx-dev-runtime import
|
|
2951
|
-
//
|
|
3018
|
+
// react/jsx-dev-runtime import that fails to resolve and aborts the
|
|
3019
|
+
// scan. 'preserve' is no fix: the scanner re-parses the transformed
|
|
3020
|
+
// output as plain JS, so any preserved JSX is a hard parse error
|
|
3021
|
+
// (issue #262). The classic runtime is the only scan-safe lowering:
|
|
3022
|
+
// it emits bare `React.createElement` calls without injecting any
|
|
3023
|
+
// import, and the scan output is never executed — it only exists so
|
|
3024
|
+
// rolldown can walk the import graph.
|
|
2952
3025
|
...(isVite8 ? {
|
|
2953
3026
|
rolldownOptions: {
|
|
2954
3027
|
transform: {
|
|
2955
|
-
jsx:
|
|
3028
|
+
jsx: {
|
|
3029
|
+
runtime: 'classic'
|
|
3030
|
+
}
|
|
2956
3031
|
}
|
|
2957
3032
|
}
|
|
2958
3033
|
} : {})
|