diff --git a/.editorconfig b/.editorconfig
index 54c8a9183..de279a9ee 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -5,4 +5,6 @@ indent_style = space
indent_size = 2
end_of_line = LF
charset = utf-8
-insert_final_newline = true
\ No newline at end of file
+insert_final_newline = true
+max_line_length = 100
+quote_type = double
diff --git a/.oxfmtrc.json b/.oxfmtrc.json
new file mode 100644
index 000000000..45c63abd9
--- /dev/null
+++ b/.oxfmtrc.json
@@ -0,0 +1,11 @@
+{
+ "$schema": "https://raw.githubusercontent.com/oxc-project/oxc/main/npm/oxfmt/configuration_schema.json",
+ "tabWidth": 2,
+ "useTabs": false,
+ "endOfLine": "lf",
+ "trailingComma": "all",
+ "semi": true,
+ "singleQuote": false,
+ "arrowParens": "avoid",
+ "printWidth": 100
+}
diff --git a/.prettierrc b/.prettierrc
deleted file mode 100644
index 6aeb7ea15..000000000
--- a/.prettierrc
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "trailingComma": "none",
- "tabWidth": 2,
- "semi": true,
- "singleQuote": false,
- "arrowParens": "avoid",
- "printWidth": 100
-}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 318496622..a882e9714 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -74,6 +74,10 @@ Once the PR is there, **create an issue** and link the PR (mention the PR as you
> [!IMPORTANT]
> Mark the **allow edit by the maintainers** so we can more easily investigate the failing test and propose a fix. Otherwise we may need to close your PR and cherry-pick your commit.
+### Formatting your code
+
+We have a set of rules defined in the `.editorconfig` and `.oxfmtrc.json` files. Please format your code before opening a PR, so that we keep the codebase consistent. Regardless of what editor you use, running `pnpm format` will format your code according to our rules.
+
---
If you have read all the way here, you're already a champ! 🏆
diff --git a/apps/fixtures/bare/vite.config.ts b/apps/fixtures/bare/vite.config.ts
index 2d2e72458..27a23708d 100644
--- a/apps/fixtures/bare/vite.config.ts
+++ b/apps/fixtures/bare/vite.config.ts
@@ -3,5 +3,5 @@ import { solidStart } from "../../../packages/start/src/config";
import { nitroV2Plugin } from "../../../packages/start-nitro-v2-vite-plugin/src";
export default defineConfig({
- plugins: [solidStart(), nitroV2Plugin()],
+ plugins: [solidStart(), nitroV2Plugin()],
});
diff --git a/apps/fixtures/basic/vite.config.ts b/apps/fixtures/basic/vite.config.ts
index 2d2e72458..27a23708d 100644
--- a/apps/fixtures/basic/vite.config.ts
+++ b/apps/fixtures/basic/vite.config.ts
@@ -3,5 +3,5 @@ import { solidStart } from "../../../packages/start/src/config";
import { nitroV2Plugin } from "../../../packages/start-nitro-v2-vite-plugin/src";
export default defineConfig({
- plugins: [solidStart(), nitroV2Plugin()],
+ plugins: [solidStart(), nitroV2Plugin()],
});
diff --git a/apps/fixtures/css/src/components/layout.tsx b/apps/fixtures/css/src/components/layout.tsx
index 91d077054..99763f047 100644
--- a/apps/fixtures/css/src/components/layout.tsx
+++ b/apps/fixtures/css/src/components/layout.tsx
@@ -26,8 +26,8 @@ const Layout = (props: FlowProps<{ title: string }>) => {
- Enable throttling & disable cache in the network tab to see eventual FOUC's (frames of unstyled
- content)
+ Enable throttling & disable cache in the network tab to see eventual FOUC's (frames of
+ unstyled content)
Click on routes to test client navigation
diff --git a/apps/fixtures/css/src/components/lazy.tsx b/apps/fixtures/css/src/components/lazy.tsx
index 462362ec2..1a64df9d1 100644
--- a/apps/fixtures/css/src/components/lazy.tsx
+++ b/apps/fixtures/css/src/components/lazy.tsx
@@ -1,7 +1,7 @@
import "../styles/lazy.css";
const Lazy = () => {
- return <>>
-}
+ return <>>;
+};
export default Lazy;
diff --git a/apps/fixtures/css/src/components/lazyGlob.tsx b/apps/fixtures/css/src/components/lazyGlob.tsx
index 75dca500b..0256e799e 100644
--- a/apps/fixtures/css/src/components/lazyGlob.tsx
+++ b/apps/fixtures/css/src/components/lazyGlob.tsx
@@ -1,7 +1,7 @@
import "../styles/lazyGlob.css";
const Lazy = () => {
- return <>>
-}
+ return <>>;
+};
export default Lazy;
diff --git a/apps/fixtures/css/src/components/lazyLink.tsx b/apps/fixtures/css/src/components/lazyLink.tsx
index f3b9084e7..5d352d41b 100644
--- a/apps/fixtures/css/src/components/lazyLink.tsx
+++ b/apps/fixtures/css/src/components/lazyLink.tsx
@@ -1,5 +1,5 @@
import url from "../styles/lazyLink.css?url";
-const Lazy = () =>
+const Lazy = () => ;
export default Lazy;
diff --git a/apps/fixtures/css/src/components/lazyLinkTmp.tsx b/apps/fixtures/css/src/components/lazyLinkTmp.tsx
index 3a04dd96e..6061f995b 100644
--- a/apps/fixtures/css/src/components/lazyLinkTmp.tsx
+++ b/apps/fixtures/css/src/components/lazyLinkTmp.tsx
@@ -1,5 +1,5 @@
import url from "../styles/lazyLinkTmp.css?url";
-const Lazy = () =>
+const Lazy = () => ;
export default Lazy;
diff --git a/apps/fixtures/css/src/components/test.tsx b/apps/fixtures/css/src/components/test.tsx
index 8f3e8ea1a..43b7de1b9 100644
--- a/apps/fixtures/css/src/components/test.tsx
+++ b/apps/fixtures/css/src/components/test.tsx
@@ -23,7 +23,7 @@ const Test = (props: {
"grid grid-cols-subgrid col-span-full items-center rounded text-white font-medium py-1 px-2 border-4 transition-colors duration-[1.5s]",
props.invert ? "bg-success" : "bg-error",
props.noSupport ? "border-warn" : "border-transparent",
- props.class
+ props.class,
)}
>
{props.component}
diff --git a/apps/fixtures/css/src/routes/[...404].tsx b/apps/fixtures/css/src/routes/[...404].tsx
index 53b221ce7..4ea71ec7f 100644
--- a/apps/fixtures/css/src/routes/[...404].tsx
+++ b/apps/fixtures/css/src/routes/[...404].tsx
@@ -16,4 +16,4 @@ export default function NotFound() {
);
-}
\ No newline at end of file
+}
diff --git a/apps/fixtures/css/vite.config.ts b/apps/fixtures/css/vite.config.ts
index 598584d4b..636b0a385 100644
--- a/apps/fixtures/css/vite.config.ts
+++ b/apps/fixtures/css/vite.config.ts
@@ -4,5 +4,5 @@ import { nitroV2Plugin } from "../../../packages/start-nitro-v2-vite-plugin/src"
import { solidStart } from "../../../packages/start/src/config";
export default defineConfig({
- plugins: [solidStart(), nitroV2Plugin(), tailwindcss()]
+ plugins: [solidStart(), nitroV2Plugin(), tailwindcss()],
});
diff --git a/apps/fixtures/experiments/src/components/BreaksOnServer.tsx b/apps/fixtures/experiments/src/components/BreaksOnServer.tsx
index 8e6ae7eec..f6b161610 100644
--- a/apps/fixtures/experiments/src/components/BreaksOnServer.tsx
+++ b/apps/fixtures/experiments/src/components/BreaksOnServer.tsx
@@ -2,5 +2,5 @@
const location = window.document.location;
export default function BreaksOnServer() {
- return Breaks on server {location.href}
-}
\ No newline at end of file
+ return Breaks on server {location.href}
;
+}
diff --git a/apps/fixtures/experiments/src/entry-server.tsx b/apps/fixtures/experiments/src/entry-server.tsx
index 9ac19e964..3cc2ec0c5 100644
--- a/apps/fixtures/experiments/src/entry-server.tsx
+++ b/apps/fixtures/experiments/src/entry-server.tsx
@@ -8,23 +8,21 @@ declare module "@solidjs/start/server" {
}
}
-export default createHandler(
- () => (
- (
-
-
-
-
-
- {assets}
-
-
- {children}
- {scripts}
-
-
- )}
- />
- )
-);
+export default createHandler(() => (
+ (
+
+
+
+
+
+ {assets}
+
+
+ {children}
+ {scripts}
+
+
+ )}
+ />
+));
diff --git a/apps/fixtures/experiments/src/middleware.ts b/apps/fixtures/experiments/src/middleware.ts
index 83072a35c..4b54dfb5e 100644
--- a/apps/fixtures/experiments/src/middleware.ts
+++ b/apps/fixtures/experiments/src/middleware.ts
@@ -2,19 +2,19 @@ import { getRequestURL } from "@solidjs/start/http";
import { createMiddleware } from "@solidjs/start/middleware";
export default createMiddleware({
- onRequest: [
- (event) => {
- event.locals.foo = "bar";
- console.log("REQUEST", event.request.url);
- console.log(
- "SEARCH PARAM KEYS FROM ASYNC CONTEXT",
- Array.from(getRequestURL().searchParams.keys()),
- );
- },
- ],
- onBeforeResponse: [
- (event, { body }) => {
- console.log("BEFORE RESPONSE", body);
- },
- ],
+ onRequest: [
+ event => {
+ event.locals.foo = "bar";
+ console.log("REQUEST", event.request.url);
+ console.log(
+ "SEARCH PARAM KEYS FROM ASYNC CONTEXT",
+ Array.from(getRequestURL().searchParams.keys()),
+ );
+ },
+ ],
+ onBeforeResponse: [
+ (event, { body }) => {
+ console.log("BEFORE RESPONSE", body);
+ },
+ ],
});
diff --git a/apps/fixtures/experiments/src/routes/(group).tsx b/apps/fixtures/experiments/src/routes/(group).tsx
index cd362dfeb..f8b17d8fd 100644
--- a/apps/fixtures/experiments/src/routes/(group).tsx
+++ b/apps/fixtures/experiments/src/routes/(group).tsx
@@ -1,8 +1,10 @@
import { RouteSectionProps } from "@solidjs/router";
-export default function(props: RouteSectionProps) {
- return <>
- Group
- {props.children}
- >
-}
\ No newline at end of file
+export default function (props: RouteSectionProps) {
+ return (
+ <>
+ Group
+ {props.children}
+ >
+ );
+}
diff --git a/apps/fixtures/experiments/src/routes/(group)/other.tsx b/apps/fixtures/experiments/src/routes/(group)/other.tsx
index ec973e9b2..64c3cec02 100644
--- a/apps/fixtures/experiments/src/routes/(group)/other.tsx
+++ b/apps/fixtures/experiments/src/routes/(group)/other.tsx
@@ -1,3 +1,3 @@
-export default function() {
- return
-}
\ No newline at end of file
+export default function () {
+ return ;
+}
diff --git a/apps/fixtures/experiments/src/routes/(group2).tsx b/apps/fixtures/experiments/src/routes/(group2).tsx
index 9da3d63e2..b6f213fb2 100644
--- a/apps/fixtures/experiments/src/routes/(group2).tsx
+++ b/apps/fixtures/experiments/src/routes/(group2).tsx
@@ -1,8 +1,10 @@
import { RouteSectionProps } from "@solidjs/router";
-export default function(props: RouteSectionProps) {
- return <>
- Group 2
- {props.children}
- >
-}
\ No newline at end of file
+export default function (props: RouteSectionProps) {
+ return (
+ <>
+ Group 2
+ {props.children}
+ >
+ );
+}
diff --git a/apps/fixtures/experiments/src/routes/(group2)/something.tsx b/apps/fixtures/experiments/src/routes/(group2)/something.tsx
index e8e024771..0cab8149c 100644
--- a/apps/fixtures/experiments/src/routes/(group2)/something.tsx
+++ b/apps/fixtures/experiments/src/routes/(group2)/something.tsx
@@ -1,3 +1,3 @@
-export default function() {
- return
-}
\ No newline at end of file
+export default function () {
+ return ;
+}
diff --git a/apps/fixtures/experiments/src/routes/[...404].tsx b/apps/fixtures/experiments/src/routes/[...404].tsx
index f979d513f..c2329dac9 100644
--- a/apps/fixtures/experiments/src/routes/[...404].tsx
+++ b/apps/fixtures/experiments/src/routes/[...404].tsx
@@ -2,10 +2,9 @@ import { Title } from "@solidjs/meta";
import { HttpStatusCode } from "@solidjs/start";
import type { APIEvent } from "@solidjs/start/server";
-
export const GET = (event: APIEvent) => {
if (event.request.headers.get("accept") !== "application/json") return;
- return { notFound: "API"}
+ return { notFound: "API" };
};
export default function NotFound() {
diff --git a/apps/fixtures/experiments/src/routes/[[option]]/thing.tsx b/apps/fixtures/experiments/src/routes/[[option]]/thing.tsx
index 325fd74d0..4135b83e8 100644
--- a/apps/fixtures/experiments/src/routes/[[option]]/thing.tsx
+++ b/apps/fixtures/experiments/src/routes/[[option]]/thing.tsx
@@ -1,5 +1,5 @@
import type { RouteSectionProps } from "@solidjs/router";
-export default function(props: RouteSectionProps) {
- return THING: {props.params.option || "NO"}
-}
\ No newline at end of file
+export default function (props: RouteSectionProps) {
+ return THING: {props.params.option || "NO"} ;
+}
diff --git a/apps/fixtures/experiments/src/routes/api/hello/[name].ts b/apps/fixtures/experiments/src/routes/api/hello/[name].ts
index 55873210b..98a0d9713 100644
--- a/apps/fixtures/experiments/src/routes/api/hello/[name].ts
+++ b/apps/fixtures/experiments/src/routes/api/hello/[name].ts
@@ -2,4 +2,4 @@ import type { APIHandler } from "@solidjs/start/server";
export const GET: APIHandler = async ({ params }) => {
return `Hello ${params.name}!`;
-};
\ No newline at end of file
+};
diff --git a/apps/fixtures/experiments/src/routes/index.tsx b/apps/fixtures/experiments/src/routes/index.tsx
index 1201bd2c0..189744fb1 100644
--- a/apps/fixtures/experiments/src/routes/index.tsx
+++ b/apps/fixtures/experiments/src/routes/index.tsx
@@ -13,7 +13,7 @@ const hello = GET(async (name: string) => {
console.log("ID", id, e.locals.foo);
return json(
{ hello: new Promise(r => setTimeout(() => r(name), 1000)) },
- { headers: { "cache-control": "max-age=60" } }
+ { headers: { "cache-control": "max-age=60" } },
);
});
@@ -22,9 +22,9 @@ export default function Home() {
console.log(v);
console.log(await v.hello);
});
- const port = isServer ? new URL(getRequestEvent()!.request.url).port: location.port;
+ const port = isServer ? new URL(getRequestEvent()!.request.url).port : location.port;
fetch(`http://localhost:${port}${import.meta.env.BASE_URL}/unknown`, {
- headers: { Accept: "application/json" }
+ headers: { Accept: "application/json" },
}).then(async res => console.log(await res.json()));
return (
diff --git a/apps/fixtures/experiments/src/routes/test(named)/[name]/home.tsx b/apps/fixtures/experiments/src/routes/test(named)/[name]/home.tsx
index 09379129c..ed60ca55d 100644
--- a/apps/fixtures/experiments/src/routes/test(named)/[name]/home.tsx
+++ b/apps/fixtures/experiments/src/routes/test(named)/[name]/home.tsx
@@ -1,3 +1,3 @@
-export default function() {
- return
-}
\ No newline at end of file
+export default function () {
+ return ;
+}
diff --git a/apps/fixtures/experiments/src/routes/test/(hi).tsx b/apps/fixtures/experiments/src/routes/test/(hi).tsx
index e48dba856..5e6a5aa68 100644
--- a/apps/fixtures/experiments/src/routes/test/(hi).tsx
+++ b/apps/fixtures/experiments/src/routes/test/(hi).tsx
@@ -1,3 +1,3 @@
-export default function() {
- return
-}
\ No newline at end of file
+export default function () {
+ return ;
+}
diff --git a/apps/fixtures/experiments/src/routes/test/[name].tsx b/apps/fixtures/experiments/src/routes/test/[name].tsx
index 5a6a3e216..9ea84914d 100644
--- a/apps/fixtures/experiments/src/routes/test/[name].tsx
+++ b/apps/fixtures/experiments/src/routes/test/[name].tsx
@@ -1,5 +1,5 @@
import { RouteSectionProps } from "@solidjs/router";
-export default function(props: RouteSectionProps) {
- return
-}
\ No newline at end of file
+export default function (props: RouteSectionProps) {
+ return ;
+}
diff --git "a/apps/fixtures/experiments/src/routes/\346\274\242\345\255\227.tsx" "b/apps/fixtures/experiments/src/routes/\346\274\242\345\255\227.tsx"
index 589296b5f..c8920b4a5 100644
--- "a/apps/fixtures/experiments/src/routes/\346\274\242\345\255\227.tsx"
+++ "b/apps/fixtures/experiments/src/routes/\346\274\242\345\255\227.tsx"
@@ -1,3 +1,3 @@
-export default function() {
- return
-}
\ No newline at end of file
+export default function () {
+ return ;
+}
diff --git a/apps/fixtures/experiments/vite.config.ts b/apps/fixtures/experiments/vite.config.ts
index 96122c421..57596416d 100644
--- a/apps/fixtures/experiments/vite.config.ts
+++ b/apps/fixtures/experiments/vite.config.ts
@@ -1,7 +1,7 @@
import { defineConfig } from "vite";
import { solidStart } from "../../../packages/start/src/config";
-import { nitroV2Plugin } from '../../../packages/start-nitro-v2-vite-plugin/src'
+import { nitroV2Plugin } from "../../../packages/start-nitro-v2-vite-plugin/src";
export default defineConfig({
- plugins: [solidStart({ middleware: "./src/middleware.ts" }), nitroV2Plugin()],
+ plugins: [solidStart({ middleware: "./src/middleware.ts" }), nitroV2Plugin()],
});
diff --git a/apps/fixtures/hackernews/public/sw.js b/apps/fixtures/hackernews/public/sw.js
index b2ecb5056..fcf9d79af 100644
--- a/apps/fixtures/hackernews/public/sw.js
+++ b/apps/fixtures/hackernews/public/sw.js
@@ -1,14 +1,14 @@
-self.addEventListener("fetch", (e) => {
+self.addEventListener("fetch", e => {
(e.request.url.includes("localhost") || e.request.url.includes("workers")) &&
e.respondWith(
caches
.open("solid-hn")
- .then((t) =>
+ .then(t =>
t
.match(e.request)
- .then((n) => n || fetch(e.request).then((n) => (t.put(e.request, n.clone()), n)))
- )
+ .then(n => n || fetch(e.request).then(n => (t.put(e.request, n.clone()), n))),
+ ),
);
});
-self.addEventListener("activate", (e) => e.waitUntil(caches.delete("solid-hn")));
+self.addEventListener("activate", e => e.waitUntil(caches.delete("solid-hn")));
diff --git a/apps/fixtures/hackernews/src/components/comment.tsx b/apps/fixtures/hackernews/src/components/comment.tsx
index 5fac5d45f..8a85eb9df 100644
--- a/apps/fixtures/hackernews/src/components/comment.tsx
+++ b/apps/fixtures/hackernews/src/components/comment.tsx
@@ -7,8 +7,8 @@ const Comment: Component<{ comment: CommentDefinition }> = props => {
return (
- referencing multiple export named functions in the same file
+
+ referencing multiple export named functions in the same file
+
{props.children}
diff --git a/apps/tests/src/e2e/api-call.test.ts b/apps/tests/src/e2e/api-call.test.ts
index 29a354b7e..32eb475cc 100644
--- a/apps/tests/src/e2e/api-call.test.ts
+++ b/apps/tests/src/e2e/api-call.test.ts
@@ -13,7 +13,9 @@ test.describe("api calls", () => {
expect(okResp.headers.get("x-return-header")).toBe("value");
expect(okResp.headers.get("x-shared-header")).toBe("event");
- const redirectResp = await fetch("http://localhost:3000/api/header-merging?status=redirect", { redirect: "manual" });
+ const redirectResp = await fetch("http://localhost:3000/api/header-merging?status=redirect", {
+ redirect: "manual",
+ });
expect(redirectResp.headers.get("Set-Cookie")).toBeTruthy();
expect(redirectResp.headers.get("x-event-header")).toBe("value");
expect(redirectResp.headers.get("x-return-header")).toBe("value");
@@ -21,9 +23,8 @@ test.describe("api calls", () => {
});
test("should preserve multiple Set-Cookie headers on redirect (RFC 6265)", async () => {
-
const response = await fetch("http://localhost:3000/api/multi-set-cookie-redirect", {
- redirect: "manual"
+ redirect: "manual",
});
expect(response.status).toBe(302);
diff --git a/apps/tests/src/e2e/http-header.test.ts b/apps/tests/src/e2e/http-header.test.ts
index 572a77721..c26f5a19f 100644
--- a/apps/tests/src/e2e/http-header.test.ts
+++ b/apps/tests/src/e2e/http-header.test.ts
@@ -1,10 +1,10 @@
import { expect, test } from "@playwright/test";
test.describe("http header", () => {
- // couldn't get this to see the headers but verified in chrome devtools
- test.skip("should set http header", async ({ page }) => {
- const response = await page.goto("/http-header");
+ // couldn't get this to see the headers but verified in chrome devtools
+ test.skip("should set http header", async ({ page }) => {
+ const response = await page.goto("/http-header");
- expect(response?.headers()["test-header"]).toBe("test-value");
- });
+ expect(response?.headers()["test-header"]).toBe("test-value");
+ });
});
diff --git a/apps/tests/src/e2e/route-groups.test.ts b/apps/tests/src/e2e/route-groups.test.ts
index 638706c65..25406163f 100644
--- a/apps/tests/src/e2e/route-groups.test.ts
+++ b/apps/tests/src/e2e/route-groups.test.ts
@@ -2,28 +2,28 @@ import { test, expect } from "@playwright/test";
test.describe("route-groups", () => {
test("should resolve `/routes/nested/(ignored)route0.tsx` to `nested/route0`", async ({
- page
+ page,
}) => {
await page.goto("http://localhost:3000/nested/route0");
await expect(page.locator("body")).toContainText("nested route 0");
});
test("should resolve `/routes/nested/(level1)/(ignored)route1.tsx` to `nested/route1`", async ({
- page
+ page,
}) => {
await page.goto("http://localhost:3000/nested/route1");
await expect(page.locator("body")).toContainText("nested route 1");
});
test("should resolve `/routes/nested/(level1)/(level2)/(ignored)route2.tsx` to `nested/route2`", async ({
- page
+ page,
}) => {
await page.goto("http://localhost:3000/nested/route2");
await expect(page.locator("body")).toContainText("nested route 2");
});
test("should resolve `/routes/nested/(level1)/(level2)/route3.tsx` to `nested/route3`", async ({
- page
+ page,
}) => {
await page.goto("http://localhost:3000/nested/route3");
await expect(page.locator("body")).toContainText("nested route 3");
diff --git a/apps/tests/src/e2e/server-function.test.ts b/apps/tests/src/e2e/server-function.test.ts
index 12dbf112e..7a8131be9 100644
--- a/apps/tests/src/e2e/server-function.test.ts
+++ b/apps/tests/src/e2e/server-function.test.ts
@@ -12,7 +12,7 @@ test.describe("server-function", () => {
});
test("should have an id of type string in the server function meta - nested", async ({
- page
+ page,
}) => {
await page.goto("http://localhost:3000/server-function-meta-nested");
await expect(page.locator("#server-fn-test")).toContainText('{"serverFnWithMeta":"string"}');
@@ -21,14 +21,14 @@ test.describe("server-function", () => {
test("should externalize node builtin in server function - nested", async ({ page }) => {
await page.goto("http://localhost:3000/node-builtin-nested");
await expect(page.locator("#server-fn-test")).toContainText(
- '{"serverFnWithNodeBuiltin":"can/externalize"}'
+ '{"serverFnWithNodeBuiltin":"can/externalize"}',
);
});
test("should externalize npm module in server function - nested", async ({ page }) => {
await page.goto("http://localhost:3000/npm-module-nested");
await expect(page.locator("#server-fn-test")).toContainText(
- '{"serverFnWithNpmModule":[2,4,6]}'
+ '{"serverFnWithNpmModule":[2,4,6]}',
);
});
@@ -38,7 +38,7 @@ test.describe("server-function", () => {
});
test("should have an id of type string in the server function meta - toplevel", async ({
- page
+ page,
}) => {
await page.goto("http://localhost:3000/server-function-meta");
await expect(page.locator("#server-fn-test")).toContainText('{"serverFnWithMeta":"string"}');
@@ -47,14 +47,14 @@ test.describe("server-function", () => {
test("should externalize node builtin in server function - toplevel", async ({ page }) => {
await page.goto("http://localhost:3000/node-builtin-toplevel");
await expect(page.locator("#server-fn-test")).toContainText(
- '{"serverFnWithNodeBuiltin":"can/externalize"}'
+ '{"serverFnWithNodeBuiltin":"can/externalize"}',
);
});
test("should externalize npm module in server function - toplevel", async ({ page }) => {
await page.goto("http://localhost:3000/npm-module-toplevel");
await expect(page.locator("#server-fn-test")).toContainText(
- '{"serverFnWithNpmModule":[2,4,6]}'
+ '{"serverFnWithNpmModule":[2,4,6]}',
);
});
diff --git a/apps/tests/src/routes/(basic).tsx b/apps/tests/src/routes/(basic).tsx
index 13c3aeeb1..54d1741b5 100644
--- a/apps/tests/src/routes/(basic).tsx
+++ b/apps/tests/src/routes/(basic).tsx
@@ -2,11 +2,13 @@ import { createSignal } from "solid-js";
export default function App() {
const [counter, setCounter] = createSignal(0);
-
+
return (
{counter()}
- setCounter(n => n + 1)}>one more
+ setCounter(n => n + 1)}>
+ one more
+
);
}
diff --git a/apps/tests/src/routes/[...404].tsx b/apps/tests/src/routes/[...404].tsx
index 7d71e47bc..f1d7221c8 100644
--- a/apps/tests/src/routes/[...404].tsx
+++ b/apps/tests/src/routes/[...404].tsx
@@ -13,9 +13,7 @@ export default function NotFound() {
Not Found
Page Not Found
-
- {"Your page cannot be found... >_<"}
-
+ {"Your page cannot be found... >_<"}
);
}
diff --git a/apps/tests/src/routes/api/header-merging.ts b/apps/tests/src/routes/api/header-merging.ts
index 0b85a77ea..23fe07359 100644
--- a/apps/tests/src/routes/api/header-merging.ts
+++ b/apps/tests/src/routes/api/header-merging.ts
@@ -4,26 +4,26 @@ export async function GET() {
const url = getRequestURL();
const s = await useSession({ password: "0".repeat(32) });
- await s.update(d => ({count: (d.count || 0) + 1}))
+ await s.update(d => ({ count: (d.count || 0) + 1 }));
setHeader("x-event-header", "value");
setHeader("x-shared-header", "event");
- if(url.searchParams.get("status") === "redirect") {
+ if (url.searchParams.get("status") === "redirect") {
return new Response(null, {
status: 301,
headers: {
location: "http://::/abc",
"x-return-header": "value",
- "x-shared-header": "return"
- }
- })
+ "x-shared-header": "return",
+ },
+ });
} else {
return new Response(null, {
headers: {
"x-return-header": "value",
- "x-shared-header": "return"
- }
- })
+ "x-shared-header": "return",
+ },
+ });
}
}
diff --git a/apps/tests/src/routes/api/multi-set-cookie-redirect.ts b/apps/tests/src/routes/api/multi-set-cookie-redirect.ts
index 1877c1677..c65f7c3b4 100644
--- a/apps/tests/src/routes/api/multi-set-cookie-redirect.ts
+++ b/apps/tests/src/routes/api/multi-set-cookie-redirect.ts
@@ -12,6 +12,6 @@ export async function GET() {
return new Response(null, {
status: 302,
- headers
+ headers,
});
}
diff --git a/apps/tests/src/routes/client-only/_component.tsx b/apps/tests/src/routes/client-only/_component.tsx
index d8737ad84..687d2b85d 100644
--- a/apps/tests/src/routes/client-only/_component.tsx
+++ b/apps/tests/src/routes/client-only/_component.tsx
@@ -1,14 +1,14 @@
import { createSignal } from "solid-js";
import { isServer } from "solid-js/web";
-
export default function ClientOnlyComponent() {
- const [output, setOutput] = createSignal<{ clientWithIsServer?: boolean; }>({});
+ const [output, setOutput] = createSignal<{ clientWithIsServer?: boolean }>({});
+
+ setOutput(prev => ({ ...prev, clientWithIsServer: isServer }));
- setOutput(prev => ({ ...prev, clientWithIsServer: isServer }));
-
- return (
-
- {JSON.stringify(output())}
- )
-}
\ No newline at end of file
+ return (
+
+ {JSON.stringify(output())}
+
+ );
+}
diff --git a/apps/tests/src/routes/client-only/index.tsx b/apps/tests/src/routes/client-only/index.tsx
index e456d13ee..8e44c8d30 100644
--- a/apps/tests/src/routes/client-only/index.tsx
+++ b/apps/tests/src/routes/client-only/index.tsx
@@ -1,12 +1,11 @@
import { clientOnly } from "@solidjs/start";
-const Component = clientOnly(() => import('./_component'))
+const Component = clientOnly(() => import("./_component"));
export default function App() {
-
return (
<>
-
+
>
);
}
diff --git a/apps/tests/src/routes/generator-server-function.tsx b/apps/tests/src/routes/generator-server-function.tsx
index 03ba7b308..8757f8452 100644
--- a/apps/tests/src/routes/generator-server-function.tsx
+++ b/apps/tests/src/routes/generator-server-function.tsx
@@ -1,19 +1,19 @@
import { createSignal, onMount } from "solid-js";
-import { sayHello } from '~/functions/use-generator-server-function';
+import { sayHello } from "~/functions/use-generator-server-function";
export default function GeneratorServerFunction() {
- const [output, setOutput] = createSignal('');
+ const [output, setOutput] = createSignal("");
- onMount(async () => {
- const greetings = await sayHello();
- for await (const greeting of greetings) {
- setOutput(greeting);
- }
- });
+ onMount(async () => {
+ const greetings = await sayHello();
+ for await (const greeting of greetings) {
+ setOutput(greeting);
+ }
+ });
- return (
-
- {output()}
-
- );
-}
\ No newline at end of file
+ return (
+
+ {output()}
+
+ );
+}
diff --git a/apps/tests/src/routes/http-header.tsx b/apps/tests/src/routes/http-header.tsx
index a12d99293..8259da4b0 100644
--- a/apps/tests/src/routes/http-header.tsx
+++ b/apps/tests/src/routes/http-header.tsx
@@ -1,10 +1,10 @@
import { HttpHeader } from "@solidjs/start";
export default function HttpHeaderRoute() {
- return (
-
- Http Header
-
-
- );
+ return (
+
+ Http Header
+
+
+ );
}
diff --git a/apps/tests/src/routes/is-server-const.tsx b/apps/tests/src/routes/is-server-const.tsx
index 6c8821e17..7304392f4 100644
--- a/apps/tests/src/routes/is-server-const.tsx
+++ b/apps/tests/src/routes/is-server-const.tsx
@@ -2,18 +2,16 @@ import { createEffect, createSignal } from "solid-js";
import { serverFnWithIsServer } from "~/functions/use-is-server-const";
export default function App() {
- const [output, setOutput] = createSignal<{ serverFnWithIsServer?: boolean }>({});
+ const [output, setOutput] = createSignal<{ serverFnWithIsServer?: boolean }>({});
+ createEffect(async () => {
+ const result = await serverFnWithIsServer();
+ setOutput(prev => ({ ...prev, serverFnWithIsServer: result }));
+ });
- createEffect(async () => {
- const result = await serverFnWithIsServer();
- setOutput(prev => ({ ...prev, serverFnWithIsServer: result }));
- });
-
-
- return (
-
- {JSON.stringify(output())}
-
- );
+ return (
+
+ {JSON.stringify(output())}
+
+ );
}
diff --git a/apps/tests/src/routes/is-server-nested.tsx b/apps/tests/src/routes/is-server-nested.tsx
index 3e6086453..f670c6350 100644
--- a/apps/tests/src/routes/is-server-nested.tsx
+++ b/apps/tests/src/routes/is-server-nested.tsx
@@ -8,15 +8,13 @@ function serverFnWithIsServer() {
}
export default function App() {
- const [output, setOutput] = createSignal<{ serverFnWithIsServer?: boolean }>({});
-
+ const [output, setOutput] = createSignal<{ serverFnWithIsServer?: boolean }>({});
createEffect(async () => {
const result = await serverFnWithIsServer();
setOutput(prev => ({ ...prev, serverFnWithIsServer: result }));
});
-
return (
{JSON.stringify(output())}
diff --git a/apps/tests/src/routes/is-server-toplevel.tsx b/apps/tests/src/routes/is-server-toplevel.tsx
index b829cef9d..e145db8f3 100644
--- a/apps/tests/src/routes/is-server-toplevel.tsx
+++ b/apps/tests/src/routes/is-server-toplevel.tsx
@@ -2,15 +2,13 @@ import { createEffect, createSignal } from "solid-js";
import { serverFnWithIsServer } from "~/functions/use-is-server";
export default function App() {
- const [output, setOutput] = createSignal<{ serverFnWithIsServer?: boolean }>({});
-
+ const [output, setOutput] = createSignal<{ serverFnWithIsServer?: boolean }>({});
createEffect(async () => {
const result = await serverFnWithIsServer();
setOutput(prev => ({ ...prev, serverFnWithIsServer: result }));
});
-
return (
{JSON.stringify(output())}
diff --git a/apps/tests/src/routes/is-server-with-anon-default-export.tsx b/apps/tests/src/routes/is-server-with-anon-default-export.tsx
index 47922b2c8..a46876dfd 100644
--- a/apps/tests/src/routes/is-server-with-anon-default-export.tsx
+++ b/apps/tests/src/routes/is-server-with-anon-default-export.tsx
@@ -2,18 +2,16 @@ import { createEffect, createSignal } from "solid-js";
import { serverFnWithIsServer } from "~/functions/use-is-server-with-anon-default-export";
export default function App() {
- const [output, setOutput] = createSignal<{ serverFnWithIsServer?: boolean }>({});
+ const [output, setOutput] = createSignal<{ serverFnWithIsServer?: boolean }>({});
+ createEffect(async () => {
+ const result = await serverFnWithIsServer();
+ setOutput(prev => ({ ...prev, serverFnWithIsServer: result }));
+ });
- createEffect(async () => {
- const result = await serverFnWithIsServer();
- setOutput(prev => ({ ...prev, serverFnWithIsServer: result }));
- });
-
-
- return (
-
- {JSON.stringify(output())}
-
- );
+ return (
+
+ {JSON.stringify(output())}
+
+ );
}
diff --git a/apps/tests/src/routes/nested/(ignored)route0.tsx b/apps/tests/src/routes/nested/(ignored)route0.tsx
index be352577d..c7092deef 100644
--- a/apps/tests/src/routes/nested/(ignored)route0.tsx
+++ b/apps/tests/src/routes/nested/(ignored)route0.tsx
@@ -1,4 +1,3 @@
-
export default function nested() {
return nested route 0 ;
}
diff --git a/apps/tests/src/routes/nested/(level1)/(ignored)route1.tsx b/apps/tests/src/routes/nested/(level1)/(ignored)route1.tsx
index 471db7aaa..ec6169cd4 100644
--- a/apps/tests/src/routes/nested/(level1)/(ignored)route1.tsx
+++ b/apps/tests/src/routes/nested/(level1)/(ignored)route1.tsx
@@ -1,4 +1,3 @@
-
export default function nested() {
return nested route 1 ;
}
diff --git a/apps/tests/src/routes/nested/(level1)/(level2)/(ignored)route2.tsx b/apps/tests/src/routes/nested/(level1)/(level2)/(ignored)route2.tsx
index fcc953235..b59f52e94 100644
--- a/apps/tests/src/routes/nested/(level1)/(level2)/(ignored)route2.tsx
+++ b/apps/tests/src/routes/nested/(level1)/(level2)/(ignored)route2.tsx
@@ -1,4 +1,3 @@
-
export default function nested() {
return nested route 2 ;
}
diff --git a/apps/tests/src/routes/nested/(level1)/(level2)/route3.tsx b/apps/tests/src/routes/nested/(level1)/(level2)/route3.tsx
index 3d0eea984..61e0b761f 100644
--- a/apps/tests/src/routes/nested/(level1)/(level2)/route3.tsx
+++ b/apps/tests/src/routes/nested/(level1)/(level2)/route3.tsx
@@ -1,4 +1,3 @@
-
export default function nested() {
return nested route 3 ;
}
diff --git a/apps/tests/src/routes/node-builtin-nested.tsx b/apps/tests/src/routes/node-builtin-nested.tsx
index e1f27c2df..988de7139 100644
--- a/apps/tests/src/routes/node-builtin-nested.tsx
+++ b/apps/tests/src/routes/node-builtin-nested.tsx
@@ -1,17 +1,15 @@
-import { join } from 'node:path';
+import { join } from "node:path";
import { createEffect, createSignal } from "solid-js";
function serverFnWithNodeBuiltin() {
"use server";
- return join('can','externalize');
+ return join("can", "externalize");
}
export default function App() {
const [output, setOutput] = createSignal<{ serverFnWithNodeBuiltin?: string }>({});
-
-
createEffect(async () => {
const result = await serverFnWithNodeBuiltin();
setOutput(prev => ({ ...prev, serverFnWithNodeBuiltin: result }));
diff --git a/apps/tests/src/routes/node-builtin-toplevel.tsx b/apps/tests/src/routes/node-builtin-toplevel.tsx
index b9ca3db82..3f5fb170c 100644
--- a/apps/tests/src/routes/node-builtin-toplevel.tsx
+++ b/apps/tests/src/routes/node-builtin-toplevel.tsx
@@ -1,4 +1,3 @@
-
import { createEffect, createSignal } from "solid-js";
import { serverFnWithNodeBuiltin } from "~/functions/use-node-builtin";
diff --git a/apps/tests/src/routes/referencing-multiple-export-named-functions-in-the-same-file.tsx b/apps/tests/src/routes/referencing-multiple-export-named-functions-in-the-same-file.tsx
index 6d477bd43..f4f81315e 100644
--- a/apps/tests/src/routes/referencing-multiple-export-named-functions-in-the-same-file.tsx
+++ b/apps/tests/src/routes/referencing-multiple-export-named-functions-in-the-same-file.tsx
@@ -1,4 +1,4 @@
-import { TextRenderTestComponent as ExternalCuteFaceDisplay} from "../functions/text-render-test-component";
+import { TextRenderTestComponent as ExternalCuteFaceDisplay } from "../functions/text-render-test-component";
export function TextRenderTestComponent() {
return <>(´。• ᵕ •。`) ♡>;
@@ -15,9 +15,11 @@ export const testObjectExport = {
};
export default function () {
- return <>
-
-
-
- >;
+ return (
+ <>
+
+
+
+ >
+ );
}
diff --git a/apps/tests/src/routes/text-plain-response.tsx b/apps/tests/src/routes/text-plain-response.tsx
index 5fc11d61d..ab8fbfd8a 100644
--- a/apps/tests/src/routes/text-plain-response.tsx
+++ b/apps/tests/src/routes/text-plain-response.tsx
@@ -12,4 +12,4 @@ export default function App() {
);
-};
+}
diff --git a/apps/tests/src/routes/treeshaking/treeshake.server.test.ts b/apps/tests/src/routes/treeshaking/treeshake.server.test.ts
index 4926f0c80..c1fe56750 100644
--- a/apps/tests/src/routes/treeshaking/treeshake.server.test.ts
+++ b/apps/tests/src/routes/treeshaking/treeshake.server.test.ts
@@ -8,7 +8,7 @@ describe("Make sure treeshaking works", () => {
const buildDir = path.resolve(process.cwd(), ".output/public/_build/assets");
const files = await readdir(buildDir);
const targetFile = files.find(
- file => file.startsWith("(no-side-effects)-") && file.endsWith(".js")
+ file => file.startsWith("(no-side-effects)-") && file.endsWith(".js"),
);
if (!targetFile) {
throw new Error("Treeshaking test: No target file not found");
diff --git a/apps/tests/vite.config.ts b/apps/tests/vite.config.ts
index fc5997e4f..4149be667 100644
--- a/apps/tests/vite.config.ts
+++ b/apps/tests/vite.config.ts
@@ -3,8 +3,8 @@ import { solidStart } from "../../packages/start/src/config";
import { nitroV2Plugin } from "../../packages/start-nitro-v2-vite-plugin/src";
export default defineConfig({
- server: {
- port: 3000,
- },
- plugins: [solidStart(), nitroV2Plugin()],
+ server: {
+ port: 3000,
+ },
+ plugins: [solidStart(), nitroV2Plugin()],
});
diff --git a/apps/tests/vitest.config.ts b/apps/tests/vitest.config.ts
index c433b3c70..9255aca52 100644
--- a/apps/tests/vitest.config.ts
+++ b/apps/tests/vitest.config.ts
@@ -15,8 +15,8 @@ export default defineConfig({
test: {
include: ["**/*.server.test.ts"], // Matches the tree-shaking test
name: { label: "Node Logic", color: "green" },
- environment: "node"
- }
+ environment: "node",
+ },
},
{
// 2. BROWSER Project (For Solid components and DOM interaction)
@@ -30,10 +30,10 @@ export default defineConfig({
provider: playwright(),
enabled: true,
headless: true,
- instances: [{ browser: "chromium" }]
- }
- }
- }
- ]
- }
+ instances: [{ browser: "chromium" }],
+ },
+ },
+ },
+ ],
+ },
});
diff --git a/package.json b/package.json
index a4973f35f..3953f708d 100644
--- a/package.json
+++ b/package.json
@@ -25,11 +25,13 @@
"packages:clean": "pnpx rimraf ./packages/*/node_modules/ ./packages/*/dist/",
"clean:test": "pnpx rimraf .tmp",
"release": "pnpm build && changeset publish",
+ "format": "pnpm oxfmt",
"rewrite-exports": "pnpm --filter='./packages/*' -c exec \"echo \\$(cat package.json | jq '.exports = .publishConfig.exports') > package.json\""
},
"devDependencies": {
"@changesets/cli": "^2.29.8",
"citty": "^0.1.5",
+ "oxfmt": "^0.14.0",
"tinyglobby": "^0.2.2",
"tippy.js": "^6.3.7",
"typescript": "^5.7.0"
diff --git a/packages/start-nitro-v2-vite-plugin/src/index.ts b/packages/start-nitro-v2-vite-plugin/src/index.ts
index 131182a69..03d1934bb 100644
--- a/packages/start-nitro-v2-vite-plugin/src/index.ts
+++ b/packages/start-nitro-v2-vite-plugin/src/index.ts
@@ -5,7 +5,7 @@ import {
type Nitro,
type NitroConfig,
prepare,
- prerender
+ prerender,
} from "nitropack";
import { promises as fsp } from "node:fs";
import path, { dirname, resolve } from "node:path";
@@ -33,7 +33,7 @@ export function nitroV2Plugin(nitroConfig?: UserNitroConfig): PluginOption {
if (file.isEntry) {
if (entryFile !== undefined) {
this.error(
- `Multiple entry points found for service "${this.environment.name}". Only one entry point is allowed.`
+ `Multiple entry points found for service "${this.environment.name}". Only one entry point is allowed.`,
);
}
entryFile = file.fileName;
@@ -45,7 +45,7 @@ export function nitroV2Plugin(nitroConfig?: UserNitroConfig): PluginOption {
}
ssrEntryFile = entryFile!;
ssrBundle = bundle;
- }
+ },
},
config() {
return {
@@ -54,12 +54,12 @@ export function nitroV2Plugin(nitroConfig?: UserNitroConfig): PluginOption {
consumer: "server",
build: {
commonjsOptions: {
- include: []
+ include: [],
},
ssr: true,
- sourcemap: true
- }
- }
+ sourcemap: true,
+ },
+ },
},
builder: {
sharedPlugins: true,
@@ -80,7 +80,7 @@ export function nitroV2Plugin(nitroConfig?: UserNitroConfig): PluginOption {
preset: "node-server",
typescript: {
generateTsConfig: false,
- generateRuntimeConfigTypes: false
+ generateRuntimeConfigTypes: false,
},
...nitroConfig,
dev: false,
@@ -88,33 +88,33 @@ export function nitroV2Plugin(nitroConfig?: UserNitroConfig): PluginOption {
{
dir: client.config.build.outDir,
maxAge: 31536000, // 1 year
- baseURL: "/"
- }
+ baseURL: "/",
+ },
],
renderer: virtualEntry,
rollupConfig: {
...nitroConfig?.rollupConfig,
- plugins: [virtualBundlePlugin(ssrBundle) as any]
+ plugins: [virtualBundlePlugin(ssrBundle) as any],
},
experimental: {
...nitroConfig?.experimental,
- asyncContext: true
+ asyncContext: true,
},
virtual: {
...nitroConfig?.virtual,
[virtualEntry]: `import { fromWebHandler } from 'h3'
import handler from '${ssrEntryFile}'
- export default fromWebHandler(handler.fetch)`
- }
+ export default fromWebHandler(handler.fetch)`,
+ },
};
const nitro = await createNitro(resolvedNitroConfig);
await buildNitroEnvironment(nitro, () => build(nitro));
- }
- }
+ },
+ },
};
- }
+ },
},
nitroConfig?.preset === "netlify" && {
name: "solid-start-nitro-netlify-fix",
@@ -123,11 +123,11 @@ export function nitroV2Plugin(nitroConfig?: UserNitroConfig): PluginOption {
return {
environments: {
client: { build: { outDir: ".solid-start/client" } },
- ssr: { build: { outDir: ".solid-start/server" } }
- }
+ ssr: { build: { outDir: ".solid-start/server" } },
+ },
};
- }
- }
+ },
+ },
];
}
@@ -161,7 +161,7 @@ function virtualBundlePlugin(ssrBundle: Rollup.OutputBundle): PluginOption {
if (content.type === "chunk") {
const virtualModule: VirtualModule = {
code: content.code,
- map: null
+ map: null,
};
const maybeMap = ssrBundle[`${fileName}.map`];
if (maybeMap && maybeMap.type === "asset") {
@@ -193,6 +193,6 @@ function virtualBundlePlugin(ssrBundle: Rollup.OutputBundle): PluginOption {
return null;
}
return m;
- }
+ },
};
}
diff --git a/packages/start/scripts/build.js b/packages/start/scripts/build.js
index 82064ab7e..79e50409b 100644
--- a/packages/start/scripts/build.js
+++ b/packages/start/scripts/build.js
@@ -9,7 +9,7 @@ await Promise.all(
fs.cp(
path.join(import.meta.dirname, "../src", file),
path.join(import.meta.dirname, "../dist", file),
- { recursive: true }
- )
- )
+ { recursive: true },
+ ),
+ ),
);
diff --git a/packages/start/scripts/validate-imports.js b/packages/start/scripts/validate-imports.js
index ef10b8cf4..f10845aa2 100755
--- a/packages/start/scripts/validate-imports.js
+++ b/packages/start/scripts/validate-imports.js
@@ -115,7 +115,7 @@ function extractImportExportStatements(content, filePath) {
// Export from: export { ... } from '...'
/export\s+(?:\{[^}]*\}|\*)\s+from\s+['"`]([^'"`]+)['"`]/g,
// Export default from: export { default } from '...'
- /export\s+\{\s*default\s*\}\s+from\s+['"`]([^'"`]+)['"`]/g
+ /export\s+\{\s*default\s*\}\s+from\s+['"`]([^'"`]+)['"`]/g,
// Note: Dynamic imports are excluded as they're handled by bundlers
];
@@ -147,7 +147,7 @@ function extractImportExportStatements(content, filePath) {
path: importPath,
line: lineNumber + 1,
fullLine: line.trim(),
- filePath
+ filePath,
});
}
}
@@ -175,7 +175,7 @@ function validateFile(filePath) {
line: statement.line,
importPath: statement.path,
fullLine: statement.fullLine,
- type: "invalid-extension"
+ type: "invalid-extension",
});
} else if (!hasValidExtension(statement.path)) {
errors.push({
@@ -183,7 +183,7 @@ function validateFile(filePath) {
line: statement.line,
importPath: statement.path,
fullLine: statement.fullLine,
- type: "missing-extension"
+ type: "missing-extension",
});
}
}
@@ -243,7 +243,7 @@ function validateImports() {
if (missingExtensionErrors.length > 0) {
console.log(
- `❌ Found ${missingExtensionErrors.length} relative import(s) without extensions:\n`
+ `❌ Found ${missingExtensionErrors.length} relative import(s) without extensions:\n`,
);
const missingByFile = new Map();
@@ -262,7 +262,7 @@ function validateImports() {
console.log(` Line ${error.line}: ${error.importPath}`);
console.log(` ${error.fullLine}`);
console.log(
- ` ${"".padStart(error.fullLine.indexOf(error.importPath), " ")}${"".padStart(error.importPath.length, "^")}`
+ ` ${"".padStart(error.fullLine.indexOf(error.importPath), " ")}${"".padStart(error.importPath.length, "^")}`,
);
});
console.log("");
@@ -271,7 +271,7 @@ function validateImports() {
if (invalidExtensionErrors.length > 0) {
console.log(
- `❌ Found ${invalidExtensionErrors.length} relative import(s) with invalid extensions:\n`
+ `❌ Found ${invalidExtensionErrors.length} relative import(s) with invalid extensions:\n`,
);
const invalidByFile = new Map();
@@ -290,7 +290,7 @@ function validateImports() {
console.log(` Line ${error.line}: ${error.importPath}`);
console.log(` ${error.fullLine}`);
console.log(
- ` ${"".padStart(error.fullLine.indexOf(error.importPath), " ")}${"".padStart(error.importPath.length, "^")}`
+ ` ${"".padStart(error.fullLine.indexOf(error.importPath), " ")}${"".padStart(error.importPath.length, "^")}`,
);
});
console.log("");
diff --git a/packages/start/src/client/mount.ts b/packages/start/src/client/mount.ts
index ac22d2196..744e759a9 100644
--- a/packages/start/src/client/mount.ts
+++ b/packages/start/src/client/mount.ts
@@ -5,7 +5,7 @@ import {
getHydrationKey,
getOwner,
hydrate,
- type MountableElement
+ type MountableElement,
} from "solid-js/web";
/**
@@ -48,14 +48,14 @@ export function mount(fn: () => JSX.Element, el: MountableElement) {
(a as any).__$owner = getOwner();
});
return;
- }
+ },
});
map.set(el, props);
hydrate(() => createComponent(Component, props[0]), el, {
renderId: hk.slice(0, hk.length - 1) + `${1 + Number(el.dataset.offset)}-`,
- owner: lookupOwner(el)
+ owner: lookupOwner(el),
});
delete el.dataset.hk;
@@ -84,8 +84,8 @@ export function mount(fn: () => JSX.Element, el: MountableElement) {
/* @vite-ignore */ import.meta.env.MANIFEST["client"]!.chunks[
asset.split("#")[0] as string
]!.output.path
- )
- )
+ ),
+ ),
)
.then(() => {
islands.forEach((el: HTMLElement) => {
diff --git a/packages/start/src/config/constants.ts b/packages/start/src/config/constants.ts
index 2dbf16159..cb2190aa0 100644
--- a/packages/start/src/config/constants.ts
+++ b/packages/start/src/config/constants.ts
@@ -10,10 +10,10 @@ export const VIRTUAL_MODULES = {
serverFnManifest: "solidstart:server-fn-manifest",
clientEntry: "solid-start:client-entry",
serverEntry: "solid-start:server-entry",
- app: "solid-start:app"
+ app: "solid-start:app",
} as const;
export const VITE_ENVIRONMENTS = {
client: "client",
- server: "ssr"
-}
+ server: "ssr",
+};
diff --git a/packages/start/src/config/dev-server.ts b/packages/start/src/config/dev-server.ts
index 2913d0dff..6d783312e 100644
--- a/packages/start/src/config/dev-server.ts
+++ b/packages/start/src/config/dev-server.ts
@@ -1,84 +1,80 @@
import { NodeRequest, sendNodeResponse } from "srvx/node";
import {
- type Connect,
- isRunnableDevEnvironment,
- type PluginOption,
- type ViteDevServer,
+ type Connect,
+ isRunnableDevEnvironment,
+ type PluginOption,
+ type ViteDevServer,
} from "vite";
import { VITE_ENVIRONMENTS } from "./constants.ts";
export function devServer(): Array {
- return [
- {
- name: "solid-start-dev-server",
- configureServer(viteDevServer) {
- (globalThis as any).VITE_DEV_SERVER = viteDevServer;
- return async () => {
- if (viteDevServer.config.server.middlewareMode) return
+ return [
+ {
+ name: "solid-start-dev-server",
+ configureServer(viteDevServer) {
+ (globalThis as any).VITE_DEV_SERVER = viteDevServer;
+ return async () => {
+ if (viteDevServer.config.server.middlewareMode) return;
- const serverEnv =
- viteDevServer.environments[VITE_ENVIRONMENTS.server];
+ const serverEnv = viteDevServer.environments[VITE_ENVIRONMENTS.server];
- if (!serverEnv) throw new Error("Server environment not found");
- if (
- // do not check via `isFetchableDevEnvironment` since nitro does implement the `FetchableDevEnvironment` interface but not via inheritance (which this helper checks)
- "dispatchFetch" in serverEnv
- )
- return;
- // another plugin is controlling the dev server
- if (!isRunnableDevEnvironment(serverEnv)) {
+ if (!serverEnv) throw new Error("Server environment not found");
+ if (
+ // do not check via `isFetchableDevEnvironment` since nitro does implement the `FetchableDevEnvironment` interface but not via inheritance (which this helper checks)
+ "dispatchFetch" in serverEnv
+ )
return;
- }
+ // another plugin is controlling the dev server
+ if (!isRunnableDevEnvironment(serverEnv)) {
+ return;
+ }
globalThis.USING_SOLID_START_DEV_SERVER = true;
- removeHtmlMiddlewares(viteDevServer);
+ removeHtmlMiddlewares(viteDevServer);
- viteDevServer.middlewares.use(async (req, res) => {
- if (req.originalUrl) {
- req.url = req.originalUrl;
- }
- const webReq = new NodeRequest({ req, res });
+ viteDevServer.middlewares.use(async (req, res) => {
+ if (req.originalUrl) {
+ req.url = req.originalUrl;
+ }
+ const webReq = new NodeRequest({ req, res });
- try {
- const serverEntry: {
- default: { fetch: (req: Request) => Promise };
- } = await serverEnv.runner.import("./src/entry-server.tsx");
+ try {
+ const serverEntry: {
+ default: { fetch: (req: Request) => Promise };
+ } = await serverEnv.runner.import("./src/entry-server.tsx");
- const webRes = await serverEntry.default.fetch(webReq);
+ const webRes = await serverEntry.default.fetch(webReq);
- return sendNodeResponse(res, webRes);
- } catch (e: unknown) {
- console.error(e);
- viteDevServer.ssrFixStacktrace(e as Error);
+ return sendNodeResponse(res, webRes);
+ } catch (e: unknown) {
+ console.error(e);
+ viteDevServer.ssrFixStacktrace(e as Error);
- if (
- webReq.headers.get("content-type")?.includes("application/json")
- ) {
- return sendNodeResponse(
- res,
- Response.json(
- {
- status: 500,
- error: "Internal Server Error",
- message:
- "An unexpected error occurred. Please try again later.",
- timestamp: new Date().toISOString(),
- },
- {
- status: 500,
- headers: {
- "Content-Type": "application/json",
- },
- },
- ),
- );
- }
+ if (webReq.headers.get("content-type")?.includes("application/json")) {
+ return sendNodeResponse(
+ res,
+ Response.json(
+ {
+ status: 500,
+ error: "Internal Server Error",
+ message: "An unexpected error occurred. Please try again later.",
+ timestamp: new Date().toISOString(),
+ },
+ {
+ status: 500,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ },
+ ),
+ );
+ }
- return sendNodeResponse(
- res,
- new Response(
- `
+ return sendNodeResponse(
+ res,
+ new Response(
+ `
@@ -87,26 +83,26 @@ export function devServer(): Array {
`,
- {
- status: 500,
- headers: { "Content-Type": "text/html" },
- },
- ),
- );
- }
- });
- };
- },
- },
- ];
+ {
+ status: 500,
+ headers: { "Content-Type": "text/html" },
+ },
+ ),
+ );
+ }
+ });
+ };
+ },
+ },
+ ];
}
/**
@@ -115,21 +111,21 @@ export function devServer(): Array {
* @param server
*/
function removeHtmlMiddlewares(server: ViteDevServer) {
- const html_middlewares = [
- "viteIndexHtmlMiddleware",
- "vite404Middleware",
- "viteSpaFallbackMiddleware",
- ];
- for (let i = server.middlewares.stack.length - 1; i > 0; i--) {
- if (
- html_middlewares.includes(
- // @ts-expect-error
- server.middlewares.stack[i].handle.name,
- )
- ) {
- server.middlewares.stack.splice(i, 1);
- }
- }
+ const html_middlewares = [
+ "viteIndexHtmlMiddleware",
+ "vite404Middleware",
+ "viteSpaFallbackMiddleware",
+ ];
+ for (let i = server.middlewares.stack.length - 1; i > 0; i--) {
+ if (
+ html_middlewares.includes(
+ // @ts-expect-error
+ server.middlewares.stack[i].handle.name,
+ )
+ ) {
+ server.middlewares.stack.splice(i, 1);
+ }
+ }
}
/**
@@ -139,11 +135,11 @@ function removeHtmlMiddlewares(server: ViteDevServer) {
* @returns
*/
function prepareError(req: Connect.IncomingMessage, error: unknown) {
- const e = error as Error;
- return {
- message: `An error occured while server rendering ${req.url}:\n\n\t${
- typeof e === "string" ? e : e.message
- } `,
- stack: typeof e === "string" ? "" : e.stack,
- };
+ const e = error as Error;
+ return {
+ message: `An error occured while server rendering ${req.url}:\n\n\t${
+ typeof e === "string" ? e : e.message
+ } `,
+ stack: typeof e === "string" ? "" : e.stack,
+ };
}
diff --git a/packages/start/src/config/fs-router.ts b/packages/start/src/config/fs-router.ts
index 668d61a95..fdc90bd0c 100644
--- a/packages/start/src/config/fs-router.ts
+++ b/packages/start/src/config/fs-router.ts
@@ -1,177 +1,162 @@
import type { ExportSpecifier } from "es-module-lexer";
import {
- analyzeModule,
- BaseFileSystemRouter,
- cleanPath,
- type FileSystemRouterConfig,
+ analyzeModule,
+ BaseFileSystemRouter,
+ cleanPath,
+ type FileSystemRouterConfig,
} from "./fs-routes/router.ts";
export class SolidStartClientFileRouter extends BaseFileSystemRouter {
- toPath(src: string) {
- const routePath = cleanPath(src, this.config)
- // remove the initial slash
- .slice(1)
- .replace(/index$/, "")
- .replace(/\[([^/]+)\]/g, (_, m) => {
- if (m.length > 3 && m.startsWith("...")) {
- return `*${m.slice(3)}`;
- }
- if (m.length > 2 && m.startsWith("[") && m.endsWith("]")) {
- return `:${m.slice(1, -1)}?`;
- }
- return `:${m}`;
- });
+ toPath(src: string) {
+ const routePath = cleanPath(src, this.config)
+ // remove the initial slash
+ .slice(1)
+ .replace(/index$/, "")
+ .replace(/\[([^/]+)\]/g, (_, m) => {
+ if (m.length > 3 && m.startsWith("...")) {
+ return `*${m.slice(3)}`;
+ }
+ if (m.length > 2 && m.startsWith("[") && m.endsWith("]")) {
+ return `:${m.slice(1, -1)}?`;
+ }
+ return `:${m}`;
+ });
- return routePath?.length > 0 ? `/${routePath}` : "/";
- }
+ return routePath?.length > 0 ? `/${routePath}` : "/";
+ }
- toRoute(src: string) {
- const path = this.toPath(src);
+ toRoute(src: string) {
+ const path = this.toPath(src);
- if (src.endsWith(".md") || src.endsWith(".mdx")) {
- return {
- page: true,
- $component: {
- src: src,
- pick: ["$css"],
- },
- $$route: undefined,
- path,
- // filePath: src
- };
- }
+ if (src.endsWith(".md") || src.endsWith(".mdx")) {
+ return {
+ page: true,
+ $component: {
+ src: src,
+ pick: ["$css"],
+ },
+ $$route: undefined,
+ path,
+ // filePath: src
+ };
+ }
- const [_, exports] = analyzeModule(src);
- const hasDefault = !!exports.find((e) => e.n === "default");
- const hasRouteConfig = !!exports.find((e) => e.n === "route");
- if (hasDefault) {
- return {
- page: true,
- $component: {
- src: src,
- pick: [
- ...exports
- .filter((e) => e.n === e.ln && e.n !== "route")
- .map((e) => e.n),
- "default",
- "$css",
- ],
- },
- $$route: hasRouteConfig
- ? {
- src: src,
- pick: ["route"],
- }
- : undefined,
- path,
- // filePath: src
- };
- }
- }
+ const [_, exports] = analyzeModule(src);
+ const hasDefault = !!exports.find(e => e.n === "default");
+ const hasRouteConfig = !!exports.find(e => e.n === "route");
+ if (hasDefault) {
+ return {
+ page: true,
+ $component: {
+ src: src,
+ pick: [
+ ...exports.filter(e => e.n === e.ln && e.n !== "route").map(e => e.n),
+ "default",
+ "$css",
+ ],
+ },
+ $$route: hasRouteConfig
+ ? {
+ src: src,
+ pick: ["route"],
+ }
+ : undefined,
+ path,
+ // filePath: src
+ };
+ }
+ }
}
-const HTTP_METHODS = [
- "HEAD",
- "GET",
- "POST",
- "PUT",
- "DELETE",
- "PATCH",
- "OPTIONS",
-];
+const HTTP_METHODS = ["HEAD", "GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"];
function createHTTPHandlers(src: string, exports: readonly ExportSpecifier[]) {
- const handlers: Record = {};
- for (const exp of exports) {
- if (HTTP_METHODS.includes(exp.n)) {
- handlers[`$${exp.n}`] = {
- src: src,
- pick: [exp.n],
- };
- if (exp.n === "GET" && !exports.find((exp) => exp.n === "HEAD")) {
- handlers.$HEAD = {
- src: src,
- pick: [exp.n],
- };
- }
- }
- }
+ const handlers: Record = {};
+ for (const exp of exports) {
+ if (HTTP_METHODS.includes(exp.n)) {
+ handlers[`$${exp.n}`] = {
+ src: src,
+ pick: [exp.n],
+ };
+ if (exp.n === "GET" && !exports.find(exp => exp.n === "HEAD")) {
+ handlers.$HEAD = {
+ src: src,
+ pick: [exp.n],
+ };
+ }
+ }
+ }
- return handlers;
+ return handlers;
}
export class SolidStartServerFileRouter extends BaseFileSystemRouter {
- declare config: FileSystemRouterConfig & { dataOnly?: boolean };
+ declare config: FileSystemRouterConfig & { dataOnly?: boolean };
- constructor(config: FileSystemRouterConfig & { dataOnly?: boolean }) {
- super(config);
- }
+ constructor(config: FileSystemRouterConfig & { dataOnly?: boolean }) {
+ super(config);
+ }
- toPath(src: string) {
- const routePath = cleanPath(src, this.config)
- // remove the initial slash
- .slice(1)
- .replace(/index$/, "")
- .replace(/\[([^/]+)\]/g, (_, m) => {
- if (m.length > 3 && m.startsWith("...")) {
- return `*${m.slice(3)}`;
- }
- if (m.length > 2 && m.startsWith("[") && m.endsWith("]")) {
- return `:${m.slice(1, -1)}?`;
- }
- return `:${m}`;
- });
+ toPath(src: string) {
+ const routePath = cleanPath(src, this.config)
+ // remove the initial slash
+ .slice(1)
+ .replace(/index$/, "")
+ .replace(/\[([^/]+)\]/g, (_, m) => {
+ if (m.length > 3 && m.startsWith("...")) {
+ return `*${m.slice(3)}`;
+ }
+ if (m.length > 2 && m.startsWith("[") && m.endsWith("]")) {
+ return `:${m.slice(1, -1)}?`;
+ }
+ return `:${m}`;
+ });
- return routePath?.length > 0 ? `/${routePath}` : "/";
- }
+ return routePath?.length > 0 ? `/${routePath}` : "/";
+ }
- toRoute(src: string) {
- const path = this.toPath(src);
- if (src.endsWith(".md") || src.endsWith(".mdx")) {
- return {
- page: true,
- $component: {
- src: src,
- pick: ["$css"],
- },
- $$route: undefined,
- path,
- };
- }
+ toRoute(src: string) {
+ const path = this.toPath(src);
+ if (src.endsWith(".md") || src.endsWith(".mdx")) {
+ return {
+ page: true,
+ $component: {
+ src: src,
+ pick: ["$css"],
+ },
+ $$route: undefined,
+ path,
+ };
+ }
- const [_, exports] = analyzeModule(src);
- const hasRouteConfig = exports.find((e) => e.n === "route");
- const hasDefault = !!exports.find((e) => e.n === "default");
- const hasAPIRoutes = !!exports.find((exp) => HTTP_METHODS.includes(exp.n));
- if (hasDefault || hasAPIRoutes) {
- return {
- page: hasDefault,
- $component:
- !this.config.dataOnly && hasDefault
- ? {
- src: src,
- pick: [
- ...exports
- .filter(
- (e) =>
- e.n === e.ln &&
- e.n !== "route" &&
- !HTTP_METHODS.includes(e.n),
- )
- .map((e) => e.n),
- "default",
- "$css",
- ],
- }
- : undefined,
- $$route: hasRouteConfig
- ? {
- src: src,
- pick: ["route"],
- }
- : undefined,
- ...createHTTPHandlers(src, exports),
- path,
- };
- }
- }
+ const [_, exports] = analyzeModule(src);
+ const hasRouteConfig = exports.find(e => e.n === "route");
+ const hasDefault = !!exports.find(e => e.n === "default");
+ const hasAPIRoutes = !!exports.find(exp => HTTP_METHODS.includes(exp.n));
+ if (hasDefault || hasAPIRoutes) {
+ return {
+ page: hasDefault,
+ $component:
+ !this.config.dataOnly && hasDefault
+ ? {
+ src: src,
+ pick: [
+ ...exports
+ .filter(e => e.n === e.ln && e.n !== "route" && !HTTP_METHODS.includes(e.n))
+ .map(e => e.n),
+ "default",
+ "$css",
+ ],
+ }
+ : undefined,
+ $$route: hasRouteConfig
+ ? {
+ src: src,
+ pick: ["route"],
+ }
+ : undefined,
+ ...createHTTPHandlers(src, exports),
+ path,
+ };
+ }
+ }
}
diff --git a/packages/start/src/config/fs-routes/fs-watcher.ts b/packages/start/src/config/fs-routes/fs-watcher.ts
index 5e7543293..0437ea947 100644
--- a/packages/start/src/config/fs-routes/fs-watcher.ts
+++ b/packages/start/src/config/fs-routes/fs-watcher.ts
@@ -1,81 +1,77 @@
import type {
- EnvironmentModuleNode,
- FSWatcher,
- ModuleGraph,
- ModuleNode,
- PluginOption,
- ViteDevServer,
+ EnvironmentModuleNode,
+ FSWatcher,
+ ModuleGraph,
+ ModuleNode,
+ PluginOption,
+ ViteDevServer,
} from "vite";
import { moduleId } from "./index.ts";
import type { BaseFileSystemRouter } from "./router.ts";
interface CompiledRouter {
- removeRoute(path: string): void;
- addRoute(path: string): void;
- updateRoute(path: string): void;
- addEventListener(event: "reload", handler: () => void): void;
- removeEventListener(event: "reload", handler: () => void): void;
+ removeRoute(path: string): void;
+ addRoute(path: string): void;
+ updateRoute(path: string): void;
+ addEventListener(event: "reload", handler: () => void): void;
+ removeEventListener(event: "reload", handler: () => void): void;
}
function setupWatcher(watcher: FSWatcher, routes: CompiledRouter): void {
- watcher.on("unlink", (path) => routes.removeRoute(path));
- watcher.on("add", (path) => routes.addRoute(path));
- watcher.on("change", (path) => routes.updateRoute(path));
+ watcher.on("unlink", path => routes.removeRoute(path));
+ watcher.on("add", path => routes.addRoute(path));
+ watcher.on("change", path => routes.updateRoute(path));
}
function createRoutesReloader(
- server: ViteDevServer,
- routes: CompiledRouter,
- environment: "client" | "ssr",
+ server: ViteDevServer,
+ routes: CompiledRouter,
+ environment: "client" | "ssr",
): () => void {
- routes.addEventListener("reload", handleRoutesReload);
- return () => routes.removeEventListener("reload", handleRoutesReload);
+ routes.addEventListener("reload", handleRoutesReload);
+ return () => routes.removeEventListener("reload", handleRoutesReload);
- function handleRoutesReload(): void {
- if (environment === "ssr") {
- // Handle server environment HMR reload
- const serverEnv = server.environments.server;
- if (serverEnv && serverEnv.moduleGraph) {
- const mod: EnvironmentModuleNode | undefined =
- serverEnv.moduleGraph.getModuleById(moduleId);
- if (mod) {
- const seen = new Set();
- serverEnv.moduleGraph.invalidateModule(mod, seen);
- }
- }
- } else {
- // Handle client environment HMR reload
- const { moduleGraph }: { moduleGraph: ModuleGraph } = server;
- const mod: ModuleNode | undefined = moduleGraph.getModuleById(moduleId);
- if (mod) {
- const seen = new Set();
- moduleGraph.invalidateModule(mod, seen);
- server.reloadModule(mod);
- }
- }
+ function handleRoutesReload(): void {
+ if (environment === "ssr") {
+ // Handle server environment HMR reload
+ const serverEnv = server.environments.server;
+ if (serverEnv && serverEnv.moduleGraph) {
+ const mod: EnvironmentModuleNode | undefined =
+ serverEnv.moduleGraph.getModuleById(moduleId);
+ if (mod) {
+ const seen = new Set();
+ serverEnv.moduleGraph.invalidateModule(mod, seen);
+ }
+ }
+ } else {
+ // Handle client environment HMR reload
+ const { moduleGraph }: { moduleGraph: ModuleGraph } = server;
+ const mod: ModuleNode | undefined = moduleGraph.getModuleById(moduleId);
+ if (mod) {
+ const seen = new Set();
+ moduleGraph.invalidateModule(mod, seen);
+ server.reloadModule(mod);
+ }
+ }
- if (!server.hot) {
- server.ws.send({ type: "full-reload" });
- }
- }
+ if (!server.hot) {
+ server.ws.send({ type: "full-reload" });
+ }
+ }
}
export const fileSystemWatcher = (
- routers: Record<"client" | "ssr", BaseFileSystemRouter>,
+ routers: Record<"client" | "ssr", BaseFileSystemRouter>,
): PluginOption => {
- const plugin: PluginOption = {
- name: "fs-watcher",
- async configureServer(server: ViteDevServer) {
- Object.keys(routers).forEach((environment) => {
- const router = (globalThis as any).ROUTERS[environment];
- setupWatcher(server.watcher, router);
- createRoutesReloader(
- server,
- router,
- environment as keyof typeof routers,
- );
- });
- },
- };
- return plugin;
+ const plugin: PluginOption = {
+ name: "fs-watcher",
+ async configureServer(server: ViteDevServer) {
+ Object.keys(routers).forEach(environment => {
+ const router = (globalThis as any).ROUTERS[environment];
+ setupWatcher(server.watcher, router);
+ createRoutesReloader(server, router, environment as keyof typeof routers);
+ });
+ },
+ };
+ return plugin;
};
diff --git a/packages/start/src/config/fs-routes/index.ts b/packages/start/src/config/fs-routes/index.ts
index 81bad92fe..272f7abaa 100644
--- a/packages/start/src/config/fs-routes/index.ts
+++ b/packages/start/src/config/fs-routes/index.ts
@@ -8,131 +8,129 @@ import { treeShake } from "./tree-shake.ts";
export const moduleId = "solid-start:routes";
export interface FsRoutesArgs {
- routers: Record<"client" | "ssr", BaseFileSystemRouter>;
+ routers: Record<"client" | "ssr", BaseFileSystemRouter>;
}
export function fsRoutes({ routers }: FsRoutesArgs): Array {
- (globalThis as any).ROUTERS = routers;
-
- return [
- {
- name: "solid-start-fs-routes",
- enforce: "pre",
- resolveId(id) {
- if (id === moduleId) return id;
- },
- async load(id) {
- const root = this.environment.config.root;
- const isBuild = this.environment.mode === "build";
-
- if (id !== moduleId) return;
- const js = jsCode();
-
- const router = (globalThis as any).ROUTERS[this.environment.name];
-
- const routes = await router.getRoutes();
-
- let routesCode = JSON.stringify(routes ?? [], (k, v) => {
- if (v === undefined) return undefined;
-
- if (k.startsWith("$$")) {
- const buildId = `${v.src}?${v.pick.map((p: any) => `pick=${p}`).join("&")}`;
-
- /**
- * @type {{ [key: string]: string }}
- */
- const refs: Record = {};
- for (var pick of v.pick) {
- refs[pick] = js.addNamedImport(pick, buildId);
- }
- return {
- require: `_$() => ({ ${Object.entries(refs)
- .map(([pick, namedImport]) => `'${pick}': ${namedImport}`)
- .join(", ")} })$_`,
- // src: isBuild ? relative(root, buildId) : buildId
- };
- } else if (k.startsWith("$")) {
- const buildId = `${v.src}?${v.pick.map((p: any) => `pick=${p}`).join("&")}`;
- return {
- src: relative(root, buildId),
- build: isBuild
- ? `_$() => import(/* @vite-ignore */ '${buildId}')$_`
- : undefined,
- import: `_$() => import(/* @vite-ignore */ '${buildId}')$_`
- };
- }
- return v;
- });
-
- routesCode = routesCode.replaceAll('"_$(', "(").replaceAll(')$_"', ")");
-
- const code = `
+ (globalThis as any).ROUTERS = routers;
+
+ return [
+ {
+ name: "solid-start-fs-routes",
+ enforce: "pre",
+ resolveId(id) {
+ if (id === moduleId) return id;
+ },
+ async load(id) {
+ const root = this.environment.config.root;
+ const isBuild = this.environment.mode === "build";
+
+ if (id !== moduleId) return;
+ const js = jsCode();
+
+ const router = (globalThis as any).ROUTERS[this.environment.name];
+
+ const routes = await router.getRoutes();
+
+ let routesCode = JSON.stringify(routes ?? [], (k, v) => {
+ if (v === undefined) return undefined;
+
+ if (k.startsWith("$$")) {
+ const buildId = `${v.src}?${v.pick.map((p: any) => `pick=${p}`).join("&")}`;
+
+ /**
+ * @type {{ [key: string]: string }}
+ */
+ const refs: Record = {};
+ for (var pick of v.pick) {
+ refs[pick] = js.addNamedImport(pick, buildId);
+ }
+ return {
+ require: `_$() => ({ ${Object.entries(refs)
+ .map(([pick, namedImport]) => `'${pick}': ${namedImport}`)
+ .join(", ")} })$_`,
+ // src: isBuild ? relative(root, buildId) : buildId
+ };
+ } else if (k.startsWith("$")) {
+ const buildId = `${v.src}?${v.pick.map((p: any) => `pick=${p}`).join("&")}`;
+ return {
+ src: relative(root, buildId),
+ build: isBuild ? `_$() => import(/* @vite-ignore */ '${buildId}')$_` : undefined,
+ import: `_$() => import(/* @vite-ignore */ '${buildId}')$_`,
+ };
+ }
+ return v;
+ });
+
+ routesCode = routesCode.replaceAll('"_$(', "(").replaceAll(')$_"', ")");
+
+ const code = `
${js.getImportStatements()}
export default ${routesCode}`;
- return code;
- },
- },
- treeShake(),
- fileSystemWatcher(routers),
- ];
+ return code;
+ },
+ },
+ treeShake(),
+ fileSystemWatcher(routers),
+ ];
}
function jsCode() {
- const imports = new Map();
- let vars = 0;
-
- function addImport(p: any) {
- let id = imports.get(p);
- if (!id) {
- id = {};
- imports.set(p, id);
- }
-
- const d = "routeData" + vars++;
- id["default"] = d;
- return d;
- }
-
- function addNamedImport(name: string | number, p: any) {
- let id = imports.get(p);
- if (!id) {
- id = {};
- imports.set(p, id);
- }
-
- const d = "routeData" + vars++;
- id[name] = d;
- return d;
- }
-
- const getNamedExport = (p: any) => {
- const id = imports.get(p);
-
- delete id["default"];
-
- return Object.keys(id).length > 0
- ? `{ ${Object.keys(id)
- .map((k) => `${k} as ${id[k]}`)
- .join(", ")} }`
- : "";
- };
-
- const getImportStatements = () => {
- return `${[...imports.keys()]
- .map(
- (i) =>
- `import ${
- imports.get(i).default
- ? `${imports.get(i).default}${Object.keys(imports.get(i)).length > 1 ? ", " : ""}`
- : ""
- } ${getNamedExport(i)} from '${i}';`,
- )
- .join("\n")}`;
- };
-
- return {
- addImport,
- addNamedImport,
- getImportStatements,
- };
+ const imports = new Map();
+ let vars = 0;
+
+ function addImport(p: any) {
+ let id = imports.get(p);
+ if (!id) {
+ id = {};
+ imports.set(p, id);
+ }
+
+ const d = "routeData" + vars++;
+ id["default"] = d;
+ return d;
+ }
+
+ function addNamedImport(name: string | number, p: any) {
+ let id = imports.get(p);
+ if (!id) {
+ id = {};
+ imports.set(p, id);
+ }
+
+ const d = "routeData" + vars++;
+ id[name] = d;
+ return d;
+ }
+
+ const getNamedExport = (p: any) => {
+ const id = imports.get(p);
+
+ delete id["default"];
+
+ return Object.keys(id).length > 0
+ ? `{ ${Object.keys(id)
+ .map(k => `${k} as ${id[k]}`)
+ .join(", ")} }`
+ : "";
+ };
+
+ const getImportStatements = () => {
+ return `${[...imports.keys()]
+ .map(
+ i =>
+ `import ${
+ imports.get(i).default
+ ? `${imports.get(i).default}${Object.keys(imports.get(i)).length > 1 ? ", " : ""}`
+ : ""
+ } ${getNamedExport(i)} from '${i}';`,
+ )
+ .join("\n")}`;
+ };
+
+ return {
+ addImport,
+ addNamedImport,
+ getImportStatements,
+ };
}
diff --git a/packages/start/src/config/fs-routes/router.ts b/packages/start/src/config/fs-routes/router.ts
index f694acc0f..bfc66c96b 100644
--- a/packages/start/src/config/fs-routes/router.ts
+++ b/packages/start/src/config/fs-routes/router.ts
@@ -27,9 +27,9 @@ export function analyzeModule(src: string) {
esbuild.transformSync(fs.readFileSync(src, "utf-8"), {
jsx: "transform",
format: "esm",
- loader: "tsx"
+ loader: "tsx",
}).code,
- src
+ src,
);
}
@@ -86,9 +86,9 @@ export class BaseFileSystemRouter extends EventTarget {
return {
$component: {
src: src,
- pick: ["default", "$css"]
+ pick: ["default", "$css"],
},
- path
+ path,
// filePath: src
};
}
@@ -123,9 +123,9 @@ export class BaseFileSystemRouter extends EventTarget {
new Event("reload", {
// @ts-ignore
detail: {
- route
- }
- })
+ route,
+ },
+ }),
);
}
diff --git a/packages/start/src/config/fs-routes/tree-shake.ts b/packages/start/src/config/fs-routes/tree-shake.ts
index b27ff1c86..5e69f6eb0 100644
--- a/packages/start/src/config/fs-routes/tree-shake.ts
+++ b/packages/start/src/config/fs-routes/tree-shake.ts
@@ -9,384 +9,363 @@ import { basename } from "pathe";
import type { Plugin, ResolvedConfig, ViteDevServer } from "vite";
type State = Omit & {
- opts: { pick: string[] };
- refs: Set;
- done: boolean;
+ opts: { pick: string[] };
+ refs: Set;
+ done: boolean;
};
function treeShakeTransform({ types: t }: typeof Babel): PluginObj {
- function getIdentifier(path: any) {
- const parentPath = path.parentPath;
- if (parentPath.type === "VariableDeclarator") {
- const pp = parentPath;
- const name = pp.get("id");
- return name.node.type === "Identifier" ? name : null;
- }
- if (parentPath.type === "AssignmentExpression") {
- const pp = parentPath;
- const name = pp.get("left");
- return name.node.type === "Identifier" ? name : null;
- }
- if (path.node.type === "ArrowFunctionExpression") {
- return null;
- }
- return path.node.id && path.node.id.type === "Identifier"
- ? path.get("id")
- : null;
- }
+ function getIdentifier(path: any) {
+ const parentPath = path.parentPath;
+ if (parentPath.type === "VariableDeclarator") {
+ const pp = parentPath;
+ const name = pp.get("id");
+ return name.node.type === "Identifier" ? name : null;
+ }
+ if (parentPath.type === "AssignmentExpression") {
+ const pp = parentPath;
+ const name = pp.get("left");
+ return name.node.type === "Identifier" ? name : null;
+ }
+ if (path.node.type === "ArrowFunctionExpression") {
+ return null;
+ }
+ return path.node.id && path.node.id.type === "Identifier" ? path.get("id") : null;
+ }
- function isIdentifierReferenced(ident: any) {
- const b: Binding | undefined = ident.scope.getBinding(ident.node.name);
- if (b?.referenced) {
- if (b.path.type === "FunctionDeclaration") {
- return !b.constantViolations
- .concat(b.referencePaths)
- .every((ref) => ref.findParent((p) => p === b.path));
- }
- return true;
- }
- return false;
- }
- function markFunction(path: any, state: any) {
- const ident = getIdentifier(path);
- if (ident && ident.node && isIdentifierReferenced(ident)) {
- state.refs.add(ident);
- }
- }
- function markImport(path: any, state: any) {
- const local = path.get("local");
- if (isIdentifierReferenced(local)) {
- state.refs.add(local);
- }
- }
+ function isIdentifierReferenced(ident: any) {
+ const b: Binding | undefined = ident.scope.getBinding(ident.node.name);
+ if (b?.referenced) {
+ if (b.path.type === "FunctionDeclaration") {
+ return !b.constantViolations
+ .concat(b.referencePaths)
+ .every(ref => ref.findParent(p => p === b.path));
+ }
+ return true;
+ }
+ return false;
+ }
+ function markFunction(path: any, state: any) {
+ const ident = getIdentifier(path);
+ if (ident && ident.node && isIdentifierReferenced(ident)) {
+ state.refs.add(ident);
+ }
+ }
+ function markImport(path: any, state: any) {
+ const local = path.get("local");
+ if (isIdentifierReferenced(local)) {
+ state.refs.add(local);
+ }
+ }
- return {
- visitor: {
- Program: {
- enter(path, state) {
- state.refs = new Set();
- state.done = false;
- path.traverse(
- {
- VariableDeclarator(variablePath, variableState: any) {
- if (variablePath.node.id.type === "Identifier") {
- const local = variablePath.get("id");
- if (isIdentifierReferenced(local)) {
- variableState.refs.add(local);
- }
- } else if (variablePath.node.id.type === "ObjectPattern") {
- const pattern = variablePath.get("id");
- const properties = pattern.get(
- "properties",
- ) as Array;
- properties.forEach((p) => {
- const local = p.get(
- p.node.type === "ObjectProperty"
- ? "value"
- : p.node.type === "RestElement"
- ? "argument"
- : (() => {
- throw new Error("invariant");
- })(),
- );
- if (isIdentifierReferenced(local)) {
- variableState.refs.add(local);
- }
- });
- } else if (variablePath.node.id.type === "ArrayPattern") {
- const pattern = variablePath.get("id");
- const elements = pattern.get("elements") as Array;
- elements.forEach((e) => {
- let local: NodePath;
- if (e.node && e.node.type === "Identifier") {
- local = e;
- } else if (e.node && e.node.type === "RestElement") {
- local = e.get("argument");
- } else {
- return;
- }
- if (isIdentifierReferenced(local)) {
- variableState.refs.add(local);
- }
- });
- }
- },
- ExportDefaultDeclaration(exportNamedPath) {
- // if opts.keep is true, we don't remove the routeData export
- if (state.opts.pick && !state.opts.pick.includes("default")) {
- exportNamedPath.remove();
- }
- },
- ExportNamedDeclaration(exportNamedPath) {
- // if opts.keep is false, we don't remove the routeData export
- if (!state.opts.pick) {
- return;
- }
- const specifiers = exportNamedPath.get("specifiers");
- if (specifiers.length) {
- specifiers.forEach((s) => {
- if (
- t.isIdentifier(s.node.exported)
- ? s.node.exported.name
- : state.opts.pick.includes(s.node.exported.value)
- ) {
- s.remove();
- }
- });
- if (exportNamedPath.node.specifiers.length < 1) {
- exportNamedPath.remove();
- }
- return;
- }
- const decl = exportNamedPath.get("declaration");
- if (decl == null || decl.node == null) {
- return;
- }
- switch (decl.node.type) {
- case "FunctionDeclaration": {
- const name = decl.node.id?.name;
- if (
- name &&
- state.opts.pick &&
- !state.opts.pick.includes(name)
- ) {
- exportNamedPath.remove();
- }
- break;
- }
- case "VariableDeclaration": {
- const inner = decl.get("declarations") as Array<
- NodePath
- >;
- inner.forEach((d) => {
- if (d.node.id.type !== "Identifier") {
- return;
- }
- const name = d.node.id.name;
- if (state.opts.pick && !state.opts.pick.includes(name)) {
- d.remove();
- }
- });
- break;
- }
- default: {
- break;
- }
- }
- },
- FunctionDeclaration: markFunction,
- FunctionExpression: markFunction,
- ArrowFunctionExpression: markFunction,
- ImportSpecifier: markImport,
- ImportDefaultSpecifier: markImport,
- ImportNamespaceSpecifier: markImport,
- ImportDeclaration: (path, state) => {
- if (
- path.node.source.value.endsWith(".css") &&
- state.opts.pick &&
- !state.opts.pick.includes("$css")
- ) {
- path.remove();
- }
- },
- },
- state,
- );
+ return {
+ visitor: {
+ Program: {
+ enter(path, state) {
+ state.refs = new Set();
+ state.done = false;
+ path.traverse(
+ {
+ VariableDeclarator(variablePath, variableState: any) {
+ if (variablePath.node.id.type === "Identifier") {
+ const local = variablePath.get("id");
+ if (isIdentifierReferenced(local)) {
+ variableState.refs.add(local);
+ }
+ } else if (variablePath.node.id.type === "ObjectPattern") {
+ const pattern = variablePath.get("id");
+ const properties = pattern.get("properties") as Array;
+ properties.forEach(p => {
+ const local = p.get(
+ p.node.type === "ObjectProperty"
+ ? "value"
+ : p.node.type === "RestElement"
+ ? "argument"
+ : (() => {
+ throw new Error("invariant");
+ })(),
+ );
+ if (isIdentifierReferenced(local)) {
+ variableState.refs.add(local);
+ }
+ });
+ } else if (variablePath.node.id.type === "ArrayPattern") {
+ const pattern = variablePath.get("id");
+ const elements = pattern.get("elements") as Array;
+ elements.forEach(e => {
+ let local: NodePath;
+ if (e.node && e.node.type === "Identifier") {
+ local = e;
+ } else if (e.node && e.node.type === "RestElement") {
+ local = e.get("argument");
+ } else {
+ return;
+ }
+ if (isIdentifierReferenced(local)) {
+ variableState.refs.add(local);
+ }
+ });
+ }
+ },
+ ExportDefaultDeclaration(exportNamedPath) {
+ // if opts.keep is true, we don't remove the routeData export
+ if (state.opts.pick && !state.opts.pick.includes("default")) {
+ exportNamedPath.remove();
+ }
+ },
+ ExportNamedDeclaration(exportNamedPath) {
+ // if opts.keep is false, we don't remove the routeData export
+ if (!state.opts.pick) {
+ return;
+ }
+ const specifiers = exportNamedPath.get("specifiers");
+ if (specifiers.length) {
+ specifiers.forEach(s => {
+ if (
+ t.isIdentifier(s.node.exported)
+ ? s.node.exported.name
+ : state.opts.pick.includes(s.node.exported.value)
+ ) {
+ s.remove();
+ }
+ });
+ if (exportNamedPath.node.specifiers.length < 1) {
+ exportNamedPath.remove();
+ }
+ return;
+ }
+ const decl = exportNamedPath.get("declaration");
+ if (decl == null || decl.node == null) {
+ return;
+ }
+ switch (decl.node.type) {
+ case "FunctionDeclaration": {
+ const name = decl.node.id?.name;
+ if (name && state.opts.pick && !state.opts.pick.includes(name)) {
+ exportNamedPath.remove();
+ }
+ break;
+ }
+ case "VariableDeclaration": {
+ const inner = decl.get("declarations") as Array>;
+ inner.forEach(d => {
+ if (d.node.id.type !== "Identifier") {
+ return;
+ }
+ const name = d.node.id.name;
+ if (state.opts.pick && !state.opts.pick.includes(name)) {
+ d.remove();
+ }
+ });
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ },
+ FunctionDeclaration: markFunction,
+ FunctionExpression: markFunction,
+ ArrowFunctionExpression: markFunction,
+ ImportSpecifier: markImport,
+ ImportDefaultSpecifier: markImport,
+ ImportNamespaceSpecifier: markImport,
+ ImportDeclaration: (path, state) => {
+ if (
+ path.node.source.value.endsWith(".css") &&
+ state.opts.pick &&
+ !state.opts.pick.includes("$css")
+ ) {
+ path.remove();
+ }
+ },
+ },
+ state,
+ );
- const refs = state.refs;
- let count = 0;
- const sweepFunction = (sweepPath: any) => {
- const ident = getIdentifier(sweepPath);
- if (
- ident &&
- ident.node &&
- refs.has(ident) &&
- !isIdentifierReferenced(ident)
- ) {
- ++count;
- if (
- t.isAssignmentExpression(sweepPath.parentPath) ||
- t.isVariableDeclarator(sweepPath.parentPath)
- ) {
- sweepPath.parentPath.remove();
- } else {
- sweepPath.remove();
- }
- }
- };
- function sweepImport(sweepPath: any) {
- const local = sweepPath.get("local");
- if (refs.has(local) && !isIdentifierReferenced(local)) {
- ++count;
- sweepPath.remove();
- if (sweepPath.parent.specifiers.length === 0) {
- sweepPath.parentPath.remove();
- }
- }
- }
- do {
- path.scope.crawl();
- count = 0;
- path.traverse({
- VariableDeclarator(variablePath) {
- if (variablePath.node.id.type === "Identifier") {
- const local = variablePath.get("id");
- if (refs.has(local) && !isIdentifierReferenced(local)) {
- ++count;
- variablePath.remove();
- }
- } else if (variablePath.node.id.type === "ObjectPattern") {
- const pattern = variablePath.get("id");
- const beforeCount = count;
- const properties = pattern.get("properties");
- properties.forEach((p) => {
- const local = p.get(
- p.node.type === "ObjectProperty"
- ? "value"
- : p.node.type === "RestElement"
- ? "argument"
- : (() => {
- throw new Error("invariant");
- })(),
- );
- if (refs.has(local) && !isIdentifierReferenced(local)) {
- ++count;
- p.remove();
- }
- });
- if (
- beforeCount !== count &&
- pattern.get("properties").length < 1
- ) {
- variablePath.remove();
- }
- } else if (variablePath.node.id.type === "ArrayPattern") {
- const pattern = variablePath.get("id");
- const beforeCount = count;
- const elements = pattern.get("elements");
- elements.forEach((e) => {
- let local: NodePath | undefined;
- if (e.node && e.node.type === "Identifier") {
- local = e;
- } else if (e.node && e.node.type === "RestElement") {
- local = e.get("argument");
- } else {
- return;
- }
- if (refs.has(local) && !isIdentifierReferenced(local)) {
- ++count;
- e.remove();
- }
- });
- if (
- beforeCount !== count &&
- pattern.get("elements").length < 1
- ) {
- variablePath.remove();
- }
- }
- },
- FunctionDeclaration: sweepFunction,
- FunctionExpression: sweepFunction,
- ArrowFunctionExpression: sweepFunction,
- ImportSpecifier: sweepImport,
- ImportDefaultSpecifier: sweepImport,
- ImportNamespaceSpecifier: sweepImport,
- });
- } while (count);
- },
- },
- },
- };
+ const refs = state.refs;
+ let count = 0;
+ const sweepFunction = (sweepPath: any) => {
+ const ident = getIdentifier(sweepPath);
+ if (ident && ident.node && refs.has(ident) && !isIdentifierReferenced(ident)) {
+ ++count;
+ if (
+ t.isAssignmentExpression(sweepPath.parentPath) ||
+ t.isVariableDeclarator(sweepPath.parentPath)
+ ) {
+ sweepPath.parentPath.remove();
+ } else {
+ sweepPath.remove();
+ }
+ }
+ };
+ function sweepImport(sweepPath: any) {
+ const local = sweepPath.get("local");
+ if (refs.has(local) && !isIdentifierReferenced(local)) {
+ ++count;
+ sweepPath.remove();
+ if (sweepPath.parent.specifiers.length === 0) {
+ sweepPath.parentPath.remove();
+ }
+ }
+ }
+ do {
+ path.scope.crawl();
+ count = 0;
+ path.traverse({
+ VariableDeclarator(variablePath) {
+ if (variablePath.node.id.type === "Identifier") {
+ const local = variablePath.get("id");
+ if (refs.has(local) && !isIdentifierReferenced(local)) {
+ ++count;
+ variablePath.remove();
+ }
+ } else if (variablePath.node.id.type === "ObjectPattern") {
+ const pattern = variablePath.get("id");
+ const beforeCount = count;
+ const properties = pattern.get("properties");
+ properties.forEach(p => {
+ const local = p.get(
+ p.node.type === "ObjectProperty"
+ ? "value"
+ : p.node.type === "RestElement"
+ ? "argument"
+ : (() => {
+ throw new Error("invariant");
+ })(),
+ );
+ if (refs.has(local) && !isIdentifierReferenced(local)) {
+ ++count;
+ p.remove();
+ }
+ });
+ if (beforeCount !== count && pattern.get("properties").length < 1) {
+ variablePath.remove();
+ }
+ } else if (variablePath.node.id.type === "ArrayPattern") {
+ const pattern = variablePath.get("id");
+ const beforeCount = count;
+ const elements = pattern.get("elements");
+ elements.forEach(e => {
+ let local: NodePath | undefined;
+ if (e.node && e.node.type === "Identifier") {
+ local = e;
+ } else if (e.node && e.node.type === "RestElement") {
+ local = e.get("argument");
+ } else {
+ return;
+ }
+ if (refs.has(local) && !isIdentifierReferenced(local)) {
+ ++count;
+ e.remove();
+ }
+ });
+ if (beforeCount !== count && pattern.get("elements").length < 1) {
+ variablePath.remove();
+ }
+ }
+ },
+ FunctionDeclaration: sweepFunction,
+ FunctionExpression: sweepFunction,
+ ArrowFunctionExpression: sweepFunction,
+ ImportSpecifier: sweepImport,
+ ImportDefaultSpecifier: sweepImport,
+ ImportNamespaceSpecifier: sweepImport,
+ });
+ } while (count);
+ },
+ },
+ },
+ };
}
export function treeShake(): Plugin {
- let config: ResolvedConfig;
- const cache: Record = {};
- let server: ViteDevServer;
+ let config: ResolvedConfig;
+ const cache: Record = {};
+ let server: ViteDevServer;
- async function transform(id: string, code: string) {
- const [path, queryString] = id.split("?");
- const query = new URLSearchParams(queryString);
- if (query.has("pick")) {
- const babel = await import("@babel/core");
- const transformed = await babel.transformAsync(code, {
- plugins: [[treeShakeTransform, { pick: query.getAll("pick") }]],
- parserOpts: {
- plugins: ["jsx", "typescript"],
- },
- filename: basename(id),
- ast: false,
- sourceMaps: true,
- configFile: false,
- babelrc: false,
- sourceFileName: id,
- });
+ async function transform(id: string, code: string) {
+ const [path, queryString] = id.split("?");
+ const query = new URLSearchParams(queryString);
+ if (query.has("pick")) {
+ const babel = await import("@babel/core");
+ const transformed = await babel.transformAsync(code, {
+ plugins: [[treeShakeTransform, { pick: query.getAll("pick") }]],
+ parserOpts: {
+ plugins: ["jsx", "typescript"],
+ },
+ filename: basename(id),
+ ast: false,
+ sourceMaps: true,
+ configFile: false,
+ babelrc: false,
+ sourceFileName: id,
+ });
- return transformed;
- }
- }
- return {
- name: "tree-shake",
- enforce: "pre",
- configResolved(resolvedConfig) {
- config = resolvedConfig;
- },
- configureServer(s) {
- server = s;
- },
- async handleHotUpdate(ctx) {
- if (cache[ctx.file]) {
- const mods = [];
- const newCode = await ctx.read();
- for (const [id, code] of Object.entries(cache[ctx.file])) {
- const transformed = await transform(id, newCode);
- if (!transformed) continue;
+ return transformed;
+ }
+ }
+ return {
+ name: "tree-shake",
+ enforce: "pre",
+ configResolved(resolvedConfig) {
+ config = resolvedConfig;
+ },
+ configureServer(s) {
+ server = s;
+ },
+ async handleHotUpdate(ctx) {
+ if (cache[ctx.file]) {
+ const mods = [];
+ const newCode = await ctx.read();
+ for (const [id, code] of Object.entries(cache[ctx.file])) {
+ const transformed = await transform(id, newCode);
+ if (!transformed) continue;
- const { code: transformedCode } = transformed;
+ const { code: transformedCode } = transformed;
- if (transformedCode !== code) {
- const mod = server.moduleGraph.getModuleById(id);
- if (mod) mods.push(mod);
- }
+ if (transformedCode !== code) {
+ const mod = server.moduleGraph.getModuleById(id);
+ if (mod) mods.push(mod);
+ }
- cache[ctx.file] ??= {};
- cache[ctx.file][id] = transformedCode;
- // server.moduleGraph.setModuleSource(id, code);
- }
+ cache[ctx.file] ??= {};
+ cache[ctx.file][id] = transformedCode;
+ // server.moduleGraph.setModuleSource(id, code);
+ }
- return mods;
- }
- // const mods = [];
- // [...server.moduleGraph.urlToModuleMap.entries()].forEach(([url, m]) => {
- // if (m.file === ctx.file && m.id.includes("pick=")) {
- // if (!m.id.includes("pick=loader")) {
- // mods.push(m);
- // }
- // }
- // });
- // return mods;
- // // this.router.updateRoute(ctx.path);
- // }
- },
- async transform(code, id) {
- const [path, queryString] = id.split("?");
- if (!path) return;
- const query = new URLSearchParams(queryString);
- const ext = path.split(".").pop();
- if (!ext) return;
- if (query.has("pick") && ["js", "jsx", "ts", "tsx"].includes(ext)) {
- const transformed = await transform(id, code);
- if (!transformed?.code) return;
+ return mods;
+ }
+ // const mods = [];
+ // [...server.moduleGraph.urlToModuleMap.entries()].forEach(([url, m]) => {
+ // if (m.file === ctx.file && m.id.includes("pick=")) {
+ // if (!m.id.includes("pick=loader")) {
+ // mods.push(m);
+ // }
+ // }
+ // });
+ // return mods;
+ // // this.router.updateRoute(ctx.path);
+ // }
+ },
+ async transform(code, id) {
+ const [path, queryString] = id.split("?");
+ if (!path) return;
+ const query = new URLSearchParams(queryString);
+ const ext = path.split(".").pop();
+ if (!ext) return;
+ if (query.has("pick") && ["js", "jsx", "ts", "tsx"].includes(ext)) {
+ const transformed = await transform(id, code);
+ if (!transformed?.code) return;
- cache[path] ??= {};
- cache[path][id] = transformed.code;
+ cache[path] ??= {};
+ cache[path][id] = transformed.code;
- return {
- code: transformed.code,
- map: transformed.map,
- };
- }
- },
- };
+ return {
+ code: transformed.code,
+ map: transformed.map,
+ };
+ }
+ },
+ };
}
diff --git a/packages/start/src/config/index.ts b/packages/start/src/config/index.ts
index 599b1c8ae..39a1d0afd 100644
--- a/packages/start/src/config/index.ts
+++ b/packages/start/src/config/index.ts
@@ -33,10 +33,10 @@ export function solidStart(options?: SolidStartOptions): Array {
ssr: true,
devOverlay: true,
experimental: {
- islands: false
+ islands: false,
},
solid: {},
- extensions: []
+ extensions: [],
});
const extensions = [...DEFAULT_EXTENSIONS, ...(start.extensions || [])];
const routeDir = join(start.appRoot, start.routeDir);
@@ -48,7 +48,7 @@ export function solidStart(options?: SolidStartOptions): Array {
const entryExtension = extname(appEntryPath);
const handlers = {
client: `${start.appRoot}/entry-client${entryExtension}`,
- server: `${start.appRoot}/entry-server${entryExtension}`
+ server: `${start.appRoot}/entry-server${entryExtension}`,
};
return [
{
@@ -57,12 +57,12 @@ export function solidStart(options?: SolidStartOptions): Array {
configEnvironment(name) {
return {
define: {
- "import.meta.env.SSR": JSON.stringify(name === VITE_ENVIRONMENTS.server)
+ "import.meta.env.SSR": JSON.stringify(name === VITE_ENVIRONMENTS.server),
},
resolve: {
// remove when https://github.com/solidjs/vite-plugin-solid/pull/228 is released
- externalConditions: ["solid", "node"]
- }
+ externalConditions: ["solid", "node"],
+ },
};
},
async config(_, env) {
@@ -93,9 +93,9 @@ export function solidStart(options?: SolidStartOptions): Array {
rollupOptions: {
input: clientInput,
treeshake: true,
- preserveEntrySignatures: "exports-only"
- }
- }
+ preserveEntrySignatures: "exports-only",
+ },
+ },
},
[VITE_ENVIRONMENTS.server]: {
consumer: "server",
@@ -105,14 +105,14 @@ export function solidStart(options?: SolidStartOptions): Array {
manifest: true,
copyPublicDir: false,
rollupOptions: {
- input: "~/entry-server.tsx"
+ input: "~/entry-server.tsx",
},
outDir: "dist/server",
commonjsOptions: {
- include: [/node_modules/]
- }
- }
- }
+ include: [/node_modules/],
+ },
+ },
+ },
},
resolve: {
alias: {
@@ -121,17 +121,17 @@ export function solidStart(options?: SolidStartOptions): Array {
...(!start.ssr
? {
"@solidjs/start/server": "@solidjs/start/server/spa",
- "@solidjs/start/client": "@solidjs/start/client/spa"
+ "@solidjs/start/client": "@solidjs/start/client/spa",
}
- : {})
- }
+ : {}),
+ },
},
define: {
"import.meta.env.MANIFEST": `globalThis.MANIFEST`,
"import.meta.env.START_SSR": JSON.stringify(start.ssr),
"import.meta.env.START_APP_ENTRY": `"${appEntryPath}"`,
"import.meta.env.START_CLIENT_ENTRY": `"${handlers.client}"`,
- "import.meta.env.START_DEV_OVERLAY": JSON.stringify(start.devOverlay)
+ "import.meta.env.START_DEV_OVERLAY": JSON.stringify(start.devOverlay),
},
builder: {
sharedPlugins: true,
@@ -144,24 +144,24 @@ export function solidStart(options?: SolidStartOptions): Array {
if (!client.isBuilt) await builder.build(client);
if (!server.isBuilt) await builder.build(server);
- }
- }
+ },
+ },
};
- }
+ },
},
manifest(start),
fsRoutes({
routers: {
client: new SolidStartClientFileRouter({
dir: absolute(routeDir, root),
- extensions
+ extensions,
}),
ssr: new SolidStartServerFileRouter({
dir: absolute(routeDir, root),
extensions,
- dataOnly: !start.ssr
- })
- }
+ dataOnly: !start.ssr,
+ }),
+ },
}),
lazy(),
// Must be placed after fsRoutes, as treeShake will remove the
@@ -177,28 +177,28 @@ export function solidStart(options?: SolidStartOptions): Array {
envName: VITE_ENVIRONMENTS.client,
getRuntimeCode: () =>
`import { createServerReference } from "${normalize(
- fileURLToPath(new URL("../server/server-runtime", import.meta.url))
+ fileURLToPath(new URL("../server/server-runtime", import.meta.url)),
)}"`,
- replacer: opts => `createServerReference('${opts.functionId}')`
+ replacer: opts => `createServerReference('${opts.functionId}')`,
},
{
envConsumer: "server",
envName: VITE_ENVIRONMENTS.server,
getRuntimeCode: () =>
`import { createServerReference } from '${normalize(
- fileURLToPath(new URL("../server/server-fns-runtime", import.meta.url))
+ fileURLToPath(new URL("../server/server-fns-runtime", import.meta.url)),
)}'`,
- replacer: opts => `createServerReference(${opts.fn}, '${opts.functionId}')`
- }
+ replacer: opts => `createServerReference(${opts.fn}, '${opts.functionId}')`,
+ },
],
provider: {
envName: VITE_ENVIRONMENTS.server,
getRuntimeCode: () =>
`import { createServerReference } from '${normalize(
- fileURLToPath(new URL("../server/server-fns-runtime", import.meta.url))
+ fileURLToPath(new URL("../server/server-fns-runtime", import.meta.url)),
)}'`,
- replacer: opts => `createServerReference(${opts.fn}, '${opts.functionId}')`
- }
+ replacer: opts => `createServerReference(${opts.fn}, '${opts.functionId}')`,
+ },
}),
{
name: "solid-start:virtual-modules",
@@ -217,20 +217,20 @@ export function solidStart(options?: SolidStartOptions): Array {
if (query.size > 0) id += `?${query.toString()}`;
return id;
}
- }
+ },
},
{
name: "solid-start:capture-client-bundle",
enforce: "post",
generateBundle(_options, bundle) {
globalThis.START_CLIENT_BUNDLE = bundle;
- }
+ },
},
devServer(),
solid({
...start.solid,
ssr: true,
- extensions: extensions.map(ext => `.${ext}`)
- })
+ extensions: extensions.map(ext => `.${ext}`),
+ }),
];
}
diff --git a/packages/start/src/config/lazy.ts b/packages/start/src/config/lazy.ts
index 65602f3bb..f94129383 100644
--- a/packages/start/src/config/lazy.ts
+++ b/packages/start/src/config/lazy.ts
@@ -13,12 +13,12 @@ const idTransform = (id: string): PluginItem => {
path.node.body.unshift(
t.exportNamedDeclaration(
t.variableDeclaration("const", [
- t.variableDeclarator(t.identifier("id$$"), t.stringLiteral(id))
- ])
- )
+ t.variableDeclarator(t.identifier("id$$"), t.stringLiteral(id)),
+ ]),
+ ),
);
- }
- }
+ },
+ },
};
};
@@ -34,13 +34,13 @@ const importTransform = (): PluginItem => {
path.insertAfter(
t.importDeclaration(
[t.importSpecifier(t.identifier("lazy"), t.identifier("lazy"))],
- t.stringLiteral("@solidjs/start/server")
- )
+ t.stringLiteral("@solidjs/start/server"),
+ ),
);
- }
+ },
});
- }
- }
+ },
+ },
};
};
@@ -79,21 +79,21 @@ const lazy = (): PluginOption => {
const transformed = await babel.transformAsync(src, {
plugins,
parserOpts: {
- plugins: ["jsx", "typescript"]
+ plugins: ["jsx", "typescript"],
},
filename: basename(id),
ast: false,
sourceMaps: true,
configFile: false,
babelrc: false,
- sourceFileName: id
+ sourceFileName: id,
});
if (!transformed?.code) return;
const { code, map } = transformed;
return { code, map };
- }
+ },
};
};
diff --git a/packages/start/src/config/manifest.ts b/packages/start/src/config/manifest.ts
index 5a0205c20..e1276d600 100644
--- a/packages/start/src/config/manifest.ts
+++ b/packages/start/src/config/manifest.ts
@@ -17,7 +17,7 @@ export function manifest(start: SolidStartOptions): PluginOption {
return `\0${VIRTUAL_MODULES.clientViteManifest}`;
if (id === VIRTUAL_MODULES.getClientManifest)
return this.resolve(
- new URL("../server/manifest/client-manifest", import.meta.url).pathname
+ new URL("../server/manifest/client-manifest", import.meta.url).pathname,
);
if (id === VIRTUAL_MODULES.getManifest) {
return this.environment.config.consumer === "client"
@@ -36,11 +36,11 @@ export function manifest(start: SolidStartOptions): PluginOption {
clientViteManifest = {};
} else {
const entry = Object.values(globalThis.START_CLIENT_BUNDLE).find(
- v => "isEntry" in v && v.isEntry
+ v => "isEntry" in v && v.isEntry,
);
if (!entry) throw new Error("No client entry found");
clientViteManifest = JSON.parse(
- (globalThis.START_CLIENT_BUNDLE[".vite/manifest.json"] as any).source
+ (globalThis.START_CLIENT_BUNDLE[".vite/manifest.json"] as any).source,
);
}
return `export const clientViteManifest = ${JSON.stringify(clientViteManifest)};`;
@@ -73,12 +73,12 @@ export function manifest(start: SolidStartOptions): PluginOption {
"data-vite-ref": "0",
},
children: () => import("${value}?inline").then(mod => mod.default),
- }`
+ }`,
);
return `export default [${cssAssets.join(",")}]`;
}
}
- }
+ },
};
}
diff --git a/packages/start/src/config/vite-utils.ts b/packages/start/src/config/vite-utils.ts
index de44bd9ea..f5a7d7627 100644
--- a/packages/start/src/config/vite-utils.ts
+++ b/packages/start/src/config/vite-utils.ts
@@ -64,10 +64,7 @@ export function unwrapId(id: string): string {
: id;
}
-export function normalizeViteImportAnalysisUrl(
- environment: DevEnvironment,
- id: string,
-): string {
+export function normalizeViteImportAnalysisUrl(environment: DevEnvironment, id: string): string {
let url = normalizeResolvedIdToUrl(environment, id, { id });
// https://github.com/vitejs/vite/blob/c18ce868c4d70873406e9f7d1b2d0a03264d2168/packages/vite/src/node/plugins/importAnalysis.ts#L416
@@ -101,8 +98,7 @@ export function slash(p: string): string {
return p.replace(windowsSlashRE, "/");
}
-const isWindows =
- typeof process !== "undefined" && process.platform === "win32";
+const isWindows = typeof process !== "undefined" && process.platform === "win32";
export function injectQuery(url: string, queryToInject: string): string {
const { file, postfix } = splitFileAndPostfix(url);
diff --git a/packages/start/src/env.d.ts b/packages/start/src/env.d.ts
index 3ba015c32..a2c99e4fb 100644
--- a/packages/start/src/env.d.ts
+++ b/packages/start/src/env.d.ts
@@ -5,31 +5,29 @@
/* eslint-disable @typescript-eslint/consistent-type-imports */
declare namespace App {
- export interface RequestEventLocals {
- [key: string | symbol]: any;
- }
+ export interface RequestEventLocals {
+ [key: string | symbol]: any;
+ }
}
declare module "solidstart:server-fn-manifest" {
- type ServerFn = (...args: Array) => Promise;
- export function getServerFnById(id: string): Promise;
+ type ServerFn = (...args: Array) => Promise;
+ export function getServerFnById(id: string): Promise;
}
-interface ImportMetaEnv
- extends Record<`VITE_${string}`, any>,
- SolidStartMetaEnv {
- BASE_URL: string;
- MODE: string;
- DEV: boolean;
- PROD: boolean;
- SSR: boolean;
+interface ImportMetaEnv extends Record<`VITE_${string}`, any>, SolidStartMetaEnv {
+ BASE_URL: string;
+ MODE: string;
+ DEV: boolean;
+ PROD: boolean;
+ SSR: boolean;
}
interface SolidStartMetaEnv {
- START_SSR: boolean;
- START_APP_ENTRY: string;
- START_CLIENT_ENTRY: string;
- // START_ISLANDS: boolean;
- // START_DEV_OVERLAY: boolean;
- // SERVER_BASE_URL: string;
+ START_SSR: boolean;
+ START_APP_ENTRY: string;
+ START_CLIENT_ENTRY: string;
+ // START_ISLANDS: boolean;
+ // START_DEV_OVERLAY: boolean;
+ // SERVER_BASE_URL: string;
}
diff --git a/packages/start/src/http/index.ts b/packages/start/src/http/index.ts
index e748dfb5d..0b4339929 100644
--- a/packages/start/src/http/index.ts
+++ b/packages/start/src/http/index.ts
@@ -3,121 +3,105 @@ import * as h3 from "h3";
import { getRequestEvent } from "solid-js/web";
function _setContext(event: H3Event, key: string, value: any) {
- event.context[key] = value;
+ event.context[key] = value;
}
function _getContext(event: H3Event, key: string) {
- return event.context[key];
+ return event.context[key];
}
function getEvent() {
- return getRequestEvent()!.nativeEvent;
+ return getRequestEvent()!.nativeEvent;
}
export function getWebRequest(): Request {
- return getEvent().req;
+ return getEvent().req;
}
export const HTTPEventSymbol = Symbol("$HTTPEvent");
-export function isEvent(
- obj: any,
-): obj is h3.H3Event | { [HTTPEventSymbol]: h3.H3Event } {
- return (
- typeof obj === "object" &&
- (obj instanceof h3.H3Event ||
- obj?.[HTTPEventSymbol] instanceof h3.H3Event ||
- obj?.__is_event__ === true)
- );
- // Implement logic to check if obj is an H3Event
+export function isEvent(obj: any): obj is h3.H3Event | { [HTTPEventSymbol]: h3.H3Event } {
+ return (
+ typeof obj === "object" &&
+ (obj instanceof h3.H3Event ||
+ obj?.[HTTPEventSymbol] instanceof h3.H3Event ||
+ obj?.__is_event__ === true)
+ );
+ // Implement logic to check if obj is an H3Event
}
type Tail = T extends [any, ...infer U] ? U : never;
type PrependOverload<
- TOriginal extends (...args: Array) => any,
- TOverload extends (...args: Array) => any,
+ TOriginal extends (...args: Array) => any,
+ TOverload extends (...args: Array) => any,
> = TOverload & TOriginal;
// add an overload to the function without the event argument
type WrapFunction) => any> = PrependOverload<
- TFn,
- (
- ...args: Parameters extends [
- h3.HTTPEvent | h3.H3Event,
- ...infer TArgs,
- ]
- ? TArgs
- : Parameters
- ) => ReturnType
+ TFn,
+ (
+ ...args: Parameters extends [h3.HTTPEvent | h3.H3Event, ...infer TArgs]
+ ? TArgs
+ : Parameters
+ ) => ReturnType
>;
function createWrapperFunction) => any>(
- h3Function: TFn,
+ h3Function: TFn,
): WrapFunction {
- return ((...args: Array) => {
- const event = args[0];
- if (!isEvent(event)) {
- args.unshift(getEvent());
- } else {
- args[0] =
- event instanceof h3.H3Event || (event as any).__is_event__
- ? event
- : event[HTTPEventSymbol];
- }
-
- return (h3Function as any)(...args);
- }) as any;
+ return ((...args: Array) => {
+ const event = args[0];
+ if (!isEvent(event)) {
+ args.unshift(getEvent());
+ } else {
+ args[0] =
+ event instanceof h3.H3Event || (event as any).__is_event__ ? event : event[HTTPEventSymbol];
+ }
+
+ return (h3Function as any)(...args);
+ }) as any;
}
// Creating wrappers for each utility and exporting them with their original names
// readRawBody => getWebRequest().text()/.arrayBuffer()
type WrappedReadBody = >(
- ...args: Tail>>
+ ...args: Tail>>
) => ReturnType>;
export const readBody = createWrapperFunction(h3.readBody) as PrependOverload<
- typeof h3.readBody,
- WrappedReadBody
+ typeof h3.readBody,
+ WrappedReadBody
>;
-type WrappedGetQuery = <
- T,
- TEventInput = Exclude, undefined>,
->(
- ...args: Tail>>
+type WrappedGetQuery = , undefined>>(
+ ...args: Tail>>
) => ReturnType>;
export const getQuery = createWrapperFunction(h3.getQuery) as PrependOverload<
- typeof h3.getQuery,
- WrappedGetQuery
+ typeof h3.getQuery,
+ WrappedGetQuery
>;
export const isMethod = createWrapperFunction(h3.isMethod);
export const isPreflightRequest = createWrapperFunction(h3.isPreflightRequest);
type WrappedGetValidatedQuery = <
- T extends HTTPEvent,
- TEventInput = InferEventInput<"query", H3Event, T>,
+ T extends HTTPEvent,
+ TEventInput = InferEventInput<"query", H3Event, T>,
>(
- ...args: Tail<
- Parameters>
- >
+ ...args: Tail>>
) => ReturnType>;
-export const getValidatedQuery = createWrapperFunction(
- h3.getValidatedQuery,
-) as PrependOverload;
+export const getValidatedQuery = createWrapperFunction(h3.getValidatedQuery) as PrependOverload<
+ typeof h3.getValidatedQuery,
+ WrappedGetValidatedQuery
+>;
export const getRouterParams = createWrapperFunction(h3.getRouterParams);
export const getRouterParam = createWrapperFunction(h3.getRouterParam);
type WrappedGetValidatedRouterParams = <
- T extends HTTPEvent,
- TEventInput = InferEventInput<"routerParams", H3Event, T>,
+ T extends HTTPEvent,
+ TEventInput = InferEventInput<"routerParams", H3Event, T>,
>(
- ...args: Tail<
- Parameters>
- >
+ ...args: Tail>>
) => ReturnType>;
export const getValidatedRouterParams = createWrapperFunction(
- h3.getValidatedRouterParams,
-) as PrependOverload<
- typeof h3.getValidatedRouterParams,
- WrappedGetValidatedRouterParams
->;
+ h3.getValidatedRouterParams,
+) as PrependOverload;
export const assertMethod = createWrapperFunction(h3.assertMethod);
export const getRequestHeaders = createWrapperFunction(h3.getRequestHeaders);
export const getRequestHeader = createWrapperFunction(h3.getRequestHeader);
@@ -126,53 +110,46 @@ export const getRequestHost = createWrapperFunction(h3.getRequestHost);
export const getRequestProtocol = createWrapperFunction(h3.getRequestProtocol);
export const getRequestIP = createWrapperFunction(h3.getRequestIP);
export const setResponseStatus = (code?: number, text?: string) => {
- const e = getEvent();
+ const e = getEvent();
- if (e.res.status !== undefined) e.res.status = code;
- if (e.res.statusText !== undefined) e.res.statusText = text;
+ if (e.res.status !== undefined) e.res.status = code;
+ if (e.res.statusText !== undefined) e.res.statusText = text;
};
export const getResponseStatus = () => getEvent().res.status;
export const getResponseStatusText = () => getEvent().res.statusText;
-export const getResponseHeaders = () =>
- Object.fromEntries(getEvent().res.headers.entries());
-export const getResponseHeader = (name: string) =>
- getEvent().res.headers.get(name);
+export const getResponseHeaders = () => Object.fromEntries(getEvent().res.headers.entries());
+export const getResponseHeader = (name: string) => getEvent().res.headers.get(name);
export const setResponseHeaders = (values: Record) => {
- const headers = getEvent().res.headers;
- for (const [name, value] of Object.entries(values)) {
- headers.set(name, value);
- }
+ const headers = getEvent().res.headers;
+ for (const [name, value] of Object.entries(values)) {
+ headers.set(name, value);
+ }
};
export const setResponseHeader = (name: string, value: string | string[]) => {
- const headers = getEvent().res.headers;
+ const headers = getEvent().res.headers;
- (Array.isArray(value) ? value : [value]).forEach((value) => {
- headers.set(name, value);
- });
+ (Array.isArray(value) ? value : [value]).forEach(value => {
+ headers.set(name, value);
+ });
};
export const appendResponseHeaders = (values: Record) => {
- const headers = getEvent().res.headers;
- for (const [name, value] of Object.entries(values)) {
- headers.append(name, value);
- }
+ const headers = getEvent().res.headers;
+ for (const [name, value] of Object.entries(values)) {
+ headers.append(name, value);
+ }
};
-export const appendResponseHeader = (
- name: string,
- value: string | string[],
-) => {
- const headers = getEvent().res.headers;
-
- (Array.isArray(value) ? value : [value]).forEach((value) => {
- headers.append(name, value);
- });
+export const appendResponseHeader = (name: string, value: string | string[]) => {
+ const headers = getEvent().res.headers;
+
+ (Array.isArray(value) ? value : [value]).forEach(value => {
+ headers.append(name, value);
+ });
};
export const defaultContentType = (type: string) =>
- getEvent().res.headers.set("content-type", type);
+ getEvent().res.headers.set("content-type", type);
export const proxyRequest = createWrapperFunction(h3.proxyRequest);
export const fetchWithEvent = createWrapperFunction(h3.fetchWithEvent);
-export const getProxyRequestHeaders = createWrapperFunction(
- h3.getProxyRequestHeaders,
-);
+export const getProxyRequestHeaders = createWrapperFunction(h3.getProxyRequestHeaders);
export const parseCookies = createWrapperFunction(h3.parseCookies);
export const getCookie = createWrapperFunction(h3.getCookie);
@@ -181,73 +158,59 @@ export const deleteCookie = createWrapperFunction(h3.deleteCookie);
// not exported :(
type SessionDataT = Record;
type WrappedUseSession = (
- ...args: Tail>>
+ ...args: Tail>>
) => ReturnType>;
-export const useSession: WrappedUseSession = createWrapperFunction(
- h3.useSession,
-);
+export const useSession: WrappedUseSession = createWrapperFunction(h3.useSession);
type WrappedGetSession = (
- ...args: Tail>>
+ ...args: Tail>>
) => ReturnType>;
-export const getSession: WrappedGetSession = createWrapperFunction(
- h3.getSession,
-);
+export const getSession: WrappedGetSession = createWrapperFunction(h3.getSession);
type WrappedUpdateSession = (
- ...args: Tail>>
+ ...args: Tail>>
) => ReturnType>;
-export const updateSession: WrappedUpdateSession = createWrapperFunction(
- h3.updateSession,
-);
+export const updateSession: WrappedUpdateSession = createWrapperFunction(h3.updateSession);
type WrappedSealSession = (
- ...args: Tail>>
+ ...args: Tail>>
) => ReturnType>;
-export const sealSession: WrappedSealSession = createWrapperFunction(
- h3.sealSession,
-);
+export const sealSession: WrappedSealSession = createWrapperFunction(h3.sealSession);
export const unsealSession = createWrapperFunction(h3.unsealSession);
export const clearSession = createWrapperFunction(h3.clearSession);
export const handleCacheHeaders = createWrapperFunction(h3.handleCacheHeaders);
export const handleCors = createWrapperFunction(h3.handleCors);
export const appendCorsHeaders = createWrapperFunction(h3.appendCorsHeaders);
-export const appendCorsPreflightHeaders = createWrapperFunction(
- h3.appendCorsPreflightHeaders,
-);
+export const appendCorsPreflightHeaders = createWrapperFunction(h3.appendCorsPreflightHeaders);
export const appendHeader = appendResponseHeader;
export const appendHeaders = appendResponseHeaders;
export const setHeader = setResponseHeader;
export const setHeaders = setResponseHeaders;
export const getHeader = getRequestHeader;
export const getHeaders = getRequestHeaders;
-export const getRequestFingerprint = createWrapperFunction(
- h3.getRequestFingerprint,
-);
+export const getRequestFingerprint = createWrapperFunction(h3.getRequestFingerprint);
export const getRequestWebStream = () => getEvent().req.body;
export const readFormData = () => getEvent().req.formData();
type WrappedReadValidatedBody = <
- T extends HTTPEvent,
- TEventInput = InferEventInput<"body", H3Event, T>,
+ T extends HTTPEvent,
+ TEventInput = InferEventInput<"body", H3Event, T>,
>(
- ...args: Tail<
- Parameters>
- >
+ ...args: Tail>>
) => ReturnType>;
-export const readValidatedBody = createWrapperFunction(
- h3.readValidatedBody,
-) as PrependOverload;
+export const readValidatedBody = createWrapperFunction(h3.readValidatedBody) as PrependOverload<
+ typeof h3.readValidatedBody,
+ WrappedReadValidatedBody
+>;
export const getContext = createWrapperFunction(_getContext);
export const setContext = createWrapperFunction(_setContext);
-export const removeResponseHeader = (name: string) =>
- getEvent().res.headers.delete(name);
+export const removeResponseHeader = (name: string) => getEvent().res.headers.delete(name);
export const clearResponseHeaders = (headerNames?: string[]) => {
- const headers = getEvent().res.headers;
-
- if (headerNames && headerNames.length > 0) {
- for (const name of headerNames) {
- headers.delete(name);
- }
- } else {
- for (const name of headers.keys()) {
- headers.delete(name);
- }
- }
+ const headers = getEvent().res.headers;
+
+ if (headerNames && headerNames.length > 0) {
+ for (const name of headerNames) {
+ headers.delete(name);
+ }
+ } else {
+ for (const name of headers.keys()) {
+ headers.delete(name);
+ }
+ }
};
diff --git a/packages/start/src/index.tsx b/packages/start/src/index.tsx
index be39a77a3..8d877e714 100644
--- a/packages/start/src/index.tsx
+++ b/packages/start/src/index.tsx
@@ -1,17 +1,18 @@
// @refresh skip
export type {
- APIEvent,
- APIHandler,
- Asset,
- ContextMatches,
- DocumentComponentProps,
- FetchEvent,
- HandlerOptions,
- PageEvent,
- ResponseStub,
- ServerFunctionMeta
+ APIEvent,
+ APIHandler,
+ Asset,
+ ContextMatches,
+ DocumentComponentProps,
+ FetchEvent,
+ HandlerOptions,
+ PageEvent,
+ ResponseStub,
+ ServerFunctionMeta,
} from "./server/types.ts";
+
export { default as clientOnly } from "./shared/clientOnly.ts";
export { GET } from "./shared/GET.ts";
export { HttpHeader } from "./shared/HttpHeader.tsx";
diff --git a/packages/start/src/internal.d.ts b/packages/start/src/internal.d.ts
index 7aee6253e..dd4ef0e40 100644
--- a/packages/start/src/internal.d.ts
+++ b/packages/start/src/internal.d.ts
@@ -10,5 +10,5 @@ declare module "h3" {
import type { Rollup } from "vite";
declare global {
var START_CLIENT_BUNDLE: Rollup.OutputBundle;
- var USING_SOLID_START_DEV_SERVER: boolean | undefined
+ var USING_SOLID_START_DEV_SERVER: boolean | undefined;
}
diff --git a/packages/start/src/middleware/index.ts b/packages/start/src/middleware/index.ts
index 692379bb0..26d28e717 100644
--- a/packages/start/src/middleware/index.ts
+++ b/packages/start/src/middleware/index.ts
@@ -10,73 +10,63 @@ export type MiddlewareFn = (event: FetchEvent) => Promise | unknown;
/** This composes an array of Exchanges into a single ExchangeIO function */
export type RequestMiddleware = (
- event: FetchEvent,
-) =>
- | Response
- | Promise
- | void
- | Promise
- | Promise;
+ event: FetchEvent,
+) => Response | Promise | void | Promise | Promise;
// copy-pasted from h3/dist/index.d.ts
type EventHandlerResponse = T | Promise;
type ResponseMiddlewareResponseParam = { body?: Awaited };
export type ResponseMiddleware = (
- event: FetchEvent,
- response: ResponseMiddlewareResponseParam,
+ event: FetchEvent,
+ response: ResponseMiddlewareResponseParam,
) => Response | Promise | void | Promise;
function wrapRequestMiddleware(onRequest: RequestMiddleware) {
- return async (h3Event: H3Event) => {
- const fetchEvent = getFetchEvent(h3Event);
- const response = await onRequest(fetchEvent);
- if (response) return response;
- };
+ return async (h3Event: H3Event) => {
+ const fetchEvent = getFetchEvent(h3Event);
+ const response = await onRequest(fetchEvent);
+ if (response) return response;
+ };
}
-function wrapResponseMiddleware(
- onBeforeResponse: ResponseMiddleware,
-): Middleware {
- return async (h3Event, next) => {
- const resp = await next();
+function wrapResponseMiddleware(onBeforeResponse: ResponseMiddleware): Middleware {
+ return async (h3Event, next) => {
+ const resp = await next();
- const fetchEvent = getFetchEvent(h3Event);
- const mwResponse = await onBeforeResponse(fetchEvent, {
- body: (resp as any)?.body,
- });
- if (mwResponse) return mwResponse;
- };
+ const fetchEvent = getFetchEvent(h3Event);
+ const mwResponse = await onBeforeResponse(fetchEvent, {
+ body: (resp as any)?.body,
+ });
+ if (mwResponse) return mwResponse;
+ };
}
export function createMiddleware(
- args:
- | {
- /** @deprecated Use H3 `Middleware` */
- onRequest?: RequestMiddleware | RequestMiddleware[] | undefined;
- /** @deprecated Use H3 `Middleware` */
- onBeforeResponse?:
- | ResponseMiddleware
- | ResponseMiddleware[]
- | undefined;
- }
- | Middleware[],
+ args:
+ | {
+ /** @deprecated Use H3 `Middleware` */
+ onRequest?: RequestMiddleware | RequestMiddleware[] | undefined;
+ /** @deprecated Use H3 `Middleware` */
+ onBeforeResponse?: ResponseMiddleware | ResponseMiddleware[] | undefined;
+ }
+ | Middleware[],
): Middleware[] {
- if (Array.isArray(args)) return args;
+ if (Array.isArray(args)) return args;
- const mw: Middleware[] = [];
+ const mw: Middleware[] = [];
- if (typeof args.onRequest === "function") {
- mw.push(wrapRequestMiddleware(args.onRequest));
- } else if (Array.isArray(args.onRequest)) {
- mw.push(...args.onRequest.map(wrapRequestMiddleware));
- }
+ if (typeof args.onRequest === "function") {
+ mw.push(wrapRequestMiddleware(args.onRequest));
+ } else if (Array.isArray(args.onRequest)) {
+ mw.push(...args.onRequest.map(wrapRequestMiddleware));
+ }
- if (typeof args.onBeforeResponse === "function") {
- mw.push(wrapResponseMiddleware(args.onBeforeResponse));
- } else if (Array.isArray(args.onBeforeResponse)) {
- mw.push(...args.onBeforeResponse.map(wrapResponseMiddleware));
- }
+ if (typeof args.onBeforeResponse === "function") {
+ mw.push(wrapResponseMiddleware(args.onBeforeResponse));
+ } else if (Array.isArray(args.onBeforeResponse)) {
+ mw.push(...args.onBeforeResponse.map(wrapResponseMiddleware));
+ }
- return mw;
+ return mw;
}
diff --git a/packages/start/src/router.tsx b/packages/start/src/router.tsx
index 7b2116e25..980942739 100644
--- a/packages/start/src/router.tsx
+++ b/packages/start/src/router.tsx
@@ -8,17 +8,18 @@ const components: Record = {};
export function createRoutes() {
function createRoute(route: any) {
- const component = route.$component && (components[route.$component.src] ??= lazy(route.$component.import));
+ const component =
+ route.$component && (components[route.$component.src] ??= lazy(route.$component.import));
return {
...route,
...(route.$$route ? route.$$route.require().route : undefined),
info: {
...(route.$$route ? route.$$route.require().route.info : {}),
- filesystem: true
+ filesystem: true,
},
component,
- children: route.children ? route.children.map(createRoute) : undefined
+ children: route.children ? route.children.map(createRoute) : undefined,
};
}
const routes = routeConfigs.map(createRoute);
diff --git a/packages/start/src/server/StartServer.tsx b/packages/start/src/server/StartServer.tsx
index 1059412bf..97419175c 100644
--- a/packages/start/src/server/StartServer.tsx
+++ b/packages/start/src/server/StartServer.tsx
@@ -1,12 +1,6 @@
// @refresh skip
import type { Component } from "solid-js";
-import {
- Hydration,
- HydrationScript,
- NoHydration,
- getRequestEvent,
- ssr
-} from "solid-js/web";
+import { Hydration, HydrationScript, NoHydration, getRequestEvent, ssr } from "solid-js/web";
import App from "solid-start:app";
import { ErrorBoundary, TopErrorBoundary } from "../shared/ErrorBoundary.tsx";
diff --git a/packages/start/src/server/assets/index.ts b/packages/start/src/server/assets/index.ts
index 5cff04dd0..947b2acaf 100644
--- a/packages/start/src/server/assets/index.ts
+++ b/packages/start/src/server/assets/index.ts
@@ -24,7 +24,7 @@ const getEntity = (registry: Registry, asset: Asset) => {
const entity = (registry[key] ??= {
key,
- consumers: 0
+ consumers: 0,
});
return entity;
diff --git a/packages/start/src/server/assets/render.tsx b/packages/start/src/server/assets/render.tsx
index 4b458e645..63aa2a07f 100644
--- a/packages/start/src/server/assets/render.tsx
+++ b/packages/start/src/server/assets/render.tsx
@@ -18,11 +18,15 @@ const assetMap = {
},
noscript: (props: { attrs: JSX.HTMLAttributes; children: JSX.Element }) => (
{props.children}
- )
+ ),
};
export function renderAsset(asset: Asset, nonce?: string) {
- let { tag, attrs: { key, ...attrs } = { key: undefined }, children } = asset as any;
+ let {
+ tag,
+ attrs: { key, ...attrs } = { key: undefined },
+ children,
+ } = asset as any;
return (assetMap as any)[tag]({ attrs: { ...attrs, nonce }, key, children });
}
diff --git a/packages/start/src/server/collect-styles.ts b/packages/start/src/server/collect-styles.ts
index 85079ae0e..7e4b40453 100644
--- a/packages/start/src/server/collect-styles.ts
+++ b/packages/start/src/server/collect-styles.ts
@@ -2,93 +2,86 @@ import path from "node:path";
import { resolve } from "pathe";
import type { DevEnvironment, EnvironmentModuleNode } from "vite";
-async function getViteModuleNode(
- vite: DevEnvironment,
- file: string,
-) {
- let nodePath = file;
- let node = vite.moduleGraph.getModuleById(file);
+async function getViteModuleNode(vite: DevEnvironment, file: string) {
+ let nodePath = file;
+ let node = vite.moduleGraph.getModuleById(file);
- if (!node) {
- const resolvedId = await vite.pluginContainer.resolveId(file, undefined);
- if (!resolvedId) return;
+ if (!node) {
+ const resolvedId = await vite.pluginContainer.resolveId(file, undefined);
+ if (!resolvedId) return;
- nodePath = resolvedId.id;
- node = vite.moduleGraph.getModuleById(file);
- }
+ nodePath = resolvedId.id;
+ node = vite.moduleGraph.getModuleById(file);
+ }
- if (!node) {
- nodePath = resolve(nodePath);
- node = await vite.moduleGraph.getModuleByUrl(file);
- }
+ if (!node) {
+ nodePath = resolve(nodePath);
+ node = await vite.moduleGraph.getModuleByUrl(file);
+ }
- if (!node) {
- await vite.moduleGraph.ensureEntryFromUrl(nodePath, false);
- node = vite.moduleGraph.getModuleById(nodePath);
- }
+ if (!node) {
+ await vite.moduleGraph.ensureEntryFromUrl(nodePath, false);
+ node = vite.moduleGraph.getModuleById(nodePath);
+ }
- return node;
+ return node;
}
async function findModuleDependencies(
- vite: DevEnvironment,
- file: string,
- deps: Set,
- crawledFiles = new Set()
+ vite: DevEnvironment,
+ file: string,
+ deps: Set,
+ crawledFiles = new Set(),
) {
- crawledFiles.add(file);
- const module = await getViteModuleNode(vite, file);
- if (!module?.id || deps.has(module)) return;
-
- deps.add(module);
-
- if (module.url.endsWith(".css") || module.url.includes("node_modules")) return;
-
- if (!module.transformResult) {
- await vite.transformRequest(module.id).catch(() => {});
- }
- if (!module.transformResult?.deps) return;
-
- // Relying on module.transformResult.deps instead of module.importedModules because:
- // transformResult properly separates imports into deps and dynamicDeps, importedModules doesn't
- // Style crawling has to skip dynamic imports as such modules load their styles themselves
- for (const dep of module.transformResult.deps) {
- if (crawledFiles.has(dep)) {
- continue;
- }
- await findModuleDependencies(vite, dep, deps, crawledFiles);
- }
+ crawledFiles.add(file);
+ const module = await getViteModuleNode(vite, file);
+ if (!module?.id || deps.has(module)) return;
+
+ deps.add(module);
+
+ if (module.url.endsWith(".css") || module.url.includes("node_modules")) return;
+
+ if (!module.transformResult) {
+ await vite.transformRequest(module.id).catch(() => {});
+ }
+ if (!module.transformResult?.deps) return;
+
+ // Relying on module.transformResult.deps instead of module.importedModules because:
+ // transformResult properly separates imports into deps and dynamicDeps, importedModules doesn't
+ // Style crawling has to skip dynamic imports as such modules load their styles themselves
+ for (const dep of module.transformResult.deps) {
+ if (crawledFiles.has(dep)) {
+ continue;
+ }
+ await findModuleDependencies(vite, dep, deps, crawledFiles);
+ }
}
// Vite doesn't expose these so we just copy the list for now
// https://github.com/vitejs/vite/blob/d6bde8b03d433778aaed62afc2be0630c8131908/packages/vite/src/node/constants.ts#L49C23-L50
-const cssFileRegExp =
- /\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)$/;
+const cssFileRegExp = /\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)$/;
// https://github.com/vitejs/vite/blob/d6bde8b03d433778aaed62afc2be0630c8131908/packages/vite/src/node/plugins/css.ts#L160
const cssModulesRegExp = new RegExp(`\\.module${cssFileRegExp.source}`);
const isCssFile = (file: string) => cssFileRegExp.test(file);
export const isCssModulesFile = (file: string) => cssModulesRegExp.test(file);
-export async function findStylesInModuleGraph(
- vite: DevEnvironment,
- id: string,
-) {
- const absolute = path.resolve(process.cwd(), id);
- const dependencies = new Set();
-
- try {
- await findModuleDependencies(vite, absolute, dependencies);
- } catch (e) {
- console.error(e);
- }
-
- const styles: Record = {};
- for (const dep of dependencies) {
- if (dep.id && isCssFile(dep.url)) {
- styles[dep.id] = dep.url;
- }
- }
-
- return styles;
+export async function findStylesInModuleGraph(vite: DevEnvironment, id: string) {
+ const absolute = path.resolve(process.cwd(), id);
+ const dependencies = new Set();
+
+ try {
+ await findModuleDependencies(vite, absolute, dependencies);
+ } catch (e) {
+ console.error(e);
+ }
+
+ const styles: Record = {};
+ for (const dep of dependencies) {
+ if (dep.id && isCssFile(dep.url)) {
+ styles[dep.id] = dep.url;
+ }
+ }
+
+ return styles;
}
diff --git a/packages/start/src/server/fetchEvent.spec.ts b/packages/start/src/server/fetchEvent.spec.ts
index 9949eab22..6b59459d0 100644
--- a/packages/start/src/server/fetchEvent.spec.ts
+++ b/packages/start/src/server/fetchEvent.spec.ts
@@ -1,89 +1,85 @@
import * as h3 from "h3";
import { beforeEach, describe, expect, it, vi } from "vitest";
-import {
- createFetchEvent,
- getFetchEvent,
- mergeResponseHeaders,
-} from "./fetchEvent.ts";
-
-vi.mock(import("h3"), async (mod) => {
- return {
- ...(await mod()),
- getRequestIP: vi.fn(),
- };
+import { createFetchEvent, getFetchEvent, mergeResponseHeaders } from "./fetchEvent.ts";
+
+vi.mock(import("h3"), async mod => {
+ return {
+ ...(await mod()),
+ getRequestIP: vi.fn(),
+ };
});
const mockedH3 = vi.mocked(h3);
const createMockH3Event = (): h3.H3Event => {
- const event = new h3.H3Event(new Request("http://localhost/test"));
+ const event = new h3.H3Event(new Request("http://localhost/test"));
- event.res.status = 200;
- event.res.statusText = "OK";
+ event.res.status = 200;
+ event.res.statusText = "OK";
- return event;
+ return event;
};
describe("fetchEvent", () => {
- let mockH3Event: h3.H3Event;
-
- beforeEach(() => {
- mockH3Event = createMockH3Event();
- vi.clearAllMocks();
-
- mockedH3.getRequestIP.mockReturnValue("127.0.0.1");
- });
-
- describe("createFetchEvent", () => {
- it("should create a FetchEvent from H3Event", () => {
- const fetchEvent = createFetchEvent(mockH3Event);
-
- expect(fetchEvent).toEqual({
- request: mockH3Event.req,
- response: expect.any(Object),
- clientAddress: "127.0.0.1",
- locals: {},
- nativeEvent: mockH3Event,
- });
- });
-
- it("should create response stub with correct properties", () => {
- const fetchEvent = createFetchEvent(mockH3Event);
-
- expect(fetchEvent.response).toHaveProperty("status");
- expect(fetchEvent.response).toHaveProperty("statusText");
- expect(fetchEvent.response).toHaveProperty("headers");
- });
- });
-
- describe("getFetchEvent", () => {
- it("should create and cache FetchEvent on first call", () => {
- const fetchEvent = getFetchEvent(mockH3Event);
-
- expect(mockH3Event.context.solidFetchEvent).toBe(fetchEvent);
- expect(fetchEvent.nativeEvent).toBe(mockH3Event);
- });
-
- it("should return cached FetchEvent on subsequent calls", () => {
- const firstCall = getFetchEvent(mockH3Event);
- const secondCall = getFetchEvent(mockH3Event);
-
- expect(firstCall).toBe(secondCall);
- });
- });
-
- describe("mergeResponseHeaders", () => {
- it("should merge headers from Headers object to H3Event", () => {
- const headers = new Headers({
- "content-type": "application/json",
- "x-custom": "value",
- });
-
- mergeResponseHeaders(mockH3Event, headers);
-
- expect(headers.get("content-type")).toBe("application/json");
- expect(headers.get("x-custom")).toBe("value");
- });
- });
+ let mockH3Event: h3.H3Event;
+
+ beforeEach(() => {
+ mockH3Event = createMockH3Event();
+ vi.clearAllMocks();
+
+ mockedH3.getRequestIP.mockReturnValue("127.0.0.1");
+ });
+
+ describe("createFetchEvent", () => {
+ it("should create a FetchEvent from H3Event", () => {
+ const fetchEvent = createFetchEvent(mockH3Event);
+
+ expect(fetchEvent).toEqual({
+ request: mockH3Event.req,
+ response: expect.any(Object),
+ clientAddress: "127.0.0.1",
+ locals: {},
+ nativeEvent: mockH3Event,
+ });
+ });
+
+ it("should create response stub with correct properties", () => {
+ const fetchEvent = createFetchEvent(mockH3Event);
+
+ expect(fetchEvent.response).toHaveProperty("status");
+ expect(fetchEvent.response).toHaveProperty("statusText");
+ expect(fetchEvent.response).toHaveProperty("headers");
+ });
+ });
+
+ describe("getFetchEvent", () => {
+ it("should create and cache FetchEvent on first call", () => {
+ const fetchEvent = getFetchEvent(mockH3Event);
+
+ expect(mockH3Event.context.solidFetchEvent).toBe(fetchEvent);
+ expect(fetchEvent.nativeEvent).toBe(mockH3Event);
+ });
+
+ it("should return cached FetchEvent on subsequent calls", () => {
+ const firstCall = getFetchEvent(mockH3Event);
+ const secondCall = getFetchEvent(mockH3Event);
+
+ expect(firstCall).toBe(secondCall);
+ });
+ });
+
+ describe("mergeResponseHeaders", () => {
+ it("should merge headers from Headers object to H3Event", () => {
+ const headers = new Headers({
+ "content-type": "application/json",
+ "x-custom": "value",
+ });
+
+ mergeResponseHeaders(mockH3Event, headers);
+
+ expect(headers.get("content-type")).toBe("application/json");
+ expect(headers.get("x-custom")).toBe("value");
+ });
+ });
});
diff --git a/packages/start/src/server/fetchEvent.ts b/packages/start/src/server/fetchEvent.ts
index ffbae0080..d3a415cc6 100644
--- a/packages/start/src/server/fetchEvent.ts
+++ b/packages/start/src/server/fetchEvent.ts
@@ -5,32 +5,32 @@ import type { FetchEvent } from "./types.ts";
const FETCH_EVENT_CONTEXT = "solidFetchEvent";
export function createFetchEvent(event: H3Event): FetchEvent {
- return {
- request: event.req,
- response: event.res,
- clientAddress: getRequestIP(event),
- locals: {},
- nativeEvent: event,
- };
+ return {
+ request: event.req,
+ response: event.res,
+ clientAddress: getRequestIP(event),
+ locals: {},
+ nativeEvent: event,
+ };
}
export function getFetchEvent(h3Event: H3Event): FetchEvent {
- if (!h3Event.context[FETCH_EVENT_CONTEXT]) {
- const fetchEvent = createFetchEvent(h3Event);
- h3Event.context[FETCH_EVENT_CONTEXT] = fetchEvent;
- }
+ if (!h3Event.context[FETCH_EVENT_CONTEXT]) {
+ const fetchEvent = createFetchEvent(h3Event);
+ h3Event.context[FETCH_EVENT_CONTEXT] = fetchEvent;
+ }
- return h3Event.context[FETCH_EVENT_CONTEXT] as any;
+ return h3Event.context[FETCH_EVENT_CONTEXT] as any;
}
export function mergeResponseHeaders(h3Event: H3Event, headers: Headers) {
- for (const [key, value] of headers.entries()) {
- h3Event.res.headers.append(key, value);
- }
+ for (const [key, value] of headers.entries()) {
+ h3Event.res.headers.append(key, value);
+ }
}
export const decorateHandler = (fn: T) =>
- (event => provideRequestEvent(getFetchEvent(event), () => fn(event))) as T;
+ (event => provideRequestEvent(getFetchEvent(event), () => fn(event))) as T;
export const decorateMiddleware = (fn: T) =>
- ((event, next) => provideRequestEvent(getFetchEvent(event), () => fn(event, next))) as T;
+ ((event, next) => provideRequestEvent(getFetchEvent(event), () => fn(event, next))) as T;
diff --git a/packages/start/src/server/handler.ts b/packages/start/src/server/handler.ts
index 271b4de06..333ad60f4 100644
--- a/packages/start/src/server/handler.ts
+++ b/packages/start/src/server/handler.ts
@@ -10,88 +10,79 @@ import { decorateHandler, decorateMiddleware } from "./fetchEvent.ts";
import { getSsrManifest } from "./manifest/ssr-manifest.ts";
import { matchAPIRoute } from "./routes.ts";
import { handleServerFunction } from "./server-functions-handler.ts";
-import type {
- APIEvent,
- FetchEvent,
- HandlerOptions,
- PageEvent,
-} from "./types.ts";
+import type { APIEvent, FetchEvent, HandlerOptions, PageEvent } from "./types.ts";
import { getExpectedRedirectStatus } from "./util.ts";
const SERVER_FN_BASE = "/_server";
export function createBaseHandler(
- createPageEvent: (e: FetchEvent) => Promise,
- fn: (context: PageEvent) => JSX.Element,
- options:
- | HandlerOptions
- | ((context: PageEvent) => HandlerOptions | Promise) = {},
+ createPageEvent: (e: FetchEvent) => Promise,
+ fn: (context: PageEvent) => JSX.Element,
+ options: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise) = {},
) {
- const handler = defineHandler({
- middleware: middleware.length ? middleware.map(decorateMiddleware): undefined,
- handler: decorateHandler(async (e: H3Event) => {
- const event = getRequestEvent()!;
- const url = new URL(event.request.url);
- const pathname = stripBaseUrl(url.pathname);
+ const handler = defineHandler({
+ middleware: middleware.length ? middleware.map(decorateMiddleware) : undefined,
+ handler: decorateHandler(async (e: H3Event) => {
+ const event = getRequestEvent()!;
+ const url = new URL(event.request.url);
+ const pathname = stripBaseUrl(url.pathname);
- if (pathname.startsWith(SERVER_FN_BASE)) {
- const serverFnResponse = await handleServerFunction(e);
+ if (pathname.startsWith(SERVER_FN_BASE)) {
+ const serverFnResponse = await handleServerFunction(e);
if (serverFnResponse instanceof Response)
return produceResponseWithEventHeaders(serverFnResponse);
- return new Response(serverFnResponse as any, {
- headers: e.res.headers,
- });
- }
-
- const match = matchAPIRoute(pathname, event.request.method);
- if (match) {
- const mod = await match.handler.import();
- const fn =
- event.request.method === "HEAD"
- ? mod["HEAD"] || mod["GET"]
- : mod[event.request.method];
- (event as APIEvent).params = match.params || {};
- // @ts-expect-error
- sharedConfig.context = { event };
- const res = await fn!(event);
+ return new Response(serverFnResponse as any, {
+ headers: e.res.headers,
+ });
+ }
+
+ const match = matchAPIRoute(pathname, event.request.method);
+ if (match) {
+ const mod = await match.handler.import();
+ const fn =
+ event.request.method === "HEAD" ? mod["HEAD"] || mod["GET"] : mod[event.request.method];
+ (event as APIEvent).params = match.params || {};
+ // @ts-expect-error
+ sharedConfig.context = { event };
+ const res = await fn!(event);
if (res !== undefined) {
- if(res instanceof Response) return produceResponseWithEventHeaders(res)
+ if (res instanceof Response) return produceResponseWithEventHeaders(res);
return res;
}
- if (event.request.method !== "GET") {
- throw new Error(
- `API handler for ${event.request.method} "${event.request.url}" did not return a response.`,
- );
- }
- if (!match.isPage) return;
- }
-
- const context = await createPageEvent(event);
-
- const resolvedOptions =
- typeof options === "function" ? await options(context) : { ...options };
- const mode = resolvedOptions.mode || "stream";
- if (resolvedOptions.nonce) context.nonce = resolvedOptions.nonce;
-
- if (mode === "sync" || !import.meta.env.START_SSR) {
- const html = renderToString(() => {
- (sharedConfig.context as any).event = context;
- return fn(context);
- });
- context.complete = true;
-
- if (context.response && context.response.headers.get("Location")) {
+ if (event.request.method !== "GET") {
+ throw new Error(
+ `API handler for ${event.request.method} "${event.request.url}" did not return a response.`,
+ );
+ }
+ if (!match.isPage) return;
+ }
+
+ const context = await createPageEvent(event);
+
+ const resolvedOptions =
+ typeof options === "function" ? await options(context) : { ...options };
+ const mode = resolvedOptions.mode || "stream";
+ if (resolvedOptions.nonce) context.nonce = resolvedOptions.nonce;
+
+ if (mode === "sync" || !import.meta.env.START_SSR) {
+ const html = renderToString(() => {
+ (sharedConfig.context as any).event = context;
+ return fn(context);
+ });
+ context.complete = true;
+
+ if (context.response && context.response.headers.get("Location")) {
const status = getExpectedRedirectStatus(context.response);
return redirect(context.response.headers.get("Location")!, status);
}
- return html;
- }
+ return html;
+ }
- if (resolvedOptions.onCompleteAll) {
+ if (resolvedOptions.onCompleteAll) {
const og = resolvedOptions.onCompleteAll;
resolvedOptions.onCompleteAll = options => {
handleStreamCompleteRedirect(context)(options);
@@ -106,10 +97,10 @@ export function createBaseHandler(
};
} else resolvedOptions.onCompleteShell = handleShellCompleteRedirect(context, e);
- const _stream = renderToStream(() => {
- (sharedConfig.context as any).event = context;
- return fn(context);
- }, resolvedOptions);
+ const _stream = renderToStream(() => {
+ (sharedConfig.context as any).event = context;
+ return fn(context);
+ }, resolvedOptions);
const stream = _stream as typeof _stream & PromiseLike; // stream has a hidden 'then' method
if (context.response && context.response.headers.get("Location")) {
@@ -117,48 +108,46 @@ export function createBaseHandler(
return redirect(context.response.headers.get("Location")!, status);
}
- if (mode === "async") return await stream
+ if (mode === "async") return await stream;
delete (stream as any).then;
// using TransformStream in dev can cause solid-start-dev-server to crash
// when stream is cancelled
- if(globalThis.USING_SOLID_START_DEV_SERVER) return stream
+ if (globalThis.USING_SOLID_START_DEV_SERVER) return stream;
// returning stream directly breaks cloudflare workers
const { writable, readable } = new TransformStream();
stream.pipeTo(writable);
- return readable
- }),
- });
+ return readable;
+ }),
+ });
- const app = new H3();
+ const app = new H3();
app.use(handler);
- return app;
+ return app;
}
export function createHandler(
- fn: (context: PageEvent) => JSX.Element,
- options:
- | HandlerOptions
- | ((context: PageEvent) => HandlerOptions | Promise) = {},
+ fn: (context: PageEvent) => JSX.Element,
+ options: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise) = {},
) {
- return createBaseHandler(createPageEvent, fn, options);
+ return createBaseHandler(createPageEvent, fn, options);
}
export async function createPageEvent(ctx: FetchEvent) {
- ctx.response.headers.set("Content-Type", "text/html");
- // const prevPath = ctx.request.headers.get("x-solid-referrer");
- // const mutation = ctx.request.headers.get("x-solid-mutation") === "true";
- const manifest = getSsrManifest(import.meta.env.SSR && import.meta.env.DEV ? "ssr": "client");
+ ctx.response.headers.set("Content-Type", "text/html");
+ // const prevPath = ctx.request.headers.get("x-solid-referrer");
+ // const mutation = ctx.request.headers.get("x-solid-mutation") === "true";
+ const manifest = getSsrManifest(import.meta.env.SSR && import.meta.env.DEV ? "ssr" : "client");
- // Handle Vite build.cssCodeSplit
- // When build.cssCodeSplit is false, a single CSS file is generated with the key style.css
- const mergedCSS = import.meta.env.PROD ? await manifest.getAssets('style.css'): [];
+ // Handle Vite build.cssCodeSplit
+ // When build.cssCodeSplit is false, a single CSS file is generated with the key style.css
+ const mergedCSS = import.meta.env.PROD ? await manifest.getAssets("style.css") : [];
- const assets = [
+ const assets = [
...mergedCSS,
...(await manifest.getAssets(import.meta.env.START_CLIENT_ENTRY)),
...(await manifest.getAssets(import.meta.env.START_APP_ENTRY)),
@@ -168,52 +157,49 @@ export async function createPageEvent(ctx: FetchEvent) {
// )
// : [])
];
- const pageEvent: PageEvent = Object.assign(ctx, {
- assets,
- router: {
- submission: initFromFlash(ctx) as any,
- },
- routes: createRoutes(),
- // prevUrl: prevPath || "",
- // mutation: mutation,
- // $type: FETCH_EVENT,
- complete: false,
- $islands: new Set(),
- });
-
- return pageEvent;
+ const pageEvent: PageEvent = Object.assign(ctx, {
+ assets,
+ router: {
+ submission: initFromFlash(ctx) as any,
+ },
+ routes: createRoutes(),
+ // prevUrl: prevPath || "",
+ // mutation: mutation,
+ // $type: FETCH_EVENT,
+ complete: false,
+ $islands: new Set(),
+ });
+
+ return pageEvent;
}
function initFromFlash(ctx: FetchEvent) {
- const flash = getCookie(ctx.nativeEvent, "flash");
- if (!flash) return;
- try {
- const param = JSON.parse(flash);
- if (!param || !param.result) return;
- const input = [
- ...param.input.slice(0, -1),
- new Map(param.input[param.input.length - 1]),
- ];
- const result = param.error ? new Error(param.result) : param.result;
- return {
- input,
- url: param.url,
- pending: false,
- result: param.thrown ? undefined : result,
- error: param.thrown ? result : undefined,
- };
- } catch (e) {
- console.error(e);
- } finally {
- setCookie(ctx.nativeEvent, "flash", "", { maxAge: 0 });
- }
+ const flash = getCookie(ctx.nativeEvent, "flash");
+ if (!flash) return;
+ try {
+ const param = JSON.parse(flash);
+ if (!param || !param.result) return;
+ const input = [...param.input.slice(0, -1), new Map(param.input[param.input.length - 1])];
+ const result = param.error ? new Error(param.result) : param.result;
+ return {
+ input,
+ url: param.url,
+ pending: false,
+ result: param.thrown ? undefined : result,
+ error: param.thrown ? result : undefined,
+ };
+ } catch (e) {
+ console.error(e);
+ } finally {
+ setCookie(ctx.nativeEvent, "flash", "", { maxAge: 0 });
+ }
}
function handleShellCompleteRedirect(context: PageEvent, e: H3Event) {
return () => {
if (context.response && context.response.headers.get("Location")) {
const status = getExpectedRedirectStatus(context.response);
- e.res.status = status
+ e.res.status = status;
e.res.headers.set("Location", context.response.headers.get("Location")!);
}
};
@@ -233,16 +219,16 @@ function produceResponseWithEventHeaders(res: Response) {
let ret = res;
// Response.redirect returns an immutable value, so we clone on any redirect just in case
- if(300 <= res.status && res.status < 400) {
+ if (300 <= res.status && res.status < 400) {
const cookies = res.headers.getSetCookie?.() ?? [];
const headers = new Headers();
res.headers.forEach((value, key) => {
- if (key.toLowerCase() !== 'set-cookie') {
+ if (key.toLowerCase() !== "set-cookie") {
headers.set(key, value);
}
});
for (const cookie of cookies) {
- headers.append('Set-Cookie', cookie);
+ headers.append("Set-Cookie", cookie);
}
ret = new Response(res.body, {
status: res.status,
@@ -253,19 +239,19 @@ function produceResponseWithEventHeaders(res: Response) {
const eventCookies = event.response.headers.getSetCookie?.() ?? [];
for (const cookie of eventCookies) {
- ret.headers.append('Set-Cookie', cookie);
+ ret.headers.append("Set-Cookie", cookie);
}
- for(const [name, value] of event.response.headers) {
- if (name.toLowerCase() !== 'set-cookie') {
+ for (const [name, value] of event.response.headers) {
+ if (name.toLowerCase() !== "set-cookie") {
ret.headers.set(name, value);
}
}
- return ret
+ return ret;
}
function stripBaseUrl(path: string) {
- if(import.meta.env.BASE_URL === "/" || import.meta.env.BASE_URL === "") return path;
+ if (import.meta.env.BASE_URL === "/" || import.meta.env.BASE_URL === "") return path;
return path.slice(import.meta.env.BASE_URL.length);
}
diff --git a/packages/start/src/server/manifest/client-manifest.ts b/packages/start/src/server/manifest/client-manifest.ts
index e511d5627..c9702bb7a 100644
--- a/packages/start/src/server/manifest/client-manifest.ts
+++ b/packages/start/src/server/manifest/client-manifest.ts
@@ -2,7 +2,7 @@ import { getClientDevManifest } from "./dev-client-manifest.ts";
import { getClientProdManifest } from "./prod-client-manifest.ts";
export function getClientManifest() {
- return import.meta.env.DEV ? getClientDevManifest() : getClientProdManifest();
+ return import.meta.env.DEV ? getClientDevManifest() : getClientProdManifest();
}
export { getClientManifest as getManifest };
diff --git a/packages/start/src/server/manifest/dev-client-manifest.ts b/packages/start/src/server/manifest/dev-client-manifest.ts
index 0d15c4d54..480693955 100644
--- a/packages/start/src/server/manifest/dev-client-manifest.ts
+++ b/packages/start/src/server/manifest/dev-client-manifest.ts
@@ -3,17 +3,19 @@ import { join } from "pathe";
export function getClientDevManifest() {
return {
import(id) {
- return import(/* @vite-ignore */ join("/", id))
+ return import(/* @vite-ignore */ join("/", id));
},
async getAssets(id) {
const assetsPath = `/@manifest/client/${Date.now()}/assets?id=${id}`;
const assets = (await import(/* @vite-ignore */ assetsPath)).default;
- return await Promise.all(assets.map(async (v: any) => ({
- ...v,
- children: await v.children()
- })));
+ return await Promise.all(
+ assets.map(async (v: any) => ({
+ ...v,
+ children: await v.children(),
+ })),
+ );
},
} satisfies StartManifest & { import(id: string): Promise };
}
diff --git a/packages/start/src/server/manifest/dev-ssr-manifest.ts b/packages/start/src/server/manifest/dev-ssr-manifest.ts
index 735ec073f..4fefff1c5 100644
--- a/packages/start/src/server/manifest/dev-ssr-manifest.ts
+++ b/packages/start/src/server/manifest/dev-ssr-manifest.ts
@@ -8,14 +8,16 @@ export function getSsrDevManifest(environment: "client" | "ssr") {
const assets = (await import(/* @vite-ignore */ assetsPath)).default;
- return await Promise.all(assets.map(async (v: any) => ({
- ...v,
- children: await v.children()
- })));
+ return await Promise.all(
+ assets.map(async (v: any) => ({
+ ...v,
+ children: await v.children(),
+ })),
+ );
},
} satisfies StartManifest & {
- path(id: string): string;
- };
+ path(id: string): string;
+ };
}
export { getSsrDevManifest as getSsrManifest };
diff --git a/packages/start/src/server/manifest/prod-client-manifest.ts b/packages/start/src/server/manifest/prod-client-manifest.ts
index 2487abaf7..03f477780 100644
--- a/packages/start/src/server/manifest/prod-client-manifest.ts
+++ b/packages/start/src/server/manifest/prod-client-manifest.ts
@@ -2,17 +2,20 @@ export function getClientProdManifest() {
return {
import(id) {
// @ts-ignore
- return import(/* @vite-ignore */ window.manifest[id].output)
+ return import(/* @vite-ignore */ window.manifest[id].output);
},
async getAssets(id) {
if (id.startsWith("./")) id = id.slice(2);
// @ts-ignore
- return window.manifest[id]?.assets ?? []
+ return window.manifest[id]?.assets ?? [];
},
async json() {
// @ts-ignore
- return window.manifest
+ return window.manifest;
},
- } satisfies StartManifest & { json(): Promise>, import(id: string): Promise; }
+ } satisfies StartManifest & {
+ json(): Promise>;
+ import(id: string): Promise;
+ };
}
diff --git a/packages/start/src/server/manifest/prod-ssr-manifest.ts b/packages/start/src/server/manifest/prod-ssr-manifest.ts
index 6d3ccd732..89d4f02ef 100644
--- a/packages/start/src/server/manifest/prod-ssr-manifest.ts
+++ b/packages/start/src/server/manifest/prod-ssr-manifest.ts
@@ -5,121 +5,105 @@ import type { Asset } from "../assets/render.tsx";
// Only reads from client manifest atm, might need server support for islands
export function getSsrProdManifest() {
- const viteManifest = clientViteManifest;
- return {
- path(id: string) {
+ const viteManifest = clientViteManifest;
+ return {
+ path(id: string) {
if (id.startsWith("./")) id = id.slice(2);
- const viteManifestEntry =
- clientViteManifest[id /*import.meta.env.START_CLIENT_ENTRY*/];
- if (!viteManifestEntry)
- throw new Error(`No entry found in vite manifest for '${id}'`);
+ const viteManifestEntry = clientViteManifest[id /*import.meta.env.START_CLIENT_ENTRY*/];
+ if (!viteManifestEntry) throw new Error(`No entry found in vite manifest for '${id}'`);
- return join("/", viteManifestEntry.file);
- },
- async getAssets(id) {
+ return join("/", viteManifestEntry.file);
+ },
+ async getAssets(id) {
if (id.startsWith("./")) id = id.slice(2);
- return createHtmlTagsForAssets(
- findAssetsInViteManifest(clientViteManifest, id),
- );
- },
- async json() {
- const json: Record = {};
+ return createHtmlTagsForAssets(findAssetsInViteManifest(clientViteManifest, id));
+ },
+ async json() {
+ const json: Record = {};
- const entryKeys = Object.keys(viteManifest)
- .filter((id) => viteManifest[id]?.isEntry || viteManifest[id]?.isDynamicEntry)
- .map((id) => id);
+ const entryKeys = Object.keys(viteManifest)
+ .filter(id => viteManifest[id]?.isEntry || viteManifest[id]?.isDynamicEntry)
+ .map(id => id);
- for (const entryKey of entryKeys) {
- json[entryKey] = {
- output: join("/", viteManifest[entryKey]!.file),
- assets: await this.getAssets(entryKey),
- };
- }
+ for (const entryKey of entryKeys) {
+ json[entryKey] = {
+ output: join("/", viteManifest[entryKey]!.file),
+ assets: await this.getAssets(entryKey),
+ };
+ }
- return json;
- },
- } satisfies StartManifest & {
- json(): Promise>;
- path(id: string): string;
- };
+ return json;
+ },
+ } satisfies StartManifest & {
+ json(): Promise>;
+ path(id: string): string;
+ };
}
function createHtmlTagsForAssets(assets: string[]) {
- return assets
- .filter(
- (asset) =>
- asset.endsWith(".css") ||
- asset.endsWith(".js") ||
- asset.endsWith(".ts") ||
- asset.endsWith(".mjs"),
- )
- .map((asset) => ({
- tag: "link",
- attrs: {
- href: '/' + asset,
- key: asset,
- ...(asset.endsWith(".css")
- ? { rel: "stylesheet" }
- : { rel: "modulepreload" }),
- },
- }));
+ return assets
+ .filter(
+ asset =>
+ asset.endsWith(".css") ||
+ asset.endsWith(".js") ||
+ asset.endsWith(".ts") ||
+ asset.endsWith(".mjs"),
+ )
+ .map(asset => ({
+ tag: "link",
+ attrs: {
+ href: "/" + asset,
+ key: asset,
+ ...(asset.endsWith(".css") ? { rel: "stylesheet" } : { rel: "modulepreload" }),
+ },
+ }));
}
const entryId = import.meta.env.START_CLIENT_ENTRY.slice(2);
let entryImports: string[] | undefined = undefined;
function findAssetsInViteManifest(
- manifest: Manifest,
- id: string,
- assetMap = new Map(),
- stack: string[] = [],
+ manifest: Manifest,
+ id: string,
+ assetMap = new Map(),
+ stack: string[] = [],
) {
- if (stack.includes(id)) {
- return [];
- }
+ if (stack.includes(id)) {
+ return [];
+ }
- const cached = assetMap.get(id);
- if (cached) {
- return cached;
- }
- const chunk = manifest[id];
- if (!chunk) {
- return [];
- }
+ const cached = assetMap.get(id);
+ if (cached) {
+ return cached;
+ }
+ const chunk = manifest[id];
+ if (!chunk) {
+ return [];
+ }
- if (!entryImports) {
- entryImports = [
- entryId,
- ...(manifest[entryId]?.imports ?? [])
- ];
- }
+ if (!entryImports) {
+ entryImports = [entryId, ...(manifest[entryId]?.imports ?? [])];
+ }
- // Only include entry imports, if we are specifically crawling the entry
- // Chunks (e.g. routes) that import something from entry, should not render entry css redundantly
- const excludeEntryImports = id !== entryId;
+ // Only include entry imports, if we are specifically crawling the entry
+ // Chunks (e.g. routes) that import something from entry, should not render entry css redundantly
+ const excludeEntryImports = id !== entryId;
- const assets = chunk.css?.filter(Boolean) || [];
- if (chunk.imports) {
- stack.push(id);
- for (let i = 0, l = chunk.imports.length; i < l; i++) {
- const importId = chunk.imports[i];
- if (!importId || (excludeEntryImports && entryImports.includes(importId))) continue;
- assets.push(
- ...findAssetsInViteManifest(
- manifest,
- importId,
- assetMap,
- stack,
- ),
- );
- }
- stack.pop();
- }
- assets.push(chunk.file);
- const all = Array.from(new Set(assets));
- assetMap.set(id, all);
+ const assets = chunk.css?.filter(Boolean) || [];
+ if (chunk.imports) {
+ stack.push(id);
+ for (let i = 0, l = chunk.imports.length; i < l; i++) {
+ const importId = chunk.imports[i];
+ if (!importId || (excludeEntryImports && entryImports.includes(importId))) continue;
+ assets.push(...findAssetsInViteManifest(manifest, importId, assetMap, stack));
+ }
+ stack.pop();
+ }
+ assets.push(chunk.file);
+ const all = Array.from(new Set(assets));
+ assetMap.set(id, all);
- return all;
+ return all;
}
diff --git a/packages/start/src/server/manifest/ssr-manifest.ts b/packages/start/src/server/manifest/ssr-manifest.ts
index 8c83fe246..8dd622128 100644
--- a/packages/start/src/server/manifest/ssr-manifest.ts
+++ b/packages/start/src/server/manifest/ssr-manifest.ts
@@ -1,8 +1,10 @@
import { getSsrDevManifest } from "./dev-ssr-manifest.ts";
import { getSsrProdManifest } from "./prod-ssr-manifest.ts";
-export function getSsrManifest(target: "client" | "ssr"): ReturnType | ReturnType {
- return import.meta.env.DEV ? getSsrDevManifest(target) : getSsrProdManifest();
+export function getSsrManifest(
+ target: "client" | "ssr",
+): ReturnType | ReturnType {
+ return import.meta.env.DEV ? getSsrDevManifest(target) : getSsrProdManifest();
}
export { getSsrManifest as getManifest };
diff --git a/packages/start/src/server/routes.ts b/packages/start/src/server/routes.ts
index 0c6807908..0b44eb18d 100644
--- a/packages/start/src/server/routes.ts
+++ b/packages/start/src/server/routes.ts
@@ -5,134 +5,122 @@ import { createRouter } from "radix3";
import type { FetchEvent } from "./types.ts";
interface Route {
- path: string;
- id: string;
- children?: Route[];
- page?: boolean;
- $component?: any;
- $HEAD?: any;
- $GET?: any;
- $POST?: any;
- $PUT?: any;
- $PATCH?: any;
- $DELETE?: any;
+ path: string;
+ id: string;
+ children?: Route[];
+ page?: boolean;
+ $component?: any;
+ $HEAD?: any;
+ $GET?: any;
+ $POST?: any;
+ $PUT?: any;
+ $PATCH?: any;
+ $DELETE?: any;
}
-export const pageRoutes = defineRoutes(
- (fileRoutes as unknown as Route[]).filter((o) => o.page),
-);
+export const pageRoutes = defineRoutes((fileRoutes as unknown as Route[]).filter(o => o.page));
function defineRoutes(fileRoutes: Route[]) {
- function processRoute(
- routes: Route[],
- route: Route,
- id: string,
- full: string,
- ) {
- const parentRoute = Object.values(routes).find((o) => {
- return id.startsWith(o.id + "/");
- });
+ function processRoute(routes: Route[], route: Route, id: string, full: string) {
+ const parentRoute = Object.values(routes).find(o => {
+ return id.startsWith(o.id + "/");
+ });
- if (!parentRoute) {
- routes.push({
- ...route,
- id,
- path: id.replace(/\([^)/]+\)/g, "").replace(/\/+/g, "/"),
- });
- return routes;
- }
- processRoute(
- parentRoute.children || (parentRoute.children = []),
- route,
- id.slice(parentRoute.id.length),
- full,
- );
+ if (!parentRoute) {
+ routes.push({
+ ...route,
+ id,
+ path: id.replace(/\([^)/]+\)/g, "").replace(/\/+/g, "/"),
+ });
+ return routes;
+ }
+ processRoute(
+ parentRoute.children || (parentRoute.children = []),
+ route,
+ id.slice(parentRoute.id.length),
+ full,
+ );
- return routes;
- }
+ return routes;
+ }
- return fileRoutes
- .sort((a, b) => a.path.length - b.path.length)
- .reduce((prevRoutes: Route[], route) => {
- return processRoute(prevRoutes, route, route.path, route.path);
- }, []);
+ return fileRoutes
+ .sort((a, b) => a.path.length - b.path.length)
+ .reduce((prevRoutes: Route[], route) => {
+ return processRoute(prevRoutes, route, route.path, route.path);
+ }, []);
}
const router = createRouter({
- routes: (fileRoutes as unknown as Route[]).reduce(
- (memo, route) => {
- if (!containsHTTP(route)) return memo;
- const path = route.path
- .replace(/\([^)/]+\)/g, "")
- .replace(/\/+/g, "/")
- .replace(/\*([^/]*)/g, (_, m) => `**:${m}`)
- .split("/")
- .map((s) =>
- s.startsWith(":") || s.startsWith("*") ? s : encodeURIComponent(s),
- )
- .join("/");
- if (/:[^/]*\?/g.test(path)) {
- throw new Error(
- `Optional parameters are not supported in API routes: ${path}`,
- );
- }
- if (memo[path]) {
- throw new Error(
- `Duplicate API routes for "${path}" found at "${memo[path]!.route.path}" and "${
- route.path
- }"`,
- );
- }
- memo[path] = { route };
- return memo;
- },
- {} as Record,
- ),
+ routes: (fileRoutes as unknown as Route[]).reduce(
+ (memo, route) => {
+ if (!containsHTTP(route)) return memo;
+ const path = route.path
+ .replace(/\([^)/]+\)/g, "")
+ .replace(/\/+/g, "/")
+ .replace(/\*([^/]*)/g, (_, m) => `**:${m}`)
+ .split("/")
+ .map(s => (s.startsWith(":") || s.startsWith("*") ? s : encodeURIComponent(s)))
+ .join("/");
+ if (/:[^/]*\?/g.test(path)) {
+ throw new Error(`Optional parameters are not supported in API routes: ${path}`);
+ }
+ if (memo[path]) {
+ throw new Error(
+ `Duplicate API routes for "${path}" found at "${memo[path]!.route.path}" and "${
+ route.path
+ }"`,
+ );
+ }
+ memo[path] = { route };
+ return memo;
+ },
+ {} as Record,
+ ),
});
function containsHTTP(route: Route) {
- return (
- route["$HEAD"] ||
- route["$GET"] ||
- route["$POST"] ||
- route["$PUT"] ||
- route["$PATCH"] ||
- route["$DELETE"]
- );
+ return (
+ route["$HEAD"] ||
+ route["$GET"] ||
+ route["$POST"] ||
+ route["$PUT"] ||
+ route["$PATCH"] ||
+ route["$DELETE"]
+ );
}
export function matchAPIRoute(
- path: string,
- method: string,
+ path: string,
+ method: string,
):
- | {
- params?: Record;
- handler: {
- import: () => Promise Promise>>;
- };
- isPage: boolean;
- }
- | undefined {
- const match = router.lookup(path);
- if (match && match.route) {
- const route = match.route;
+ | {
+ params?: Record;
+ handler: {
+ import: () => Promise Promise>>;
+ };
+ isPage: boolean;
+ }
+ | undefined {
+ const match = router.lookup(path);
+ if (match && match.route) {
+ const route = match.route;
- // Find the appropriate handler for the HTTP method
- const handler =
- method === "HEAD" ? route.$HEAD || route.$GET : route[`$${method}`];
+ // Find the appropriate handler for the HTTP method
+ const handler = method === "HEAD" ? route.$HEAD || route.$GET : route[`$${method}`];
- if (handler === undefined) return;
+ if (handler === undefined) return;
- // Check if this is a page route
- const isPage = route.page === true && route.$component !== undefined;
+ // Check if this is a page route
+ const isPage = route.page === true && route.$component !== undefined;
- // Return comprehensive route information
- return {
- handler,
- params: match.params,
- isPage,
- };
- }
+ // Return comprehensive route information
+ return {
+ handler,
+ params: match.params,
+ isPage,
+ };
+ }
- return undefined;
+ return undefined;
}
diff --git a/packages/start/src/server/server-fns-runtime.ts b/packages/start/src/server/server-fns-runtime.ts
index f56fdad72..a287670b9 100644
--- a/packages/start/src/server/server-fns-runtime.ts
+++ b/packages/start/src/server/server-fns-runtime.ts
@@ -5,7 +5,7 @@ export function createServerReference(fn: Function, id: string) {
if (typeof fn !== "function")
throw new Error("Export from a 'use server' module must be a function");
let baseURL = import.meta.env.BASE_URL ?? "/";
- if(!baseURL.endsWith("/")) baseURL += "/"
+ if (!baseURL.endsWith("/")) baseURL += "/";
return new Proxy(fn, {
get(target, prop, receiver) {
@@ -20,12 +20,12 @@ export function createServerReference(fn: Function, id: string) {
if (!ogEvt) throw new Error("Cannot call server function outside of a request");
const evt = { ...ogEvt };
evt.locals.serverFunctionMeta = {
- id
+ id,
};
evt.serverOnly = true;
return provideRequestEvent(evt, () => {
return fn.apply(thisArg, args);
});
- }
+ },
});
}
diff --git a/packages/start/src/server/server-functions-handler.ts b/packages/start/src/server/server-functions-handler.ts
index 2466567d0..160672684 100644
--- a/packages/start/src/server/server-functions-handler.ts
+++ b/packages/start/src/server/server-functions-handler.ts
@@ -1,22 +1,18 @@
import { getServerFnById } from "solidstart:server-fn-manifest";
import { parseSetCookie } from "cookie-es";
import { type H3Event, parseCookies } from "h3";
+import { crossSerializeStream, fromJSON, getCrossReferenceHeader } from "seroval";
import {
- crossSerializeStream,
- fromJSON,
- getCrossReferenceHeader,
-} from "seroval";
-import {
- CustomEventPlugin,
- DOMExceptionPlugin,
- EventPlugin,
- FormDataPlugin,
- HeadersPlugin,
- ReadableStreamPlugin,
- RequestPlugin,
- ResponsePlugin,
- URLPlugin,
- URLSearchParamsPlugin,
+ CustomEventPlugin,
+ DOMExceptionPlugin,
+ EventPlugin,
+ FormDataPlugin,
+ HeadersPlugin,
+ ReadableStreamPlugin,
+ RequestPlugin,
+ ResponsePlugin,
+ URLPlugin,
+ URLSearchParamsPlugin,
} from "seroval-plugins/web";
import { sharedConfig } from "solid-js";
import { renderToString } from "solid-js/web";
@@ -28,337 +24,316 @@ import type { FetchEvent, PageEvent } from "./types.ts";
import { getExpectedRedirectStatus } from "./util.ts";
function createChunk(data: string) {
- const encodeData = new TextEncoder().encode(data);
- const bytes = encodeData.length;
- const baseHex = bytes.toString(16);
- const totalHex = "00000000".substring(0, 8 - baseHex.length) + baseHex; // 32-bit
- const head = new TextEncoder().encode(`;0x${totalHex};`);
+ const encodeData = new TextEncoder().encode(data);
+ const bytes = encodeData.length;
+ const baseHex = bytes.toString(16);
+ const totalHex = "00000000".substring(0, 8 - baseHex.length) + baseHex; // 32-bit
+ const head = new TextEncoder().encode(`;0x${totalHex};`);
- const chunk = new Uint8Array(12 + bytes);
- chunk.set(head);
- chunk.set(encodeData, 12);
- return chunk;
+ const chunk = new Uint8Array(12 + bytes);
+ chunk.set(head);
+ chunk.set(encodeData, 12);
+ return chunk;
}
function serializeToStream(id: string, value: any) {
- return new ReadableStream({
- start(controller) {
- crossSerializeStream(value, {
- scopeId: id,
- plugins: [
- CustomEventPlugin,
- DOMExceptionPlugin,
- EventPlugin,
- FormDataPlugin,
- HeadersPlugin,
- ReadableStreamPlugin,
- RequestPlugin,
- ResponsePlugin,
- URLSearchParamsPlugin,
- URLPlugin,
- ],
- onSerialize(data: string, initial: boolean) {
- controller.enqueue(
- createChunk(
- initial ? `(${getCrossReferenceHeader(id)},${data})` : data,
- ),
- );
- },
- onDone() {
- controller.close();
- },
- onError(error: any) {
- controller.error(error);
- },
- });
- },
- });
+ return new ReadableStream({
+ start(controller) {
+ crossSerializeStream(value, {
+ scopeId: id,
+ plugins: [
+ CustomEventPlugin,
+ DOMExceptionPlugin,
+ EventPlugin,
+ FormDataPlugin,
+ HeadersPlugin,
+ ReadableStreamPlugin,
+ RequestPlugin,
+ ResponsePlugin,
+ URLSearchParamsPlugin,
+ URLPlugin,
+ ],
+ onSerialize(data: string, initial: boolean) {
+ controller.enqueue(
+ createChunk(initial ? `(${getCrossReferenceHeader(id)},${data})` : data),
+ );
+ },
+ onDone() {
+ controller.close();
+ },
+ onError(error: any) {
+ controller.error(error);
+ },
+ });
+ },
+ });
}
export async function handleServerFunction(h3Event: H3Event) {
- const event = getFetchEvent(h3Event);
- const request = event.request;
+ const event = getFetchEvent(h3Event);
+ const request = event.request;
- const serverReference = request.headers.get("X-Server-Id");
- const instance = request.headers.get("X-Server-Instance");
- const singleFlight = request.headers.has("X-Single-Flight");
- const url = new URL(request.url);
- let functionId: string | undefined | null;
- if (serverReference) {
- // invariant(typeof serverReference === "string", "Invalid server function");
- [functionId] = serverReference.split("#");
- } else {
- functionId = url.searchParams.get("id");
+ const serverReference = request.headers.get("X-Server-Id");
+ const instance = request.headers.get("X-Server-Instance");
+ const singleFlight = request.headers.has("X-Single-Flight");
+ const url = new URL(request.url);
+ let functionId: string | undefined | null;
+ if (serverReference) {
+ // invariant(typeof serverReference === "string", "Invalid server function");
+ [functionId] = serverReference.split("#");
+ } else {
+ functionId = url.searchParams.get("id");
- if (!functionId) {
- return process.env.NODE_ENV === "development"
- ? new Response("Server function not found", { status: 404 })
- : new Response(null, { status: 404 });
- }
- }
+ if (!functionId) {
+ return process.env.NODE_ENV === "development"
+ ? new Response("Server function not found", { status: 404 })
+ : new Response(null, { status: 404 });
+ }
+ }
- const serverFunction = await getServerFnById(functionId!);
+ const serverFunction = await getServerFnById(functionId!);
- let parsed: any[] = [];
+ let parsed: any[] = [];
- // grab bound arguments from url when no JS
- if (!instance || h3Event.method === "GET") {
- const args = url.searchParams.get("args");
- if (args) {
- const json = JSON.parse(args);
- (json.t
- ? (fromJSON(json, {
- plugins: [
- CustomEventPlugin,
- DOMExceptionPlugin,
- EventPlugin,
- FormDataPlugin,
- HeadersPlugin,
- ReadableStreamPlugin,
- RequestPlugin,
- ResponsePlugin,
- URLSearchParamsPlugin,
- URLPlugin,
- ],
- }) as any)
- : json
- ).forEach((arg: any) => {
- parsed.push(arg);
- });
- }
- }
- if (h3Event.method === "POST") {
- const contentType = request.headers.get("content-type");
+ // grab bound arguments from url when no JS
+ if (!instance || h3Event.method === "GET") {
+ const args = url.searchParams.get("args");
+ if (args) {
+ const json = JSON.parse(args);
+ (json.t
+ ? (fromJSON(json, {
+ plugins: [
+ CustomEventPlugin,
+ DOMExceptionPlugin,
+ EventPlugin,
+ FormDataPlugin,
+ HeadersPlugin,
+ ReadableStreamPlugin,
+ RequestPlugin,
+ ResponsePlugin,
+ URLSearchParamsPlugin,
+ URLPlugin,
+ ],
+ }) as any)
+ : json
+ ).forEach((arg: any) => {
+ parsed.push(arg);
+ });
+ }
+ }
+ if (h3Event.method === "POST") {
+ const contentType = request.headers.get("content-type");
- if (
- contentType?.startsWith("multipart/form-data") ||
- contentType?.startsWith("application/x-www-form-urlencoded")
- ) {
- parsed.push(await event.request.formData());
- } else if (contentType?.startsWith("application/json")) {
- parsed = fromJSON(await event.request.json(), {
- plugins: [
- CustomEventPlugin,
- DOMExceptionPlugin,
- EventPlugin,
- FormDataPlugin,
- HeadersPlugin,
- ReadableStreamPlugin,
- RequestPlugin,
- ResponsePlugin,
- URLSearchParamsPlugin,
- URLPlugin,
- ],
- });
- }
- }
- try {
- let result = await provideRequestEvent(event, async () => {
- /* @ts-expect-error */
- sharedConfig.context = { event };
- event.locals.serverFunctionMeta = {
- id: functionId
- };
- return serverFunction(...parsed);
- });
+ if (
+ contentType?.startsWith("multipart/form-data") ||
+ contentType?.startsWith("application/x-www-form-urlencoded")
+ ) {
+ parsed.push(await event.request.formData());
+ } else if (contentType?.startsWith("application/json")) {
+ parsed = fromJSON(await event.request.json(), {
+ plugins: [
+ CustomEventPlugin,
+ DOMExceptionPlugin,
+ EventPlugin,
+ FormDataPlugin,
+ HeadersPlugin,
+ ReadableStreamPlugin,
+ RequestPlugin,
+ ResponsePlugin,
+ URLSearchParamsPlugin,
+ URLPlugin,
+ ],
+ });
+ }
+ }
+ try {
+ let result = await provideRequestEvent(event, async () => {
+ /* @ts-expect-error */
+ sharedConfig.context = { event };
+ event.locals.serverFunctionMeta = {
+ id: functionId,
+ };
+ return serverFunction(...parsed);
+ });
- if (singleFlight && instance) {
- result = await handleSingleFlight(event, result);
- }
+ if (singleFlight && instance) {
+ result = await handleSingleFlight(event, result);
+ }
- // handle responses
- if (result instanceof Response) {
- if (result.headers && result.headers.has("X-Content-Raw")) return result;
- if (instance) {
- // forward headers
- if (result.headers) mergeResponseHeaders(h3Event, result.headers);
- // forward non-redirect statuses
- if (result.status && (result.status < 300 || result.status >= 400))
- h3Event.res.status = result.status;
- if ((result as any).customBody) {
- result = await (result as any).customBody();
- } else if (result.body == undefined) result = null;
- }
- }
+ // handle responses
+ if (result instanceof Response) {
+ if (result.headers && result.headers.has("X-Content-Raw")) return result;
+ if (instance) {
+ // forward headers
+ if (result.headers) mergeResponseHeaders(h3Event, result.headers);
+ // forward non-redirect statuses
+ if (result.status && (result.status < 300 || result.status >= 400))
+ h3Event.res.status = result.status;
+ if ((result as any).customBody) {
+ result = await (result as any).customBody();
+ } else if (result.body == undefined) result = null;
+ }
+ }
- // handle no JS success case
- if (!instance) return handleNoJS(result, request, parsed);
+ // handle no JS success case
+ if (!instance) return handleNoJS(result, request, parsed);
- h3Event.res.headers.set("content-type", "text/javascript");
+ h3Event.res.headers.set("content-type", "text/javascript");
- return serializeToStream(instance, result);
- } catch (x) {
- if (x instanceof Response) {
- if (singleFlight && instance) {
- x = await handleSingleFlight(event, x);
- }
- // forward headers
- if ((x as any).headers) mergeResponseHeaders(h3Event, (x as any).headers);
- // forward non-redirect statuses
- if (
- (x as any).status &&
- (!instance || (x as any).status < 300 || (x as any).status >= 400)
- )
- h3Event.res.status = (x as any).status;
- if ((x as any).customBody) {
- x = (x as any).customBody();
- } else if ((x as any).body === undefined) x = null;
- h3Event.res.headers.set("X-Error", "true");
- } else if (instance) {
- const error =
- x instanceof Error ? x.message : typeof x === "string" ? x : "true";
+ return serializeToStream(instance, result);
+ } catch (x) {
+ if (x instanceof Response) {
+ if (singleFlight && instance) {
+ x = await handleSingleFlight(event, x);
+ }
+ // forward headers
+ if ((x as any).headers) mergeResponseHeaders(h3Event, (x as any).headers);
+ // forward non-redirect statuses
+ if ((x as any).status && (!instance || (x as any).status < 300 || (x as any).status >= 400))
+ h3Event.res.status = (x as any).status;
+ if ((x as any).customBody) {
+ x = (x as any).customBody();
+ } else if ((x as any).body === undefined) x = null;
+ h3Event.res.headers.set("X-Error", "true");
+ } else if (instance) {
+ const error = x instanceof Error ? x.message : typeof x === "string" ? x : "true";
- h3Event.res.headers.set("X-Error", error.replace(/[\r\n]+/g, ""));
- } else {
- x = handleNoJS(x, request, parsed, true);
- }
- if (instance) {
- h3Event.res.headers.set("content-type", "text/javascript");
- return serializeToStream(instance, x);
- }
- return x;
- }
+ h3Event.res.headers.set("X-Error", error.replace(/[\r\n]+/g, ""));
+ } else {
+ x = handleNoJS(x, request, parsed, true);
+ }
+ if (instance) {
+ h3Event.res.headers.set("content-type", "text/javascript");
+ return serializeToStream(instance, x);
+ }
+ return x;
+ }
}
-function handleNoJS(
- result: any,
- request: Request,
- parsed: any[],
- thrown?: boolean,
-) {
- const url = new URL(request.url);
- const isError = result instanceof Error;
- let statusCode = 302;
- let headers: Headers;
- if (result instanceof Response) {
- headers = new Headers(result.headers);
- if (result.headers.has("Location")) {
- headers.set(
- `Location`,
- new URL(
- result.headers.get("Location")!,
- url.origin + import.meta.env.BASE_URL,
- ).toString(),
- );
- statusCode = getExpectedRedirectStatus(result);
- }
- } else
- headers = new Headers({
- Location: new URL(request.headers.get("referer")!).toString(),
- });
- if (result) {
- headers.append(
- "Set-Cookie",
- `flash=${encodeURIComponent(
- JSON.stringify({
- url: url.pathname + url.search,
- result: isError ? result.message : result,
- thrown: thrown,
- error: isError,
- input: [
- ...parsed.slice(0, -1),
- [...parsed[parsed.length - 1].entries()],
- ],
- }),
- )}; Secure; HttpOnly;`,
- );
- }
- return new Response(null, {
- status: statusCode,
- headers,
- });
+function handleNoJS(result: any, request: Request, parsed: any[], thrown?: boolean) {
+ const url = new URL(request.url);
+ const isError = result instanceof Error;
+ let statusCode = 302;
+ let headers: Headers;
+ if (result instanceof Response) {
+ headers = new Headers(result.headers);
+ if (result.headers.has("Location")) {
+ headers.set(
+ `Location`,
+ new URL(result.headers.get("Location")!, url.origin + import.meta.env.BASE_URL).toString(),
+ );
+ statusCode = getExpectedRedirectStatus(result);
+ }
+ } else
+ headers = new Headers({
+ Location: new URL(request.headers.get("referer")!).toString(),
+ });
+ if (result) {
+ headers.append(
+ "Set-Cookie",
+ `flash=${encodeURIComponent(
+ JSON.stringify({
+ url: url.pathname + url.search,
+ result: isError ? result.message : result,
+ thrown: thrown,
+ error: isError,
+ input: [...parsed.slice(0, -1), [...parsed[parsed.length - 1].entries()]],
+ }),
+ )}; Secure; HttpOnly;`,
+ );
+ }
+ return new Response(null, {
+ status: statusCode,
+ headers,
+ });
}
let App: any;
function createSingleFlightHeaders(sourceEvent: FetchEvent) {
- // cookie handling logic is pretty simplistic so this might be imperfect
- // unclear if h3 internals are available on all platforms but we need a way to
- // update request headers on the underlying H3 event.
+ // cookie handling logic is pretty simplistic so this might be imperfect
+ // unclear if h3 internals are available on all platforms but we need a way to
+ // update request headers on the underlying H3 event.
- const headers = sourceEvent.request.headers;
- const cookies = parseCookies(sourceEvent.nativeEvent);
- const SetCookies = sourceEvent.response.headers.getSetCookie();
- headers.delete("cookie");
- // let useH3Internals = false;
- // if (sourceEvent.nativeEvent.node?.req) {
- // useH3Internals = true;
- // sourceEvent.nativeEvent.node.req.headers.cookie = "";
- // }
- SetCookies.forEach((cookie) => {
- if (!cookie) return;
- const { maxAge, expires, name, value } = parseSetCookie(cookie);
- if (maxAge != null && maxAge <= 0) {
- delete cookies[name];
- return;
- }
- if (expires != null && expires.getTime() <= Date.now()) {
- delete cookies[name];
- return;
- }
- cookies[name] = value;
- });
- Object.entries(cookies).forEach(([key, value]) => {
- headers.append("cookie", `${key}=${value}`);
- // useH3Internals &&
- // (sourceEvent.nativeEvent.node.req.headers.cookie += `${key}=${value};`);
- });
+ const headers = sourceEvent.request.headers;
+ const cookies = parseCookies(sourceEvent.nativeEvent);
+ const SetCookies = sourceEvent.response.headers.getSetCookie();
+ headers.delete("cookie");
+ // let useH3Internals = false;
+ // if (sourceEvent.nativeEvent.node?.req) {
+ // useH3Internals = true;
+ // sourceEvent.nativeEvent.node.req.headers.cookie = "";
+ // }
+ SetCookies.forEach(cookie => {
+ if (!cookie) return;
+ const { maxAge, expires, name, value } = parseSetCookie(cookie);
+ if (maxAge != null && maxAge <= 0) {
+ delete cookies[name];
+ return;
+ }
+ if (expires != null && expires.getTime() <= Date.now()) {
+ delete cookies[name];
+ return;
+ }
+ cookies[name] = value;
+ });
+ Object.entries(cookies).forEach(([key, value]) => {
+ headers.append("cookie", `${key}=${value}`);
+ // useH3Internals &&
+ // (sourceEvent.nativeEvent.node.req.headers.cookie += `${key}=${value};`);
+ });
- return headers;
+ return headers;
}
-async function handleSingleFlight(
- sourceEvent: FetchEvent,
- result: any,
-): Promise {
- let revalidate: string[];
- let url = new URL(sourceEvent.request.headers.get("referer")!).toString();
- if (result instanceof Response) {
- if (result.headers.has("X-Revalidate"))
- revalidate = result.headers.get("X-Revalidate")!.split(",");
- if (result.headers.has("Location"))
- url = new URL(
- result.headers.get("Location")!,
- new URL(sourceEvent.request.url).origin +
- import.meta.env.BASE_URL,
- ).toString();
- }
- const event = { ...sourceEvent } as PageEvent;
- event.request = new Request(url, {
- headers: createSingleFlightHeaders(sourceEvent),
- });
- return await provideRequestEvent(event, async () => {
- await createPageEvent(event);
- App || (App = (await import("solid-start:app")).default);
- /* @ts-expect-error */
- event.router.dataOnly = revalidate || true;
- /* @ts-expect-error */
- event.router.previousUrl = sourceEvent.request.headers.get("referer");
- try {
- renderToString(() => {
- /* @ts-expect-error */
- sharedConfig.context.event = event;
- App();
- });
- } catch (e) {
- console.log(e);
- }
+async function handleSingleFlight(sourceEvent: FetchEvent, result: any): Promise {
+ let revalidate: string[];
+ let url = new URL(sourceEvent.request.headers.get("referer")!).toString();
+ if (result instanceof Response) {
+ if (result.headers.has("X-Revalidate"))
+ revalidate = result.headers.get("X-Revalidate")!.split(",");
+ if (result.headers.has("Location"))
+ url = new URL(
+ result.headers.get("Location")!,
+ new URL(sourceEvent.request.url).origin + import.meta.env.BASE_URL,
+ ).toString();
+ }
+ const event = { ...sourceEvent } as PageEvent;
+ event.request = new Request(url, {
+ headers: createSingleFlightHeaders(sourceEvent),
+ });
+ return await provideRequestEvent(event, async () => {
+ await createPageEvent(event);
+ App || (App = (await import("solid-start:app")).default);
+ /* @ts-expect-error */
+ event.router.dataOnly = revalidate || true;
+ /* @ts-expect-error */
+ event.router.previousUrl = sourceEvent.request.headers.get("referer");
+ try {
+ renderToString(() => {
+ /* @ts-expect-error */
+ sharedConfig.context.event = event;
+ App();
+ });
+ } catch (e) {
+ console.log(e);
+ }
- /* @ts-expect-error */
- const body = event.router.data;
- if (!body) return result;
- let containsKey = false;
- for (const key in body) {
- if (body[key] === undefined) delete body[key];
- else containsKey = true;
- }
- if (!containsKey) return result;
- if (!(result instanceof Response)) {
- body["_$value"] = result;
- result = new Response(null, { status: 200 });
- } else if ((result as any).customBody) {
- body["_$value"] = (result as any).customBody();
- }
- result.customBody = () => body;
- result.headers.set("X-Single-Flight", "true");
- return result;
- });
+ /* @ts-expect-error */
+ const body = event.router.data;
+ if (!body) return result;
+ let containsKey = false;
+ for (const key in body) {
+ if (body[key] === undefined) delete body[key];
+ else containsKey = true;
+ }
+ if (!containsKey) return result;
+ if (!(result instanceof Response)) {
+ body["_$value"] = result;
+ result = new Response(null, { status: 200 });
+ } else if ((result as any).customBody) {
+ body["_$value"] = (result as any).customBody();
+ }
+ result.customBody = () => body;
+ result.headers.set("X-Single-Flight", "true");
+ return result;
+ });
}
diff --git a/packages/start/src/server/server-runtime.ts b/packages/start/src/server/server-runtime.ts
index 0af198aea..8bbabe40b 100644
--- a/packages/start/src/server/server-runtime.ts
+++ b/packages/start/src/server/server-runtime.ts
@@ -11,7 +11,7 @@ import {
RequestPlugin,
ResponsePlugin,
URLPlugin,
- URLSearchParamsPlugin
+ URLSearchParamsPlugin,
} from "seroval-plugins/web";
import { type Component } from "solid-js";
@@ -46,7 +46,7 @@ class SerovalChunkReader {
if (this.done) {
return {
done: true,
- value: undefined
+ value: undefined,
};
}
// Otherwise, read a new chunk
@@ -77,7 +77,7 @@ class SerovalChunkReader {
// Deserialize the chunk
return {
done: false,
- value: deserialize(partial)
+ value: deserialize(partial),
};
}
@@ -107,7 +107,7 @@ async function deserializeStream(id: string, response: Response) {
},
() => {
// no-op
- }
+ },
);
}
@@ -123,8 +123,8 @@ function createRequest(base: string, id: string, instance: string, options: Requ
headers: {
...options.headers,
"X-Server-Id": id,
- "X-Server-Instance": instance
- }
+ "X-Server-Instance": instance,
+ },
});
}
@@ -138,14 +138,14 @@ const plugins = [
RequestPlugin,
ResponsePlugin,
URLSearchParamsPlugin,
- URLPlugin
+ URLPlugin,
];
async function fetchServerFunction(
base: string,
id: string,
options: Omit,
- args: any[]
+ args: any[],
) {
const instance = `server-fn:${INSTANCE++}`;
const response = await (args.length === 0
@@ -156,12 +156,12 @@ async function fetchServerFunction(
? createRequest(base, id, instance, {
...options,
body: args[0],
- headers: { ...options.headers, "Content-Type": "application/x-www-form-urlencoded" }
+ headers: { ...options.headers, "Content-Type": "application/x-www-form-urlencoded" },
})
: createRequest(base, id, instance, {
...options,
body: JSON.stringify(await Promise.resolve(toJSONAsync(args, { plugins }))),
- headers: { ...options.headers, "Content-Type": "application/json" }
+ headers: { ...options.headers, "Content-Type": "application/json" },
}));
if (
@@ -195,7 +195,7 @@ async function fetchServerFunction(
export function createServerReference(id: string) {
let baseURL = import.meta.env.BASE_URL ?? "/";
- if(!baseURL.endsWith("/")) baseURL += "/"
+ if (!baseURL.endsWith("/")) baseURL += "/";
const fn = (...args: any[]) => fetchServerFunction(`${baseURL}_server`, id, {}, args);
@@ -217,13 +217,13 @@ export function createServerReference(id: string) {
? url +
(args.length
? `&args=${encodeURIComponent(
- JSON.stringify(await Promise.resolve(toJSONAsync(args, { plugins })))
+ JSON.stringify(await Promise.resolve(toJSONAsync(args, { plugins }))),
)}`
: "")
: `${baseURL}_server`,
id,
options,
- encodeArgs ? [] : args
+ encodeArgs ? [] : args,
);
};
fn.url = url;
diff --git a/packages/start/src/server/spa/handler.ts b/packages/start/src/server/spa/handler.ts
index a9234d0c8..baf9ebd53 100644
--- a/packages/start/src/server/spa/handler.ts
+++ b/packages/start/src/server/spa/handler.ts
@@ -9,21 +9,21 @@ import type { FetchEvent, HandlerOptions, PageEvent } from "../types.ts";
* Read more: https://docs.solidjs.com/solid-start/reference/server/create-handler
*/
export function createHandler(
- fn: (context: PageEvent) => JSX.Element,
- options?: HandlerOptions | ((context: PageEvent) => HandlerOptions),
+ fn: (context: PageEvent) => JSX.Element,
+ options?: HandlerOptions | ((context: PageEvent) => HandlerOptions),
) {
- return createBaseHandler(createPageEvent, fn, options);
+ return createBaseHandler(createPageEvent, fn, options);
}
async function createPageEvent(ctx: FetchEvent) {
- const manifest = getSsrManifest("ssr");
- const pageEvent: PageEvent = Object.assign(ctx, {
- manifest: "json" in manifest ? await manifest.json() : {},
- assets: await manifest.getAssets(import.meta.env.START_CLIENT_ENTRY),
- routes: [],
- complete: false,
- $islands: new Set(),
- });
+ const manifest = getSsrManifest("ssr");
+ const pageEvent: PageEvent = Object.assign(ctx, {
+ manifest: "json" in manifest ? await manifest.json() : {},
+ assets: await manifest.getAssets(import.meta.env.START_CLIENT_ENTRY),
+ routes: [],
+ complete: false,
+ $islands: new Set(),
+ });
- return pageEvent;
+ return pageEvent;
}
diff --git a/packages/start/src/server/types.ts b/packages/start/src/server/types.ts
index 52998b597..b59467f78 100644
--- a/packages/start/src/server/types.ts
+++ b/packages/start/src/server/types.ts
@@ -5,78 +5,78 @@ import type { RequestEvent } from "solid-js/web";
// export const FETCH_EVENT = "$FETCH";
export type DocumentComponentProps = {
- assets?: JSX.Element;
- scripts: JSX.Element;
- children?: JSX.Element;
+ assets?: JSX.Element;
+ scripts: JSX.Element;
+ children?: JSX.Element;
};
export type Asset =
- | {
- tag: "style";
- attrs: JSX.StyleHTMLAttributes & { key?: string };
- children?: JSX.Element;
- }
- | {
- tag: "script";
- attrs: JSX.ScriptHTMLAttributes & { key?: string };
- }
- | {
- tag: "link";
- attrs: JSX.LinkHTMLAttributes & { key?: string };
- };
+ | {
+ tag: "style";
+ attrs: JSX.StyleHTMLAttributes & { key?: string };
+ children?: JSX.Element;
+ }
+ | {
+ tag: "script";
+ attrs: JSX.ScriptHTMLAttributes & { key?: string };
+ }
+ | {
+ tag: "link";
+ attrs: JSX.LinkHTMLAttributes & { key?: string };
+ };
export type HandlerOptions = {
- mode?: "sync" | "async" | "stream";
- nonce?: string;
- renderId?: string;
- onCompleteAll?: (options: { write: (v: any) => void }) => void;
- onCompleteShell?: (options: { write: (v: any) => void }) => void;
+ mode?: "sync" | "async" | "stream";
+ nonce?: string;
+ renderId?: string;
+ onCompleteAll?: (options: { write: (v: any) => void }) => void;
+ onCompleteShell?: (options: { write: (v: any) => void }) => void;
};
export type ContextMatches = {
- originalPath: string;
- pattern: string;
- path: string;
- params: unknown;
+ originalPath: string;
+ pattern: string;
+ path: string;
+ params: unknown;
};
export interface ResponseStub {
- status?: number;
- statusText?: string;
- headers: Headers;
+ status?: number;
+ statusText?: string;
+ headers: Headers;
}
export interface FetchEvent {
- request: Request;
- response: ResponseStub;
- clientAddress?: string;
- locals: App.RequestEventLocals;
- nativeEvent: H3Event;
+ request: Request;
+ response: ResponseStub;
+ clientAddress?: string;
+ locals: App.RequestEventLocals;
+ nativeEvent: H3Event;
}
export interface PageEvent extends RequestEvent {
- assets: any[];
- routes: any[];
- // prevUrl: string | null;
- // $type: typeof FETCH_EVENT;
- $islands: Set;
- complete: boolean;
- nonce?: string;
- // mutation: boolean;
+ assets: any[];
+ routes: any[];
+ // prevUrl: string | null;
+ // $type: typeof FETCH_EVENT;
+ $islands: Set;
+ complete: boolean;
+ nonce?: string;
+ // mutation: boolean;
}
export interface APIEvent extends FetchEvent {
- params: { [key: string]: string };
+ params: { [key: string]: string };
}
export type APIHandler = (event: APIEvent) => Promise;
export interface ServerFunctionMeta {
- id: string;
+ id: string;
}
declare module "solid-js/web" {
- interface RequestEvent extends FetchEvent {
- serverOnly?: boolean;
- }
+ interface RequestEvent extends FetchEvent {
+ serverOnly?: boolean;
+ }
}
diff --git a/packages/start/src/server/util.ts b/packages/start/src/server/util.ts
index 5aa7f0d07..da325bf49 100644
--- a/packages/start/src/server/util.ts
+++ b/packages/start/src/server/util.ts
@@ -4,9 +4,9 @@ import type { ResponseStub } from "./types.ts";
const validRedirectStatuses = new Set([301, 302, 303, 307, 308]);
export function getExpectedRedirectStatus(response: ResponseStub): number {
- if (response.status && validRedirectStatuses.has(response.status)) {
- return response.status;
- }
+ if (response.status && validRedirectStatuses.has(response.status)) {
+ return response.status;
+ }
- return 302;
+ return 302;
}
diff --git a/packages/start/src/shared/ErrorBoundary.tsx b/packages/start/src/shared/ErrorBoundary.tsx
index cc3f84217..6be12348e 100644
--- a/packages/start/src/shared/ErrorBoundary.tsx
+++ b/packages/start/src/shared/ErrorBoundary.tsx
@@ -37,7 +37,7 @@ export const TopErrorBoundary = (props: ParentProps) => {
err => {
console.error(err);
isError = !!err;
- }
+ },
);
return isError ? (
<>
diff --git a/packages/start/src/shared/HttpHeader.tsx b/packages/start/src/shared/HttpHeader.tsx
index 30e061a4c..6dcb504b6 100644
--- a/packages/start/src/shared/HttpHeader.tsx
+++ b/packages/start/src/shared/HttpHeader.tsx
@@ -17,26 +17,26 @@ export interface HttpHeaderProps {
*/
export const HttpHeader = isServer
? (props: HttpHeaderProps) => {
- const event = getRequestEvent() as PageEvent;
+ const event = getRequestEvent() as PageEvent;
- if (props.append) appendHeader(props.name, props.value);
- else setHeader(props.name, props.value);
+ if (props.append) appendHeader(props.name, props.value);
+ else setHeader(props.name, props.value);
- onCleanup(() => {
- // @ts-expect-error
- if (event.nativeEvent.handled || event.complete) return;
- const value = event.response.headers.get(props.name);
- if (!value) return;
- if (!value.includes(", ")) {
- if (value === props.value) event.response.headers.delete(props.name);
- return;
- }
- const values = value.split(", ");
- const index = values.indexOf(props.value);
- index !== -1 && values.splice(index, 1);
- if (values.length) event.response.headers.set(props.name, values.join(","));
- else event.response.headers.delete(props.name);
- });
- return null;
- }
+ onCleanup(() => {
+ // @ts-expect-error
+ if (event.nativeEvent.handled || event.complete) return;
+ const value = event.response.headers.get(props.name);
+ if (!value) return;
+ if (!value.includes(", ")) {
+ if (value === props.value) event.response.headers.delete(props.name);
+ return;
+ }
+ const values = value.split(", ");
+ const index = values.indexOf(props.value);
+ index !== -1 && values.splice(index, 1);
+ if (values.length) event.response.headers.set(props.name, values.join(","));
+ else event.response.headers.delete(props.name);
+ });
+ return null;
+ }
: (_props: HttpHeaderProps) => null;
diff --git a/packages/start/src/shared/HttpStatusCode.ts b/packages/start/src/shared/HttpStatusCode.ts
index b378f93cb..56a86b06d 100644
--- a/packages/start/src/shared/HttpStatusCode.ts
+++ b/packages/start/src/shared/HttpStatusCode.ts
@@ -4,8 +4,8 @@ import { getRequestEvent, isServer } from "solid-js/web";
import type { PageEvent } from "../server/types.ts";
export interface HttpStatusCodeProps {
- code: number;
- text?: string;
+ code: number;
+ text?: string;
}
/**
@@ -13,15 +13,15 @@ export interface HttpStatusCodeProps {
* Read more: https://docs.solidjs.com/solid-start/reference/server/http-status-code
*/
export const HttpStatusCode = isServer
- ? (props: HttpStatusCodeProps) => {
- const event = getRequestEvent() as PageEvent;
- event.response.status = props.code;
- event.response.statusText = props.text;
- onCleanup(
- () =>
- // !event.nativeEvent.handled &&
- !event.complete && (event.response.status = 200),
- );
- return null;
- }
- : (_props: HttpStatusCodeProps) => null;
+ ? (props: HttpStatusCodeProps) => {
+ const event = getRequestEvent() as PageEvent;
+ event.response.status = props.code;
+ event.response.statusText = props.text;
+ onCleanup(
+ () =>
+ // !event.nativeEvent.handled &&
+ !event.complete && (event.response.status = 200),
+ );
+ return null;
+ }
+ : (_props: HttpStatusCodeProps) => null;
diff --git a/packages/start/src/shared/clientOnly.ts b/packages/start/src/shared/clientOnly.ts
index bee0711db..899a1d545 100644
--- a/packages/start/src/shared/clientOnly.ts
+++ b/packages/start/src/shared/clientOnly.ts
@@ -12,7 +12,7 @@ export default function clientOnly>(
fn: () => Promise<{
default: T;
}>,
- options: { lazy?: boolean } = {}
+ options: { lazy?: boolean } = {},
) {
if (isServer) return (props: ComponentProps & { fallback?: JSX.Element }) => props.fallback;
@@ -29,7 +29,7 @@ export default function clientOnly>(
return createMemo(
() => (
(Comp = comp()), (m = mounted()), untrack(() => (Comp && m ? Comp(rest) : props.fallback))
- )
+ ),
);
};
}
@@ -38,7 +38,7 @@ function load(
fn: () => Promise<{
default: T;
}>,
- setComp: Setter
+ setComp: Setter,
) {
fn().then(m => setComp(() => m.default));
}
diff --git a/packages/start/src/shared/dev-overlay/CodeView.tsx b/packages/start/src/shared/dev-overlay/CodeView.tsx
index 3116ce5e5..5af80976a 100644
--- a/packages/start/src/shared/dev-overlay/CodeView.tsx
+++ b/packages/start/src/shared/dev-overlay/CodeView.tsx
@@ -1,31 +1,24 @@
// @refresh skip
-import { getSingletonHighlighter, type BuiltinLanguage, type Highlighter } from 'shiki';
-import { loadWasm } from 'shiki/engine/oniguruma';
-import { createEffect, createResource, type JSX } from 'solid-js';
+import { getSingletonHighlighter, type BuiltinLanguage, type Highlighter } from "shiki";
+import { loadWasm } from "shiki/engine/oniguruma";
+import { createEffect, createResource, type JSX } from "solid-js";
-import url from 'shiki/onig.wasm?url';
+import url from "shiki/onig.wasm?url";
-import langJS from 'shiki/langs/javascript.mjs';
-import langJSX from 'shiki/langs/jsx.mjs';
-import langTSX from 'shiki/langs/tsx.mjs';
-import langTS from 'shiki/langs/typescript.mjs';
-import darkPlus from 'shiki/themes/dark-plus.mjs';
+import langJS from "shiki/langs/javascript.mjs";
+import langJSX from "shiki/langs/jsx.mjs";
+import langTSX from "shiki/langs/tsx.mjs";
+import langTS from "shiki/langs/typescript.mjs";
+import darkPlus from "shiki/themes/dark-plus.mjs";
let HIGHLIGHTER: Highlighter;
async function loadHighlighter() {
if (!HIGHLIGHTER) {
- await loadWasm(await fetch(url))
+ await loadWasm(await fetch(url));
HIGHLIGHTER = await getSingletonHighlighter({
- themes: [
- darkPlus,
- ],
- langs: [
- langJS,
- langJSX,
- langTS,
- langTSX,
- ],
+ themes: [darkPlus],
+ langs: [langJS, langJSX, langTS, langTSX],
});
}
return HIGHLIGHTER;
@@ -41,7 +34,7 @@ const RANGE = 8;
export function CodeView(props: CodeViewProps): JSX.Element | null {
const lines = () =>
- props.content.split('\n').map((item, index) => ({
+ props.content.split("\n").map((item, index) => ({
index: index + 1,
line: item,
}));
@@ -51,27 +44,25 @@ export function CodeView(props: CodeViewProps): JSX.Element | null {
let ref: HTMLDivElement | undefined;
- const [data] = createResource(() => (
- lines()
- .slice(minLine(), maxLine())
- .map(item => item.line)
- .join('\n')
- ) ,async (value) => {
- const highlighter = await loadHighlighter();
- const fileExtension = props.fileName
- .split(/[#?]/)[0]!
- .split('.')
- .pop()
- ?.trim();
- let lang = fileExtension as BuiltinLanguage;
- if (fileExtension === 'mjs' || fileExtension === 'cjs') {
- lang = 'js';
- }
- return highlighter.codeToHtml(value, {
- theme: 'dark-plus',
- lang,
- });
- });
+ const [data] = createResource(
+ () =>
+ lines()
+ .slice(minLine(), maxLine())
+ .map(item => item.line)
+ .join("\n"),
+ async value => {
+ const highlighter = await loadHighlighter();
+ const fileExtension = props.fileName.split(/[#?]/)[0]!.split(".").pop()?.trim();
+ let lang = fileExtension as BuiltinLanguage;
+ if (fileExtension === "mjs" || fileExtension === "cjs") {
+ lang = "js";
+ }
+ return highlighter.codeToHtml(value, {
+ theme: "dark-plus",
+ lang,
+ });
+ },
+ );
createEffect(() => {
const result = data();
@@ -82,14 +73,20 @@ export function CodeView(props: CodeViewProps): JSX.Element | null {
for (let i = 0, len = lines.length; i < len; i++) {
const el = lines[i] as HTMLElement;
- if ((props.line - minLine() - 1) === i) {
- el.classList.add('dev-overlay-error-line');
+ if (props.line - minLine() - 1 === i) {
+ el.classList.add("dev-overlay-error-line");
}
}
}
});
- return
;
+ return (
+
+ );
}
diff --git a/packages/start/src/shared/dev-overlay/DevOverlayDialog.tsx b/packages/start/src/shared/dev-overlay/DevOverlayDialog.tsx
index 4d10d90d0..e3b836d7a 100644
--- a/packages/start/src/shared/dev-overlay/DevOverlayDialog.tsx
+++ b/packages/start/src/shared/dev-overlay/DevOverlayDialog.tsx
@@ -19,7 +19,7 @@ import {
RefreshIcon,
SolidStartIcon,
ViewCompiledIcon,
- ViewOriginalIcon
+ ViewOriginalIcon,
} from "./icons.tsx";
import "./styles.css";
@@ -134,7 +134,7 @@ function StackFramesContent(props: StackFramesContentProps) {
content: "",
line: current.getLineNumber()!,
column: current.getColumnNumber()!,
- name: current.getFunctionName()
+ name: current.getFunctionName(),
})}
@@ -225,8 +225,8 @@ export default function DevOverlayDialog(props: DevOverlayDialogProps): JSX.Elem
htmlToImage
.toPng(current, {
style: {
- transform: "scale(0.75)"
- }
+ transform: "scale(0.75)",
+ },
})
.then(url => {
download(url, "start-screenshot.png");
diff --git a/packages/start/src/shared/dev-overlay/createStackFrame.ts b/packages/start/src/shared/dev-overlay/createStackFrame.ts
index 7d5bd8e90..df03cc76f 100644
--- a/packages/start/src/shared/dev-overlay/createStackFrame.ts
+++ b/packages/start/src/shared/dev-overlay/createStackFrame.ts
@@ -2,76 +2,73 @@ import { type Accessor, createMemo, createResource } from "solid-js";
import getSourceMap from "./get-source-map.ts";
export interface StackFrameSource {
- content: string;
- source: string;
- name?: string;
- line: number;
- column: number;
+ content: string;
+ source: string;
+ name?: string;
+ line: number;
+ column: number;
}
function getActualFileSource(path: string): string {
- if (path.startsWith("file://")) {
- return "/_build/@fs" + path.substring("file://".length);
- }
- return path;
+ if (path.startsWith("file://")) {
+ return "/_build/@fs" + path.substring("file://".length);
+ }
+ return path;
}
-export function createStackFrame(
- stackframe: StackFrame,
- isCompiled: () => boolean,
-) {
- const [data] = createResource(
- () => ({
- fileName: stackframe.fileName,
- line: stackframe.lineNumber,
- column: stackframe.columnNumber,
- functionName: stackframe.functionName,
- }),
- async (source) => {
- if (!source.fileName) {
- return null;
- }
- const response = await fetch(getActualFileSource(source.fileName));
- if (!response.ok) {
- return null;
- }
- const content = await response.text();
- const sourceMap = await getSourceMap(source.fileName, content);
- return {
- source,
- content,
- sourceMap,
- };
- },
- );
+export function createStackFrame(stackframe: StackFrame, isCompiled: () => boolean) {
+ const [data] = createResource(
+ () => ({
+ fileName: stackframe.fileName,
+ line: stackframe.lineNumber,
+ column: stackframe.columnNumber,
+ functionName: stackframe.functionName,
+ }),
+ async source => {
+ if (!source.fileName) {
+ return null;
+ }
+ const response = await fetch(getActualFileSource(source.fileName));
+ if (!response.ok) {
+ return null;
+ }
+ const content = await response.text();
+ const sourceMap = await getSourceMap(source.fileName, content);
+ return {
+ source,
+ content,
+ sourceMap,
+ };
+ },
+ );
- const info = createMemo(() => {
- const current = data();
- if (!current) {
- return undefined;
- }
- const { source, content, sourceMap } = current;
+ const info = createMemo(() => {
+ const current = data();
+ if (!current) {
+ return undefined;
+ }
+ const { source, content, sourceMap } = current;
- if (!isCompiled() && source.line && source.column && sourceMap) {
- const result = sourceMap.originalPositionFor({
- line: source.line,
- column: source.column,
- });
+ if (!isCompiled() && source.line && source.column && sourceMap) {
+ const result = sourceMap.originalPositionFor({
+ line: source.line,
+ column: source.column,
+ });
- return {
- ...result,
- content: sourceMap.sourceContentFor(result.source),
- } as StackFrameSource;
- }
+ return {
+ ...result,
+ content: sourceMap.sourceContentFor(result.source),
+ } as StackFrameSource;
+ }
- return {
- source: source.fileName,
- line: source.line,
- column: source.column,
- name: source.functionName,
- content,
- } as StackFrameSource;
- });
+ return {
+ source: source.fileName,
+ line: source.line,
+ column: source.column,
+ name: source.functionName,
+ content,
+ } as StackFrameSource;
+ });
- return info as Accessor;
+ return info as Accessor;
}
diff --git a/packages/start/src/shared/dev-overlay/env.d.ts b/packages/start/src/shared/dev-overlay/env.d.ts
index 8c54073db..ac68ef8f4 100644
--- a/packages/start/src/shared/dev-overlay/env.d.ts
+++ b/packages/start/src/shared/dev-overlay/env.d.ts
@@ -1,4 +1,4 @@
-declare module '*.json' {
+declare module "*.json" {
const data: Record;
export default data;
-}
\ No newline at end of file
+}
diff --git a/packages/start/src/shared/dev-overlay/get-source-map.ts b/packages/start/src/shared/dev-overlay/get-source-map.ts
index 2b8b164d6..0447a10d1 100644
--- a/packages/start/src/shared/dev-overlay/get-source-map.ts
+++ b/packages/start/src/shared/dev-overlay/get-source-map.ts
@@ -1,4 +1,4 @@
-import { RawSourceMap, SourceMapConsumer } from 'source-map-js';
+import { RawSourceMap, SourceMapConsumer } from "source-map-js";
const INLINE_SOURCEMAP_REGEX = /^data:application\/json[^,]+base64,/;
const SOURCEMAP_REGEX =
@@ -8,7 +8,7 @@ export default async function getSourceMap(
url: string,
content: string,
): Promise {
- const lines = content.split('\n');
+ const lines = content.split("\n");
let sourceMapUrl: string | undefined;
for (let i = lines.length - 1; i >= 0 && !sourceMapUrl; i--) {
const result = lines[i]!.match(SOURCEMAP_REGEX);
@@ -21,13 +21,11 @@ export default async function getSourceMap(
return null;
}
- if (
- !(INLINE_SOURCEMAP_REGEX.test(sourceMapUrl) || sourceMapUrl.startsWith('/'))
- ) {
+ if (!(INLINE_SOURCEMAP_REGEX.test(sourceMapUrl) || sourceMapUrl.startsWith("/"))) {
// Resolve path if it's a relative access
- const parsedURL = url.split('/');
+ const parsedURL = url.split("/");
parsedURL[parsedURL.length - 1] = sourceMapUrl;
- sourceMapUrl = parsedURL.join('/');
+ sourceMapUrl = parsedURL.join("/");
}
const response = await fetch(sourceMapUrl);
const rawSourceMap: RawSourceMap = await response.json();
diff --git a/packages/start/src/shared/dev-overlay/icons.tsx b/packages/start/src/shared/dev-overlay/icons.tsx
index 210d328fa..dd5598b3e 100644
--- a/packages/start/src/shared/dev-overlay/icons.tsx
+++ b/packages/start/src/shared/dev-overlay/icons.tsx
@@ -1,8 +1,8 @@
// @refresh skip
-import type { JSX } from 'solid-js';
+import type { JSX } from "solid-js";
export function ArrowRightIcon(
- props: JSX.IntrinsicElements['svg'] & { title: string },
+ props: JSX.IntrinsicElements["svg"] & { title: string },
): JSX.Element {
return (
{props.title}
-
+
{props.title}
-
+
);
}
export function SolidStartIcon(
- props: JSX.IntrinsicElements['svg'] & { title: string },
+ props: JSX.IntrinsicElements["svg"] & { title: string },
): JSX.Element {
return (
-
+
{props.title}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
}
-
diff --git a/packages/start/src/shared/dev-overlay/index.tsx b/packages/start/src/shared/dev-overlay/index.tsx
index e581e9520..e14e3c1c3 100644
--- a/packages/start/src/shared/dev-overlay/index.tsx
+++ b/packages/start/src/shared/dev-overlay/index.tsx
@@ -6,7 +6,7 @@ import {
createSignal,
onCleanup,
resetErrorBoundaries,
- type JSX
+ type JSX,
} from "solid-js";
import { HttpStatusCode } from "../HttpStatusCode.ts";
import clientOnly from "../clientOnly.ts";
diff --git a/packages/start/src/shared/lazy.ts b/packages/start/src/shared/lazy.ts
index df961921b..4904e57ba 100644
--- a/packages/start/src/shared/lazy.ts
+++ b/packages/start/src/shared/lazy.ts
@@ -38,14 +38,15 @@ const withAssets = function Promise<{ default: Component }
useAssets(assets, nonce);
return mod.default(props);
- }
+ },
};
};
return wrapper as T;
};
-const lazy = !isServer ? solidLazy: >(fn: () => Promise<{ default: T }>) =>
- solidLazy(withAssets(fn));
+const lazy = !isServer
+ ? solidLazy
+ : >(fn: () => Promise<{ default: T }>) => solidLazy(withAssets(fn));
export default lazy;
diff --git a/packages/start/src/shared/serverFunction.ts b/packages/start/src/shared/serverFunction.ts
index 394d4e533..8de3b0a3b 100644
--- a/packages/start/src/shared/serverFunction.ts
+++ b/packages/start/src/shared/serverFunction.ts
@@ -6,5 +6,5 @@ import type { ServerFunctionMeta } from "../server/types.ts";
* Read more: https://docs.solidjs.com/solid-start/reference/server/get-server-function-meta
*/
export function getServerFunctionMeta(): ServerFunctionMeta | undefined {
- return getRequestEvent()?.locals.serverFunctionMeta;
+ return getRequestEvent()?.locals.serverFunctionMeta;
}
diff --git a/packages/start/src/virtual.d.ts b/packages/start/src/virtual.d.ts
index 68ab708ee..53083c11d 100644
--- a/packages/start/src/virtual.d.ts
+++ b/packages/start/src/virtual.d.ts
@@ -1,27 +1,27 @@
declare module "solid-start:client-vite-manifest" {
- export const clientViteManifest: Record<
- string,
- { css?: Array; file: string; [key: string]: unknown }
- >;
+ export const clientViteManifest: Record<
+ string,
+ { css?: Array; file: string; [key: string]: unknown }
+ >;
}
interface StartManifest {
- getAssets(id: string): Promise;
+ getAssets(id: string): Promise;
}
declare module "solid-start:get-client-manifest" {
- export const getClientManifest: () => StartManifest;
+ export const getClientManifest: () => StartManifest;
}
declare module "solid-start:get-manifest" {
- export const getManifest: (target: "client" | "ssr") => StartManifest;
+ export const getManifest: (target: "client" | "ssr") => StartManifest;
}
declare module "solid-start:app" {
- export default App as import("solid-js").Component;
+ export default App as import("solid-js").Component;
}
declare module "solid-start:middleware" {
- type MaybeArray = T | Array;
- export default Middleware as import("h3").Middleware[];
+ type MaybeArray = T | Array;
+ export default Middleware as import("h3").Middleware[];
}
diff --git a/packages/start/vitest.config.ts b/packages/start/vitest.config.ts
index 8cac8fda7..0cf5c2332 100644
--- a/packages/start/vitest.config.ts
+++ b/packages/start/vitest.config.ts
@@ -4,6 +4,6 @@ export default defineConfig({
test: {
globals: true,
environment: "node",
- mockReset: true
- }
+ mockReset: true,
+ },
});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index bf2c2914b..549f6ed49 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -19,6 +19,9 @@ importers:
citty:
specifier: ^0.1.5
version: 0.1.6
+ oxfmt:
+ specifier: ^0.14.0
+ version: 0.14.0
tinyglobby:
specifier: ^0.2.2
version: 0.2.15
@@ -1560,6 +1563,46 @@ packages:
cpu: [x64]
os: [win32]
+ '@oxfmt/darwin-arm64@0.14.0':
+ resolution: {integrity: sha512-g8FANFTuzEcB2KLsE2IcQYXjdgDi8x9GUf8c4t7iyFD7oj0HGucKHhoMz3XsRWTx8szBZoJJD+t4bzs4+AMFdQ==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@oxfmt/darwin-x64@0.14.0':
+ resolution: {integrity: sha512-Hd/DI+a8PKhl33CmaR3eQdx2P4zpaeoUwjOJQd090cFEbEX9auoCo6+t4LLm/JlzgnRSnFq0EaZOWJVK3wDu8Q==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@oxfmt/linux-arm64-gnu@0.14.0':
+ resolution: {integrity: sha512-JzMyMKuDY9UmxRRnHWFdzYIXYZ2SK2/RmJKhYS47lcRELQC64nzuFe0d5JkRnt7KIJoM7RdUmYqEr+UKdiZ5mg==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@oxfmt/linux-arm64-musl@0.14.0':
+ resolution: {integrity: sha512-sPLA+jvL5kArpnUpxlt6v/EZCGvIhe8Z6hnNuGUa4gdYfzVf2XhAK1jO6hrrjFMT+2cnkbqmxa5iuZqCT6Y5xg==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@oxfmt/linux-x64-gnu@0.14.0':
+ resolution: {integrity: sha512-2hWVwIBa756NHs3+19om1mQp2C4vnGhFGe75AmsRRlkLq1vttC1iuQoF6slQQTS6n0/d7o4Pg1wGY3kldY6Msw==}
+ cpu: [x64]
+ os: [linux]
+
+ '@oxfmt/linux-x64-musl@0.14.0':
+ resolution: {integrity: sha512-bk98BFY2wArfWTVJ+T0zTCqF1deFfcyzrJ0/zppupQDFVdKUTga2XeKY8S1ImdyG+N7XcixdCrcT9db+SVNKMA==}
+ cpu: [x64]
+ os: [linux]
+
+ '@oxfmt/win32-arm64@0.14.0':
+ resolution: {integrity: sha512-UxctetV+XOXGXYcJp8uwP+/cUq3GSTAxq6UBbeGUq+0j1je3zC4XCQ6Kh/dm6kxOnAzrmMkX1uG4Su4bwvMq8w==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@oxfmt/win32-x64@0.14.0':
+ resolution: {integrity: sha512-P/Cw1aP0UIf42HDH6t3+5IY0xx8e4HxCfDHQz/PDbJ+Vc2JhAB6rzkVFAOEo9inQsXoZVdApF/xklp4NJtrkqQ==}
+ cpu: [x64]
+ os: [win32]
+
'@parcel/watcher-android-arm64@2.4.1':
resolution: {integrity: sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==}
engines: {node: '>= 10.0.0'}
@@ -4305,6 +4348,11 @@ packages:
resolution: {integrity: sha512-dQPNIF+gHpSkmC0+Vg9IktNyhcn28Y8R3eTLyzn52UNymkasLicl3sFAtz7oEVuFmCpgGjaUTKkwk+jW2cHpDQ==}
engines: {node: ^20.19.0 || >=22.12.0}
+ oxfmt@0.14.0:
+ resolution: {integrity: sha512-cZpXmiiEIHxEWq1bkqgCM/9vMv4TQ8RCSA9l+5PPEuCewL+2qNP/7vZynIrQnByvUnJc/G3YOj95XH+GXYLaKg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+
p-event@5.0.1:
resolution: {integrity: sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -7022,6 +7070,30 @@ snapshots:
'@oxc-transform/binding-win32-x64-msvc@0.96.0':
optional: true
+ '@oxfmt/darwin-arm64@0.14.0':
+ optional: true
+
+ '@oxfmt/darwin-x64@0.14.0':
+ optional: true
+
+ '@oxfmt/linux-arm64-gnu@0.14.0':
+ optional: true
+
+ '@oxfmt/linux-arm64-musl@0.14.0':
+ optional: true
+
+ '@oxfmt/linux-x64-gnu@0.14.0':
+ optional: true
+
+ '@oxfmt/linux-x64-musl@0.14.0':
+ optional: true
+
+ '@oxfmt/win32-arm64@0.14.0':
+ optional: true
+
+ '@oxfmt/win32-x64@0.14.0':
+ optional: true
+
'@parcel/watcher-android-arm64@2.4.1':
optional: true
@@ -9911,6 +9983,17 @@ snapshots:
'@oxc-transform/binding-win32-arm64-msvc': 0.96.0
'@oxc-transform/binding-win32-x64-msvc': 0.96.0
+ oxfmt@0.14.0:
+ optionalDependencies:
+ '@oxfmt/darwin-arm64': 0.14.0
+ '@oxfmt/darwin-x64': 0.14.0
+ '@oxfmt/linux-arm64-gnu': 0.14.0
+ '@oxfmt/linux-arm64-musl': 0.14.0
+ '@oxfmt/linux-x64-gnu': 0.14.0
+ '@oxfmt/linux-x64-musl': 0.14.0
+ '@oxfmt/win32-arm64': 0.14.0
+ '@oxfmt/win32-x64': 0.14.0
+
p-event@5.0.1:
dependencies:
p-timeout: 5.1.0
diff --git a/scripts/bump.js b/scripts/bump.js
index 6e8304f58..bd67097e0 100644
--- a/scripts/bump.js
+++ b/scripts/bump.js
@@ -7,8 +7,8 @@ import { promisify } from "util";
const command = defineCommand({
args: {
vinxi: {
- description: "Bump vinxi packages to latest version"
- }
+ description: "Bump vinxi packages to latest version",
+ },
},
async run({ args }) {
const extPackageNames = ["solid-js"];
@@ -20,8 +20,8 @@ const command = defineCommand({
"@vinxi/plugin-directives",
"@vinxi/server-components",
"@vinxi/server-functions",
- "@vinxi/plugin-mdx"
- ]
+ "@vinxi/plugin-mdx",
+ ],
);
}
@@ -30,12 +30,12 @@ const command = defineCommand({
extPackageNames.map(async name => {
const proc = await execAsync(`npm view ${name} version`);
return { name, version: proc.stdout.toString().trim() };
- })
+ }),
);
await Promise.all(
- globSync(["package.json", "packages/*/package.json", "examples/*/package.json"])
- .map(async path => {
+ globSync(["package.json", "packages/*/package.json", "examples/*/package.json"]).map(
+ async path => {
const packageJson = JSON.parse(await fs.readFile(path));
let deps = packages;
for (const dep of deps) {
@@ -45,12 +45,13 @@ const command = defineCommand({
(packageJson.devDependencies[dep.name] = `^${dep.version}`);
}
await fs.writeFile(path, JSON.stringify(packageJson, null, 2) + "\n");
- })
+ },
+ ),
);
console.log("Updating lock file...\n");
spawnSync("pnpm i", { shell: true, stdio: "inherit" });
- }
+ },
});
runMain(command);