From d7c38e705ddc5a13d74096eed86aaab0870320a3 Mon Sep 17 00:00:00 2001
From: thinkeW <863093879@qq.com>
Date: Thu, 27 Mar 2025 15:27:33 +0800
Subject: [PATCH 1/5] feat:encode sfn > functionId & extractedFilename
---
packages/start/config/index.js | 23 +++++++++++++++++---
packages/start/src/runtime/server-handler.ts | 7 +++++-
2 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/packages/start/config/index.js b/packages/start/config/index.js
index 64f5497ee..2421b6b17 100644
--- a/packages/start/config/index.js
+++ b/packages/start/config/index.js
@@ -37,6 +37,23 @@ function solidStartServerFsRouter(config) {
);
}
+/**
+ * @param {string} filepath
+ * @returns {string}
+ */
+function convertToRelativePath(filepath) {
+ const arr = filepath.split("/src/");
+ return arr[1] ? `~/${arr[1]}` : filepath;
+}
+
+/** encode string, here to base64
+ * @param {string} str
+ * @returns {string}
+ */
+function encodeString(str) {
+ return btoa(encodeURIComponent(str));
+}
+
const SolidStartServerFnsPlugin = createTanStackServerFnPlugin({
// This is the ID that will be available to look up and import
// our server function manifest and resolve its module
@@ -47,7 +64,7 @@ const SolidStartServerFnsPlugin = createTanStackServerFnPlugin({
fileURLToPath(new URL("../dist/runtime/server-runtime.js", import.meta.url))
)}"`,
replacer: opts =>
- `createServerReference(${() => {}}, '${opts.functionId}', '${opts.extractedFilename}')`
+ `createServerReference(${() => {}}, '${encodeString(opts.functionId)}', '${encodeString(convertToRelativePath(opts.extractedFilename))}')`
},
ssr: {
getRuntimeCode: () =>
@@ -55,7 +72,7 @@ const SolidStartServerFnsPlugin = createTanStackServerFnPlugin({
fileURLToPath(new URL("../dist/runtime/server-fns-runtime.js", import.meta.url))
)}'`,
replacer: opts =>
- `createServerReference(${opts.fn}, '${opts.functionId}', '${opts.extractedFilename}')`
+ `createServerReference(${opts.fn}, '${encodeString(opts.functionId)}', '${encodeString(convertToRelativePath(opts.extractedFilename))}')`
},
server: {
getRuntimeCode: () =>
@@ -63,7 +80,7 @@ const SolidStartServerFnsPlugin = createTanStackServerFnPlugin({
fileURLToPath(new URL("../dist/runtime/server-fns-runtime.js", import.meta.url))
)}'`,
replacer: opts =>
- `createServerReference(${opts.fn}, '${opts.functionId}', '${opts.extractedFilename}')`
+ `createServerReference(${opts.fn}, '${encodeString(opts.functionId)}', '${encodeString(convertToRelativePath(opts.extractedFilename))}')`
}
});
diff --git a/packages/start/src/runtime/server-handler.ts b/packages/start/src/runtime/server-handler.ts
index 46e1603c5..5d2c2eca6 100644
--- a/packages/start/src/runtime/server-handler.ts
+++ b/packages/start/src/runtime/server-handler.ts
@@ -78,6 +78,11 @@ function serializeToStream(id: string, value: any) {
});
}
+/** decode string, here to base64 */
+function decodeString(str?: string) {
+ return str ? decodeURIComponent(atob(str)) : str;
+}
+
async function handleServerFunction(h3Event: HTTPEvent) {
const event = getFetchEvent(h3Event);
const request = event.request;
@@ -100,7 +105,7 @@ async function handleServerFunction(h3Event: HTTPEvent) {
: new Response(null, { status: 404 });
}
}
-
+ functionId = decodeString(functionId);
const serverFnInfo = serverFnManifest[functionId];
let fnModule: undefined | { [key: string]: any };
From 0d3ca23b84b7669bf52a6c851ca8c603fe48343e Mon Sep 17 00:00:00 2001
From: thinkeW <863093879@qq.com>
Date: Fri, 28 Mar 2025 15:24:02 +0800
Subject: [PATCH 2/5] feat:hash encode sfn > functionId
---
packages/start/config/index.js | 11 +++---
packages/start/src/runtime/server-handler.ts | 37 +++++++++++++++++---
2 files changed, 38 insertions(+), 10 deletions(-)
diff --git a/packages/start/config/index.js b/packages/start/config/index.js
index 2421b6b17..c721f848f 100644
--- a/packages/start/config/index.js
+++ b/packages/start/config/index.js
@@ -1,5 +1,6 @@
import { createTanStackServerFnPlugin } from "@tanstack/server-functions-plugin";
import defu from "defu";
+import { createHash } from "node:crypto";
import { existsSync } from "node:fs";
import { join } from "node:path";
import { fileURLToPath } from "node:url";
@@ -46,12 +47,12 @@ function convertToRelativePath(filepath) {
return arr[1] ? `~/${arr[1]}` : filepath;
}
-/** encode string, here to base64
+/** encode string, here to sha256 hash
* @param {string} str
* @returns {string}
*/
function encodeString(str) {
- return btoa(encodeURIComponent(str));
+ return createHash("sha256").update(str).digest("hex");
}
const SolidStartServerFnsPlugin = createTanStackServerFnPlugin({
@@ -64,7 +65,7 @@ const SolidStartServerFnsPlugin = createTanStackServerFnPlugin({
fileURLToPath(new URL("../dist/runtime/server-runtime.js", import.meta.url))
)}"`,
replacer: opts =>
- `createServerReference(${() => {}}, '${encodeString(opts.functionId)}', '${encodeString(convertToRelativePath(opts.extractedFilename))}')`
+ `createServerReference(${() => {}}, '${encodeString(opts.functionId)}', '${encodeURIComponent(convertToRelativePath(opts.extractedFilename))}')`
},
ssr: {
getRuntimeCode: () =>
@@ -72,7 +73,7 @@ const SolidStartServerFnsPlugin = createTanStackServerFnPlugin({
fileURLToPath(new URL("../dist/runtime/server-fns-runtime.js", import.meta.url))
)}'`,
replacer: opts =>
- `createServerReference(${opts.fn}, '${encodeString(opts.functionId)}', '${encodeString(convertToRelativePath(opts.extractedFilename))}')`
+ `createServerReference(${opts.fn}, '${encodeString(opts.functionId)}', '${encodeURIComponent(convertToRelativePath(opts.extractedFilename))}')`
},
server: {
getRuntimeCode: () =>
@@ -80,7 +81,7 @@ const SolidStartServerFnsPlugin = createTanStackServerFnPlugin({
fileURLToPath(new URL("../dist/runtime/server-fns-runtime.js", import.meta.url))
)}'`,
replacer: opts =>
- `createServerReference(${opts.fn}, '${encodeString(opts.functionId)}', '${encodeString(convertToRelativePath(opts.extractedFilename))}')`
+ `createServerReference(${opts.fn}, '${encodeString(opts.functionId)}', '${encodeURIComponent(convertToRelativePath(opts.extractedFilename))}')`
}
});
diff --git a/packages/start/src/runtime/server-handler.ts b/packages/start/src/runtime/server-handler.ts
index 5d2c2eca6..14ba7a1f6 100644
--- a/packages/start/src/runtime/server-handler.ts
+++ b/packages/start/src/runtime/server-handler.ts
@@ -1,4 +1,5 @@
///
+import { createHash } from "node:crypto";
import { crossSerializeStream, fromJSON, getCrossReferenceHeader } from "seroval";
// @ts-ignore
import {
@@ -78,11 +79,38 @@ function serializeToStream(id: string, value: any) {
});
}
-/** decode string, here to base64 */
-function decodeString(str?: string) {
- return str ? decodeURIComponent(atob(str)) : str;
+/** encode string, Need to be consistent with `packages/start/config/index.js` */
+function encodeString(str: string) {
+ return createHash("sha256").update(str).digest("hex");
}
+function hashObjectKey(objectValue: Record) {
+ return Object.fromEntries(
+ Object.entries(objectValue).flatMap(([key, value]) => [
+ [key, value],
+ [encodeString(key), value]
+ ])
+ );
+}
+
+/**
+ * Creates a hashed version of server function manifest with different behavior based on environment
+ *
+ * In development: Uses a Proxy to dynamically access both original and hashed keys
+ * In production: Directly returns an object with both original and hashed keys
+ */
+const hashServerFnManifest = process.env.NODE_ENV === "development"
+ ? new Proxy(serverFnManifest, { // Development environment uses Proxy
+ get(target, key) {
+ // If key not found in original manifest and key is string, try hashed version
+ if (!target[key] && typeof key === 'string') {
+ return hashObjectKey(target)[key];
+ }
+ return target[key];
+ },
+ })
+ : hashObjectKey(serverFnManifest);
+
async function handleServerFunction(h3Event: HTTPEvent) {
const event = getFetchEvent(h3Event);
const request = event.request;
@@ -105,8 +133,7 @@ async function handleServerFunction(h3Event: HTTPEvent) {
: new Response(null, { status: 404 });
}
}
- functionId = decodeString(functionId);
- const serverFnInfo = serverFnManifest[functionId];
+ const serverFnInfo = hashServerFnManifest[functionId];
let fnModule: undefined | { [key: string]: any };
if (!serverFnInfo) {
From 73b7c1bf01f93283c919b1e6c5df8c9e6477a91c Mon Sep 17 00:00:00 2001
From: thinkeW <863093879@qq.com>
Date: Wed, 2 Apr 2025 10:09:22 +0800
Subject: [PATCH 3/5] feat:only encode sfn > extractedFilename
---
packages/start/config/index.js | 18 +++-------
packages/start/src/runtime/server-handler.ts | 35 +-------------------
2 files changed, 5 insertions(+), 48 deletions(-)
diff --git a/packages/start/config/index.js b/packages/start/config/index.js
index c721f848f..b8dbb8b00 100644
--- a/packages/start/config/index.js
+++ b/packages/start/config/index.js
@@ -1,6 +1,5 @@
import { createTanStackServerFnPlugin } from "@tanstack/server-functions-plugin";
import defu from "defu";
-import { createHash } from "node:crypto";
import { existsSync } from "node:fs";
import { join } from "node:path";
import { fileURLToPath } from "node:url";
@@ -43,16 +42,7 @@ function solidStartServerFsRouter(config) {
* @returns {string}
*/
function convertToRelativePath(filepath) {
- const arr = filepath.split("/src/");
- return arr[1] ? `~/${arr[1]}` : filepath;
-}
-
-/** encode string, here to sha256 hash
- * @param {string} str
- * @returns {string}
- */
-function encodeString(str) {
- return createHash("sha256").update(str).digest("hex");
+ return filepath.replace(process.cwd(), "~");
}
const SolidStartServerFnsPlugin = createTanStackServerFnPlugin({
@@ -65,7 +55,7 @@ const SolidStartServerFnsPlugin = createTanStackServerFnPlugin({
fileURLToPath(new URL("../dist/runtime/server-runtime.js", import.meta.url))
)}"`,
replacer: opts =>
- `createServerReference(${() => {}}, '${encodeString(opts.functionId)}', '${encodeURIComponent(convertToRelativePath(opts.extractedFilename))}')`
+ `createServerReference(${() => {}}, '${opts.functionId}', '${encodeURIComponent(convertToRelativePath(opts.extractedFilename))}')`
},
ssr: {
getRuntimeCode: () =>
@@ -73,7 +63,7 @@ const SolidStartServerFnsPlugin = createTanStackServerFnPlugin({
fileURLToPath(new URL("../dist/runtime/server-fns-runtime.js", import.meta.url))
)}'`,
replacer: opts =>
- `createServerReference(${opts.fn}, '${encodeString(opts.functionId)}', '${encodeURIComponent(convertToRelativePath(opts.extractedFilename))}')`
+ `createServerReference(${opts.fn}, '${opts.functionId}', '${encodeURIComponent(convertToRelativePath(opts.extractedFilename))}')`
},
server: {
getRuntimeCode: () =>
@@ -81,7 +71,7 @@ const SolidStartServerFnsPlugin = createTanStackServerFnPlugin({
fileURLToPath(new URL("../dist/runtime/server-fns-runtime.js", import.meta.url))
)}'`,
replacer: opts =>
- `createServerReference(${opts.fn}, '${encodeString(opts.functionId)}', '${encodeURIComponent(convertToRelativePath(opts.extractedFilename))}')`
+ `createServerReference(${opts.fn}, '${opts.functionId}', '${encodeURIComponent(convertToRelativePath(opts.extractedFilename))}')`
}
});
diff --git a/packages/start/src/runtime/server-handler.ts b/packages/start/src/runtime/server-handler.ts
index 14ba7a1f6..ffa620af4 100644
--- a/packages/start/src/runtime/server-handler.ts
+++ b/packages/start/src/runtime/server-handler.ts
@@ -1,5 +1,4 @@
///
-import { createHash } from "node:crypto";
import { crossSerializeStream, fromJSON, getCrossReferenceHeader } from "seroval";
// @ts-ignore
import {
@@ -79,38 +78,6 @@ function serializeToStream(id: string, value: any) {
});
}
-/** encode string, Need to be consistent with `packages/start/config/index.js` */
-function encodeString(str: string) {
- return createHash("sha256").update(str).digest("hex");
-}
-
-function hashObjectKey(objectValue: Record) {
- return Object.fromEntries(
- Object.entries(objectValue).flatMap(([key, value]) => [
- [key, value],
- [encodeString(key), value]
- ])
- );
-}
-
-/**
- * Creates a hashed version of server function manifest with different behavior based on environment
- *
- * In development: Uses a Proxy to dynamically access both original and hashed keys
- * In production: Directly returns an object with both original and hashed keys
- */
-const hashServerFnManifest = process.env.NODE_ENV === "development"
- ? new Proxy(serverFnManifest, { // Development environment uses Proxy
- get(target, key) {
- // If key not found in original manifest and key is string, try hashed version
- if (!target[key] && typeof key === 'string') {
- return hashObjectKey(target)[key];
- }
- return target[key];
- },
- })
- : hashObjectKey(serverFnManifest);
-
async function handleServerFunction(h3Event: HTTPEvent) {
const event = getFetchEvent(h3Event);
const request = event.request;
@@ -133,7 +100,7 @@ async function handleServerFunction(h3Event: HTTPEvent) {
: new Response(null, { status: 404 });
}
}
- const serverFnInfo = hashServerFnManifest[functionId];
+ const serverFnInfo = serverFnManifest[functionId];
let fnModule: undefined | { [key: string]: any };
if (!serverFnInfo) {
From 4042f70d77c887119aeab218e503989713a28500 Mon Sep 17 00:00:00 2001
From: thinkeW <863093879@qq.com>
Date: Wed, 2 Apr 2025 10:11:05 +0800
Subject: [PATCH 4/5] fix:not change server-handler.ts
---
packages/start/src/runtime/server-handler.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/packages/start/src/runtime/server-handler.ts b/packages/start/src/runtime/server-handler.ts
index ffa620af4..cbae38bdb 100644
--- a/packages/start/src/runtime/server-handler.ts
+++ b/packages/start/src/runtime/server-handler.ts
@@ -100,6 +100,7 @@ async function handleServerFunction(h3Event: HTTPEvent) {
: new Response(null, { status: 404 });
}
}
+
const serverFnInfo = serverFnManifest[functionId];
let fnModule: undefined | { [key: string]: any };
From b640817896d7821920bf09eb08c6fa0b0aa1a9d1 Mon Sep 17 00:00:00 2001
From: thinkeW <863093879@qq.com>
Date: Wed, 2 Apr 2025 10:11:32 +0800
Subject: [PATCH 5/5] fix:not change server-handler.ts
---
packages/start/src/runtime/server-handler.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/start/src/runtime/server-handler.ts b/packages/start/src/runtime/server-handler.ts
index cbae38bdb..46e1603c5 100644
--- a/packages/start/src/runtime/server-handler.ts
+++ b/packages/start/src/runtime/server-handler.ts
@@ -100,7 +100,7 @@ async function handleServerFunction(h3Event: HTTPEvent) {
: new Response(null, { status: 404 });
}
}
-
+
const serverFnInfo = serverFnManifest[functionId];
let fnModule: undefined | { [key: string]: any };