// Direct-upload deploy to Statichost (https://www.statichost.eu/docs/direct-upload/). // // Uploads the zip produced by the `zip` task (diffuse.zip) to // //drop — the same endpoint the official `shcli` // tool uses. The zip already contains the *contents* of the public directory // (not the directory itself), as the docs require. // // Usage: // deno task deploy:statichost // // Environment variables: // STATICHOST_APIKEY Required. API token from https://builder.statichost.eu/account // STATICHOST_SITE Optional. Site name, used when no argument is given. // STATICHOST_BUILDER Optional. Builder host, defaults to https://builder.statichost.eu import { load } from "@std/dotenv"; const dotenv = await load(); // `@std/dotenv`'s `load()` returns only the .env file values (no merge with // the process environment), so check both: the process env first (matching // the shcli docs' `export STATICHOST_APIKEY=...`), then the .env file (the // convention used elsewhere in this repo, eg. tasks/deploy/ipfs.ts). const env = { ...dotenv, STATICHOST_APIKEY: Deno.env.get("STATICHOST_APIKEY") ?? dotenv.STATICHOST_APIKEY, STATICHOST_SITE: Deno.env.get("STATICHOST_SITE") ?? dotenv.STATICHOST_SITE, STATICHOST_BUILDER: Deno.env.get("STATICHOST_BUILDER") ?? dotenv.STATICHOST_BUILDER, }; const apiKey = env.STATICHOST_APIKEY; if (!apiKey) { console.error("❌ STATICHOST_APIKEY is not set."); console.error( " Create an API token at https://builder.statichost.eu/account and set it as an env var.", ); Deno.exit(1); } const siteName = Deno.args[0] ?? env.STATICHOST_SITE; if (!siteName) { console.error("❌ No site name provided."); console.error(" Usage: deno task deploy:statichost "); Deno.exit(1); } const builderHost = (env.STATICHOST_BUILDER ?? "https://builder.statichost.eu") .replace(/\/+$/, ""); // Fail fast if the zip is missing — it's produced by the `zip` task, which // deploy:statichost runs before this script. try { const stat = Deno.statSync("diffuse.zip"); if (!stat.isFile) throw new Error("diffuse.zip is not a file"); } catch { console.error("❌ diffuse.zip does not exist. Create it first: deno task zip"); Deno.exit(1); } // Stream the zip to the upload endpoint, like shcli's // `curl --fail-with-body --data-binary @statichost.zip`. Consuming // `file.readable` as the body closes the file when the request completes. const file = Deno.openSync("diffuse.zip"); const response = await fetch(`${builderHost}/${siteName}/drop`, { method: "POST", headers: { "Authorization": `Bearer ${apiKey}`, "Content-Type": "application/zip", "Accept": "text/plain", }, body: file.readable, }); const body = await response.text(); if (!response.ok) { console.error(`❌ Upload failed: ${response.status} ${response.statusText}`); if (body) console.error(body); Deno.exit(1); } if (body) console.log(body); console.log(`✅️ Uploaded diffuse.zip to ${siteName}.statichost.eu`);