Skip to content

Commit

Permalink
Merge pull request #6 from bertybot/add-config-options
Browse files Browse the repository at this point in the history
Add Config Validation and options
  • Loading branch information
bertybot authored Sep 19, 2024
2 parents 07aee6e + a6b45c4 commit 82c997e
Show file tree
Hide file tree
Showing 5 changed files with 2,517 additions and 1,218 deletions.
7 changes: 7 additions & 0 deletions .changeset/ninety-knives-appear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"svelte-adapter-fastly": patch
---

- Added Configuration validation for fastly.toml files.
- Added prompts to more easily create your own fastly.toml files.
- Added `staticPublishConfig` option so you can supply your own `static-publish.rc.js` file
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,13 @@ const config = {
- Make sure it has a script to run pnpm build.

3. You can test your project via the fastly CLI using `fastly compute serve`

## Options

### silent

By default if a fastly.toml file is not included this adapter will help you make one. You can avoid this option in CI/CD enviroments by passing `silent: true`

### staticPublishConfig

Due to its nature as an edgeworker Fastly needs to compile static assets to be served by the edgeworker. This adapter uses [`compute-js-static-publish`](https://github.com/fastly/compute-js-static-publish) to handle this, and uses a default config that should work well for most use cases. However, if you would like to customize this using a `static-publish.rc.js` you can supply the path to it here. This would be useful if you want to store your assets in a KV store instead of binary.
8 changes: 8 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ export default function plugin(options?: AdapterOptions): Adapter;

export interface AdapterOptions {
out?: string;
staticPublishConfig?: string;
silent?: boolean;
}

export type FastlyConfig = {
manifest_version: number;
name: string;
language: "javascript";
};

export { Geolocation };
150 changes: 139 additions & 11 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import { writeFileSync } from "node:fs";
import { posix } from "node:path";
import { existsSync, readFileSync, writeFileSync } from "node:fs";
import { posix, resolve } from "node:path";
import { execSync } from "node:child_process";
import esbuild from "esbuild";
import toml from "@iarna/toml";
import readline from "node:readline/promises";
import { fileURLToPath } from "node:url";

/** @type {import('./index.js').default} */
export default function (opts = {}) {
const { out = "bin" } = opts;
const { out = "bin", silent = false } = opts;
return {
name: "sveltekit-adapter-fastly",
async adapt(builder) {
//validate fastly config
await validate_config(builder, silent);

//Removing tmp directory if exists
const files = fileURLToPath(new URL("./files", import.meta.url).href);
const tmp = builder.getBuildDirectory("fastly-tmp");
Expand All @@ -21,13 +26,21 @@ export default function (opts = {}) {
builder.writeClient(static_dir);
builder.writePrerendered(static_dir);

// leverage @fastly/compute-js-static-publish to out put static files where i need them

builder.copy(
`${files}/static-publish.rc.js`,
`${tmp}/static-publish.rc.js`,
{}
);
if (opts.staticPublishConfig) {
await validate_static_publish_config(builder, opts.staticPublishConfig);
builder.copy(
opts.staticPublishConfig,
`${tmp}/static-publish.rc.js`,
{}
);
} else {
//sticking with default
builder.copy(
`${files}/static-publish.rc.js`,
`${tmp}/static-publish.rc.js`,
{}
);
}

execSync(`npx @fastly/compute-js-static-publish --build-static`, {
cwd: `${tmp}`,
Expand Down Expand Up @@ -72,7 +85,7 @@ export default function (opts = {}) {

const external = ["fastly:*"];

console.log("Building worker...");
builder.log("Building worker...");
try {
const result = await esbuild.build({
platform: "browser",
Expand Down Expand Up @@ -113,6 +126,10 @@ export default function (opts = {}) {
});

console.error(formatted.join("\n"));
} else {
builder.log(
"Fastly Worker built successfully run fastly compute serve to test locally"
);
}
} catch (error) {
for (const e of error.errors) {
Expand Down Expand Up @@ -176,3 +193,114 @@ export default function (opts = {}) {
},
};
}

/**
* @param {import('@sveltejs/kit').Builder} builder
* @param {string} file
*/
async function validate_static_publish_config(builder, file) {
if (!existsSync(file)) {
builder.log(
"No static-publish.rc.js file found. Using default configuration."
);
return;
}

const path = resolve(file);
const publishConfig = await import(path).then((m) => m.default);

if (publishConfig.rootDir !== "./static") {
builder.log.warn(
"RootDir is not ./static. This may cause issues with the adapter"
);
}

return true;
}

/**
* @param {import('@sveltejs/kit').Builder} builder
* @param {boolean} silent
* @returns {Promise<import('./index.js').FastlyConfig>}
*/
async function validate_config(builder, silent) {
if (existsSync("fastly.toml")) {
/** @type {import('./index.js').FastlyConfig} */
let fastly_config;

try {
fastly_config = /** @type {import('./index.js').FastlyConfig} */ (
toml.parse(readFileSync("fastly.toml", "utf-8"))
);
} catch (err) {
err.message = `Error parsing fastly.toml: ${err.message}`;
throw err;
}

if (fastly_config.language !== "javascript") {
throw new Error(
'You must specify `language = "javascript"` in fastly.toml.'
);
}

return fastly_config;
}

if (silent) {
throw new Error("Missing a fastly.toml file");
}

const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});

const res = await rl.question("No fastly.toml file. Create one? (y/n): ");

if (res.toLowerCase() === "y") {
const name = await rl.question("Please enter name of project: ");
const service_id = await rl.question(
"Please enter service id of compute service: "
);
const author = await rl.question("Please enter author name: ");
rl.close();
writeFileSync(
"fastly.toml",
`manifest_version = 3
service_id = "${service_id}"
name = "${name}"
description = "A SvelteKit project deployed on Fastly Compute@Edge"
authors = ["${author}"]
language = "javascript"
[scripts]
build = "npm run build"`,
{
encoding: "utf-8",
}
);

return {
manifest_version: 3,
name,
language: "javascript",
};
}

builder.log(
`
Sample fastly.toml:
manifest_version = 3
service_id = "<your-service-id>"
name = "<your-site-name>"
description = "A SvelteKit project deployed on Fastly Compute@Edge"
authors = ["<your-name>"]
language = "javascript"`
.replace(/^\t+/gm, "")
.trim()
);
throw new Error(
"Missing a fastly.toml file. please create one and try again"
);
}
Loading

0 comments on commit 82c997e

Please sign in to comment.