@solidjs/start 2.0.0-beta.6 → 2.0.0-beta.8
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/CHANGELOG.md +13 -0
- package/dist/config/dev-server.d.ts +1 -1
- package/dist/config/dev-server.js +2 -2
- package/dist/config/env.js +5 -4
- package/dist/config/index.js +4 -4
- package/dist/directives/index.js +39 -7
- package/dist/fns/handler.js +27 -2
- package/dist/fns/registration.d.ts +2 -1
- package/dist/fns/registration.js +4 -1
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @solidjs/start
|
|
2
2
|
|
|
3
|
+
## 2.0.0-beta.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- ecc02be: fix: resolve server functions in dev when their route was reached through client-side navigation before its module was evaluated on the server
|
|
8
|
+
- 85b24b2: Use per-environment Vite plugin hook APIs for forward compatibility with Vite 9.
|
|
9
|
+
|
|
10
|
+
## 2.0.0-beta.7
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- d2f0621: Support JavaScript projects whose app and client/server entries use `.jsx`.
|
|
15
|
+
|
|
3
16
|
## 2.0.0-beta.6
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { type PluginOption } from "vite";
|
|
2
|
-
export declare function devServer(): Array<PluginOption>;
|
|
2
|
+
export declare function devServer(serverEntryPath: string): Array<PluginOption>;
|
|
3
3
|
export declare function resolvePreviewServerEntry(root: string): string;
|
|
4
4
|
export declare function isHtmlResponse(response: Response): boolean;
|
|
@@ -12,7 +12,7 @@ import { pathToFileURL } from "node:url";
|
|
|
12
12
|
import { NodeRequest, sendNodeResponse } from "srvx/node";
|
|
13
13
|
import { isRunnableDevEnvironment, } from "vite";
|
|
14
14
|
import { VITE_ENVIRONMENTS } from "./constants.js";
|
|
15
|
-
export function devServer() {
|
|
15
|
+
export function devServer(serverEntryPath) {
|
|
16
16
|
return [
|
|
17
17
|
{
|
|
18
18
|
name: "solid-start-dev-server",
|
|
@@ -54,7 +54,7 @@ export function devServer() {
|
|
|
54
54
|
}
|
|
55
55
|
const webReq = new NodeRequest({ req, res });
|
|
56
56
|
try {
|
|
57
|
-
const serverEntry = await serverEnv.runner.import(
|
|
57
|
+
const serverEntry = await serverEnv.runner.import(serverEntryPath);
|
|
58
58
|
const webRes = await serverEntry.default.fetch(webReq);
|
|
59
59
|
return sendNodeResponse(res, webRes);
|
|
60
60
|
}
|
package/dist/config/env.js
CHANGED
|
@@ -47,9 +47,10 @@ export function envPlugin(options) {
|
|
|
47
47
|
}
|
|
48
48
|
return undefined;
|
|
49
49
|
},
|
|
50
|
-
load(id
|
|
50
|
+
load(id) {
|
|
51
|
+
const isServer = this.environment.config.consumer === "server";
|
|
51
52
|
if (id === SERVER_ENV) {
|
|
52
|
-
if (!
|
|
53
|
+
if (!isServer) {
|
|
53
54
|
return SERVER_ONLY_MODULE;
|
|
54
55
|
}
|
|
55
56
|
const vars = currentOptions.server?.load
|
|
@@ -64,13 +65,13 @@ export function envPlugin(options) {
|
|
|
64
65
|
return convertObjectToModule(vars);
|
|
65
66
|
}
|
|
66
67
|
if (id === SERVER_RUNTIME_LOADER) {
|
|
67
|
-
if (!
|
|
68
|
+
if (!isServer) {
|
|
68
69
|
return SERVER_ONLY_MODULE;
|
|
69
70
|
}
|
|
70
71
|
return runtimeCode;
|
|
71
72
|
}
|
|
72
73
|
if (id === SERVER_RUNTIME_ENV) {
|
|
73
|
-
if (!
|
|
74
|
+
if (!isServer) {
|
|
74
75
|
return SERVER_ONLY_MODULE;
|
|
75
76
|
}
|
|
76
77
|
return SERVER_RUNTIME_CODE;
|
package/dist/config/index.js
CHANGED
|
@@ -44,8 +44,8 @@ export function solidStart(options) {
|
|
|
44
44
|
serverFunctionsPlugin({
|
|
45
45
|
manifest: VIRTUAL_MODULES.serverFnManifest,
|
|
46
46
|
runtime: {
|
|
47
|
-
server:
|
|
48
|
-
client:
|
|
47
|
+
server: "@solidjs/start/fns/server",
|
|
48
|
+
client: "@solidjs/start/fns/client",
|
|
49
49
|
},
|
|
50
50
|
filter: options?.serverFunctions?.filter,
|
|
51
51
|
}),
|
|
@@ -110,7 +110,7 @@ export function solidStart(options) {
|
|
|
110
110
|
manifest: true,
|
|
111
111
|
copyPublicDir: false,
|
|
112
112
|
rollupOptions: {
|
|
113
|
-
input:
|
|
113
|
+
input: handlers.server,
|
|
114
114
|
},
|
|
115
115
|
outDir: "dist/server",
|
|
116
116
|
commonjsOptions: {
|
|
@@ -214,7 +214,7 @@ export function solidStart(options) {
|
|
|
214
214
|
globalThis.START_CLIENT_OUT_DIR = options.dir;
|
|
215
215
|
},
|
|
216
216
|
},
|
|
217
|
-
devServer(),
|
|
217
|
+
devServer(handlers.server),
|
|
218
218
|
solid({
|
|
219
219
|
...start.solid,
|
|
220
220
|
ssr: true,
|
package/dist/directives/index.js
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { createFilter, } from "vite";
|
|
2
|
+
import fg from "fast-glob";
|
|
2
3
|
import { compile } from "./compile.js";
|
|
4
|
+
import xxHash32 from "./xxhash32.js";
|
|
3
5
|
const DEFAULT_INCLUDE = "src/**/*.{jsx,tsx,ts,js,mjs,cjs}";
|
|
4
6
|
const DEFAULT_EXCLUDE = "node_modules/**/*.{jsx,tsx,ts,js,mjs,cjs}";
|
|
5
7
|
const DIRECTIVE = "use server";
|
|
8
|
+
// Dev-only virtual module used by fns/handler.ts to lazily resolve a server
|
|
9
|
+
// function id back to its owning module when the function was never evaluated
|
|
10
|
+
// in the server environment (e.g. its route was only client-side navigated to).
|
|
11
|
+
const LOOKUP_ID = "solid-start:server-fn-lookup";
|
|
6
12
|
function createManifest() {
|
|
7
13
|
return {
|
|
8
14
|
server: new Set(),
|
|
@@ -63,8 +69,11 @@ function invalidateModule(moduleGraph, path) {
|
|
|
63
69
|
function invalidateModules(server, result, manifest) {
|
|
64
70
|
if (server) {
|
|
65
71
|
if (result.invalidPreload) {
|
|
66
|
-
|
|
67
|
-
|
|
72
|
+
// Environments are not limited to "client"/"ssr": plugins like nitro
|
|
73
|
+
// render in their own environment (e.g. "nitro"), so invalidate everywhere.
|
|
74
|
+
for (const environment of Object.values(server.environments)) {
|
|
75
|
+
invalidateModule(environment.moduleGraph, manifest);
|
|
76
|
+
}
|
|
68
77
|
}
|
|
69
78
|
}
|
|
70
79
|
}
|
|
@@ -125,24 +134,47 @@ export function serverFunctionsPlugin(options) {
|
|
|
125
134
|
if (source === options.manifest) {
|
|
126
135
|
return { id: options.manifest, moduleSideEffects: true };
|
|
127
136
|
}
|
|
137
|
+
if (source.startsWith(LOOKUP_ID)) {
|
|
138
|
+
return { id: source, moduleSideEffects: true };
|
|
139
|
+
}
|
|
128
140
|
return null;
|
|
129
141
|
},
|
|
130
|
-
async load(id
|
|
131
|
-
const mode =
|
|
142
|
+
async load(id) {
|
|
143
|
+
const mode = this.environment.config.consumer;
|
|
132
144
|
if (id === options.manifest) {
|
|
133
145
|
const current = new Debouncer(() => [...manifest[mode]].map(entry => `import "${entry}";`).join("\n"));
|
|
134
146
|
preload[mode] = current;
|
|
135
147
|
const result = await current.promise.reference;
|
|
136
148
|
return result;
|
|
137
149
|
}
|
|
150
|
+
if (id.startsWith(LOOKUP_ID)) {
|
|
151
|
+
if (this.environment.mode !== "dev") {
|
|
152
|
+
throw new Error(`${LOOKUP_ID} is only available in dev`);
|
|
153
|
+
}
|
|
154
|
+
const functionId = new URLSearchParams(id.slice(LOOKUP_ID.length + 1)).get("id");
|
|
155
|
+
// dev function ids are `${xxHash32(file)}-${count}-${name}`
|
|
156
|
+
const hash = functionId?.split("-")[0];
|
|
157
|
+
if (!hash)
|
|
158
|
+
return "export {};";
|
|
159
|
+
// Look through the files already discovered by the transform first;
|
|
160
|
+
// fall back to scanning the project so a function is found even when
|
|
161
|
+
// the browser kept a chunk from before a dev server restart.
|
|
162
|
+
let files = [...manifest.server].filter(file => xxHash32(file).toString(16) === hash);
|
|
163
|
+
if (files.length === 0) {
|
|
164
|
+
files = fg
|
|
165
|
+
.sync(DEFAULT_INCLUDE, { cwd: this.environment.config.root, absolute: true })
|
|
166
|
+
.filter(file => filter(file) && xxHash32(file).toString(16) === hash);
|
|
167
|
+
}
|
|
168
|
+
return files.map(file => `import ${JSON.stringify(file)};`).join("\n") || "export {};";
|
|
169
|
+
}
|
|
138
170
|
return null;
|
|
139
171
|
},
|
|
140
172
|
},
|
|
141
173
|
{
|
|
142
174
|
name: "solid-start:server-functions/compiler",
|
|
143
|
-
enforce:
|
|
144
|
-
async transform(code, fileId
|
|
145
|
-
const mode =
|
|
175
|
+
enforce: "pre",
|
|
176
|
+
async transform(code, fileId) {
|
|
177
|
+
const mode = this.environment.config.consumer;
|
|
146
178
|
const [id] = fileId.split("?");
|
|
147
179
|
if (!filter(id)) {
|
|
148
180
|
return null;
|
package/dist/fns/handler.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
1
9
|
import { parseSetCookie } from "cookie-es";
|
|
2
10
|
import { parseCookies } from "h3";
|
|
3
11
|
import { sharedConfig } from "solid-js";
|
|
@@ -6,9 +14,9 @@ import { provideRequestEvent } from "solid-js/web/storage";
|
|
|
6
14
|
import { getFetchEvent, mergeResponseHeaders } from "../server/fetchEvent.js";
|
|
7
15
|
import { createPageEvent } from "../server/handler.js";
|
|
8
16
|
import { deserializeFromJSONString, serializeToJSONStream, serializeToJSStream, } from "./serialization.js";
|
|
9
|
-
import { BODY_FORMAT_KEY, BodyFormat, extractBody, getHeadersAndBody
|
|
17
|
+
import { BODY_FORMAT_KEY, BodyFormat, extractBody, getHeadersAndBody } from "./shared.js";
|
|
10
18
|
import "solid-start:server-fn-manifest";
|
|
11
|
-
import { getServerFunction } from "./registration.js";
|
|
19
|
+
import { getServerFunction, hasServerFunction } from "./registration.js";
|
|
12
20
|
import { getExpectedRedirectStatus } from "../server/util.js";
|
|
13
21
|
export async function handleServerFunction(h3Event) {
|
|
14
22
|
const event = getFetchEvent(h3Event);
|
|
@@ -30,6 +38,23 @@ export async function handleServerFunction(h3Event) {
|
|
|
30
38
|
: new Response(null, { status: 404 });
|
|
31
39
|
}
|
|
32
40
|
}
|
|
41
|
+
if (import.meta.env.DEV && !hasServerFunction(functionId)) {
|
|
42
|
+
// The module that owns this function has not been evaluated in the server
|
|
43
|
+
// environment yet (e.g. the route was reached by client-side navigation, so
|
|
44
|
+
// it was only ever loaded in the browser). Ask the dev server to resolve the
|
|
45
|
+
// function id back to its owning module and import it, which registers it.
|
|
46
|
+
// Resolved by the "solid-start:server-functions/preload" plugin.
|
|
47
|
+
try {
|
|
48
|
+
// the /@id/ prefix routes the request through the plugin container so the
|
|
49
|
+
// virtual module can be resolved (bare ids get node-resolved by the runner)
|
|
50
|
+
await import(__rewriteRelativeImportExtension(
|
|
51
|
+
/* @vite-ignore */ `/@id/solid-start:server-fn-lookup?id=${encodeURIComponent(functionId)}`, true));
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
// fall through to getServerFunction, which reports the missing function
|
|
55
|
+
console.error("[solid-start] server function lookup failed:", error);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
33
58
|
const serverFunction = getServerFunction(functionId);
|
|
34
59
|
let parsed = [];
|
|
35
60
|
// grab bound arguments from url when no JS
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export declare function registerServerFunction<T extends any[], R>(id: string, callback: (...args: T) => Promise<R>): (...args: T) => Promise<R>;
|
|
2
|
-
export declare function
|
|
2
|
+
export declare function hasServerFunction(id: string): boolean;
|
|
3
|
+
export declare function getServerFunction<T extends any[], R>(id: string): (...args: T) => Promise<R>;
|
package/dist/fns/registration.js
CHANGED
|
@@ -3,10 +3,13 @@ export function registerServerFunction(id, callback) {
|
|
|
3
3
|
REGISTRATIONS.set(id, callback);
|
|
4
4
|
return callback;
|
|
5
5
|
}
|
|
6
|
+
export function hasServerFunction(id) {
|
|
7
|
+
return REGISTRATIONS.has(id);
|
|
8
|
+
}
|
|
6
9
|
export function getServerFunction(id) {
|
|
7
10
|
const fn = REGISTRATIONS.get(id);
|
|
8
11
|
if (fn) {
|
|
9
12
|
return fn;
|
|
10
13
|
}
|
|
11
|
-
throw new Error(
|
|
14
|
+
throw new Error("invalid server function: " + id);
|
|
12
15
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidjs/start",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -66,13 +66,14 @@
|
|
|
66
66
|
"vitest": "^4.1.0"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
|
-
"vite": "^8"
|
|
69
|
+
"vite": "^8 || ^9"
|
|
70
70
|
},
|
|
71
71
|
"scripts": {
|
|
72
72
|
"build": "pnpm validate-imports && tsc && node scripts/build.js",
|
|
73
73
|
"dev": "tsc --watch",
|
|
74
74
|
"test": "vitest",
|
|
75
75
|
"test:ci": "vitest run",
|
|
76
|
+
"typecheck": "tsc --noEmit",
|
|
76
77
|
"typecheck:dist": "pnpm build && pnpx @arethetypeswrong/cli --pack . --profile esm-only",
|
|
77
78
|
"validate-imports": "node scripts/validate-imports.js"
|
|
78
79
|
}
|