From 66e5aba9e5cc86f0c371f2e3079ef34e0223f925 Mon Sep 17 00:00:00 2001 From: Asher Gomez Date: Sun, 11 May 2025 22:42:26 +1000 Subject: [PATCH 1/7] feat(core): `SetupError` --- src/app.ts | 22 +++++------------- src/error.ts | 7 ++++++ src/finish_setup.tsx | 54 -------------------------------------------- 3 files changed, 13 insertions(+), 70 deletions(-) delete mode 100644 src/finish_setup.tsx diff --git a/src/app.ts b/src/app.ts index 1f67789b460..a0539a091dc 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,6 +1,5 @@ import * as path from "@std/path"; -import { type ComponentType, h } from "preact"; -import { renderToString } from "preact-render-to-string"; +import type { ComponentType } from "preact"; import { trace } from "@opentelemetry/api"; import { DENO_DEPLOYMENT_ID } from "./runtime/build_id.ts"; @@ -20,8 +19,7 @@ import { } from "./config.ts"; import { type BuildCache, ProdBuildCache } from "./build_cache.ts"; import type { ServerIslandRegistry } from "./context.ts"; -import { FinishSetup, ForgotBuild } from "./finish_setup.tsx"; -import { HttpError } from "./error.ts"; +import { HttpError, SetupError } from "./error.ts"; // TODO: Completed type clashes in older Deno versions // deno-lint-ignore no-explicit-any @@ -189,7 +187,10 @@ export class App { !this.#buildCache.hasSnapshot && this.config.mode === "production" && DENO_DEPLOYMENT_ID !== undefined ) { - return missingBuildHandler; + const message = DENO_DEPLOYMENT_ID + ? '`deno task build` must be run before starting the server. Go to "Settings" in Deno Deploy and set the build command to `deno task build`.' + : "`deno task build` must be run before starting the server."; + throw new SetupError(message); } return async ( @@ -325,14 +326,3 @@ export class App { } } } - -// deno-lint-ignore require-await -const missingBuildHandler = async (): Promise => { - const headers = new Headers(); - headers.set("Content-Type", "text/html; charset=utf-8"); - - const html = DENO_DEPLOYMENT_ID - ? renderToString(h(FinishSetup, null)) - : renderToString(h(ForgotBuild, null)); - return new Response(html, { headers, status: 500 }); -}; diff --git a/src/error.ts b/src/error.ts index d2cbaa71111..6d783abf7ef 100644 --- a/src/error.ts +++ b/src/error.ts @@ -74,3 +74,10 @@ export class HttpError extends Error { this.status = status; } } + +export class SetupError extends Error { + constructor(message: string) { + super(message); + this.name = this.constructor.name; + } +} diff --git a/src/finish_setup.tsx b/src/finish_setup.tsx deleted file mode 100644 index b3673d22059..00000000000 --- a/src/finish_setup.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import type { ComponentChildren } from "preact"; - -export function FinishSetup() { - return ( - -
-
-

Finish setting up Fresh

-
    -
  1. - Go to your project in Deno Deploy and click the{" "} - Settings tab. -
  2. -
  3. - In the Git Integration section, enter deno task build - {" "} - in the Build Command input. -
  4. -
  5. - Save the changes. -
  6. -
-
-
-
- ); -} - -export function ForgotBuild() { - return ( - -
-
-

Missing build directory

-

- Did you forget to run deno task build? -

-
-
-
- ); -} - -function Doc(props: { children?: ComponentChildren }) { - return ( - - - - Finish setting up Fresh - - {props.children} - - ); -} From fd8f4bd3171ad2fe1a68d8c4aad98247653a001e Mon Sep 17 00:00:00 2001 From: Asher Gomez Date: Mon, 12 May 2025 18:07:30 +1000 Subject: [PATCH 2/7] complete --- deno.lock | 3 ++- src/error.ts | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/deno.lock b/deno.lock index 5e30ab51502..c4ba8ca1be8 100644 --- a/deno.lock +++ b/deno.lock @@ -14,6 +14,7 @@ "jsr:@std/async@1": "1.0.12", "jsr:@std/bytes@^1.0.2": "1.0.5", "jsr:@std/bytes@^1.0.5": "1.0.5", + "jsr:@std/cli@1": "1.0.17", "jsr:@std/cli@^1.0.17": "1.0.17", "jsr:@std/collections@^1.0.11": "1.0.11", "jsr:@std/crypto@1": "1.0.4", @@ -215,7 +216,7 @@ "@std/http@1.0.15": { "integrity": "435a4934b4e196e82a8233f724da525f7b7112f3566502f28815e94764c19159", "dependencies": [ - "jsr:@std/cli", + "jsr:@std/cli@^1.0.17", "jsr:@std/encoding@^1.0.10", "jsr:@std/fmt@^1.0.7", "jsr:@std/html@^1.0.3", diff --git a/src/error.ts b/src/error.ts index 6d783abf7ef..6e82c9412e7 100644 --- a/src/error.ts +++ b/src/error.ts @@ -75,9 +75,40 @@ export class HttpError extends Error { } } +/** + * Error that's throw when the app setup fails. Usually caused by + * `deno task build` not being run before starting the server. + * + * @example Basic usage + * ```ts + * import { App, SetupError } from "fresh"; + * import { expect } from "@std/expect"; + * + * const app = new App() + * .get("/", () => new Response("ok")) + * .get("/not-found", () => { + * throw new SetupError("App not setup"); + * }); + * + * const handler = await app.handler(); + * + * try { + * await handler(new Request("http://localhost/not-found")) + * } catch (error) { + * expect(error).toBeInstanceOf(SetupError); + * expect(error.message).toBe("App not setup"); + * } + * ``` + */ export class SetupError extends Error { - constructor(message: string) { - super(message); + /** + * Constructs a new instance. + * + * @param message The error message. + * @param options Optional error options. + */ + constructor(message: string, options?: ErrorOptions) { + super(message, options); this.name = this.constructor.name; } } From d9ffc14d4909ebd833a2e3b433b9f5cfd9217081 Mon Sep 17 00:00:00 2001 From: Asher Gomez Date: Mon, 12 May 2025 18:18:27 +1000 Subject: [PATCH 3/7] fix --- src/error.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/error.ts b/src/error.ts index 6e82c9412e7..59a668db590 100644 --- a/src/error.ts +++ b/src/error.ts @@ -80,20 +80,16 @@ export class HttpError extends Error { * `deno task build` not being run before starting the server. * * @example Basic usage - * ```ts + * ```ts ignore * import { App, SetupError } from "fresh"; * import { expect } from "@std/expect"; * * const app = new App() * .get("/", () => new Response("ok")) - * .get("/not-found", () => { - * throw new SetupError("App not setup"); - * }); - * - * const handler = await app.handler(); * * try { - * await handler(new Request("http://localhost/not-found")) + * // Throws if `deno task build` was not run beforehand + * const handler = await app.handler(); * } catch (error) { * expect(error).toBeInstanceOf(SetupError); * expect(error.message).toBe("App not setup"); From 8ef669414888c172bb5b3c94cb7e6cf78cf0b0d8 Mon Sep 17 00:00:00 2001 From: Asher Gomez Date: Mon, 12 May 2025 18:38:27 +1000 Subject: [PATCH 4/7] work --- src/error.ts | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/error.ts b/src/error.ts index c574c69f3c4..e093c9b930d 100644 --- a/src/error.ts +++ b/src/error.ts @@ -96,15 +96,4 @@ export class HttpError extends Error { * } * ``` */ -export class SetupError extends Error { - /** - * Constructs a new instance. - * - * @param message The error message. - * @param options Optional error options. - */ - constructor(message: string, options?: ErrorOptions) { - super(message, options); - this.name = this.constructor.name; - } -} +export class SetupError extends Error {} From 36718bac9881ed6f69c4d30ab9b36d2e5c8ba98b Mon Sep 17 00:00:00 2001 From: Asher Gomez Date: Mon, 12 May 2025 19:11:37 +1000 Subject: [PATCH 5/7] fix --- src/app.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/app.ts b/src/app.ts index 8c853ed2bee..c0b19d2c6cb 100644 --- a/src/app.ts +++ b/src/app.ts @@ -256,10 +256,9 @@ export class App { !this.#buildCache.hasSnapshot && this.config.mode === "production" && DENO_DEPLOYMENT_ID !== undefined ) { - const message = DENO_DEPLOYMENT_ID - ? '`deno task build` must be run before starting the server. Go to "Settings" in Deno Deploy and set the build command to `deno task build`.' - : "`deno task build` must be run before starting the server."; - throw new SetupError(message); + throw new SetupError( + '`deno task build` must be run before starting the server. Go to "Settings" in Deno Deploy and set the build command to `deno task build`.', + ); } return async ( From 2c0ce4a19a31f3d85edbb3cb5fe1620d8bd8448b Mon Sep 17 00:00:00 2001 From: Asher Gomez Date: Mon, 12 May 2025 20:01:45 +1000 Subject: [PATCH 6/7] work --- src/app.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/app.ts b/src/app.ts index c0b19d2c6cb..0193e2684ee 100644 --- a/src/app.ts +++ b/src/app.ts @@ -252,13 +252,14 @@ export class App { ); } - if ( - !this.#buildCache.hasSnapshot && this.config.mode === "production" && - DENO_DEPLOYMENT_ID !== undefined - ) { - throw new SetupError( - '`deno task build` must be run before starting the server. Go to "Settings" in Deno Deploy and set the build command to `deno task build`.', - ); + if (!this.#buildCache.hasSnapshot && this.config.mode === "production") { + let message = + "The build cache is not set up. Run `deno task build` before starting the server."; + if (DENO_DEPLOYMENT_ID) { + message += + 'Go to "Settings" in Deno Deploy and set the build command to `deno task build`.'; + } + throw new SetupError(message); } return async ( From d68bcf038f9cc27cb9356124f34d52aa8ff7483e Mon Sep 17 00:00:00 2001 From: Asher Gomez Date: Tue, 13 May 2025 09:48:49 +1000 Subject: [PATCH 7/7] fix --- src/app.ts | 4 ++-- tests/fixture_precompile/valid/main.tsx | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/app.ts b/src/app.ts index 5ab38efd488..01b22a44811 100644 --- a/src/app.ts +++ b/src/app.ts @@ -255,9 +255,9 @@ export class App { if (!this.#buildCache.hasSnapshot && this.config.mode === "production") { let message = "The build cache is not set up. Run `deno task build` before starting the server."; - if (DENO_DEPLOYMENT_ID) { + if (DENO_DEPLOYMENT_ID !== undefined) { message += - 'Go to "Settings" in Deno Deploy and set the build command to `deno task build`.'; + ' Go to "Settings" in Deno Deploy and set the build command to `deno task build`.'; } throw new SetupError(message); } diff --git a/tests/fixture_precompile/valid/main.tsx b/tests/fixture_precompile/valid/main.tsx index 7beef0698fd..3e95d63c73f 100644 --- a/tests/fixture_precompile/valid/main.tsx +++ b/tests/fixture_precompile/valid/main.tsx @@ -1,4 +1,7 @@ import { App } from "../../../src/app.ts"; +import { Builder } from "../../../src/dev/mod.ts"; + +const builder = new Builder(); const app = new App({ staticDir: "./static" }).get( "/", @@ -25,6 +28,8 @@ const app = new App({ staticDir: "./static" }).get( ), ); +await builder.build(app); + const handler = app.handler(); const res = await handler(new Request("http://localhost/")); // deno-lint-ignore no-console