Skip to content

Commit

Permalink
Add worker and secret management to setup scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
sergiodxa committed Dec 19, 2024
1 parent 4a59a59 commit 35165ac
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 3 deletions.
8 changes: 8 additions & 0 deletions scripts/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { Database } from "./setup/d1-database";
import { KVNamespace } from "./setup/kv-namespace";
import { Queue } from "./setup/queue";
import { R2Bucket } from "./setup/r2-bucket";
import { Secret } from "./setup/secret";
import { Worker } from "./setup/worker";

config({ path: "./.dev.vars" });

Expand Down Expand Up @@ -59,6 +61,12 @@ try {
"Do you have a Verifier API key? (press enter to continue) ",
);

// We need to create a worker if it doesn't exist to associate the secrets
let worker = await Worker.upsert(cf, account, projectName);

await Secret.create(cf, account, worker, "GRAVATAR_API_KEY", gravatar);
await Secret.create(cf, account, worker, "VERIFIER_API_KEY", verifier);

consola.info("Creating .dev.vars file with the app environment variables.");

await write(
Expand Down
2 changes: 1 addition & 1 deletion scripts/setup/kv-namespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class KVNamespace extends Data<ObjectParser> {
}

static async create(cf: Cloudflare, account: Account, title: string) {
consola.info("Creating KV namespace...");
consola.info(`Creating KV namespace ${title}.`);

let result = await cf.kv.namespaces.create({
account_id: account.id,
Expand Down
2 changes: 1 addition & 1 deletion scripts/setup/queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class Queue extends Data<ObjectParser> {
}

static async create(cf: Cloudflare, account: Account, name: string) {
consola.info("Creating queue...");
consola.info(`Creating queue ${name}.`);

let result = await cf.queues.create({
account_id: account.id,
Expand Down
2 changes: 1 addition & 1 deletion scripts/setup/r2-bucket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export class R2Bucket extends Data<ObjectParser> {
}

static async create(cf: Cloudflare, account: Account, name: string) {
consola.info("Creating queue...");
consola.info(`Creating R2 bucket ${name}.`);

let result = await cf.r2.buckets.create({ account_id: account.id, name });

Expand Down
50 changes: 50 additions & 0 deletions scripts/setup/secret.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Data } from "@edgefirst-dev/data";
import { ObjectParser } from "@edgefirst-dev/data/parser";
import type Cloudflare from "cloudflare";
import consola from "consola";
import { generatePath } from "react-router";
import type { Account } from "./account";
import { Worker } from "./worker";

export class Secret extends Data<ObjectParser> {
get name() {
return this.parser.string("name");
}

get type() {
return this.parser.string("type");
}

static async create(
cf: Cloudflare,
account: Account,
worker: Worker,
name: string,
text: string,
) {
consola.info(`Creating secret ${name}.`);

let path = generatePath(
"/client/v4/accounts/:accountId/workers/scripts/:name/secrets",
{ accountId: account.id, name: worker.name },
);

let response = await fetch(new URL(path, "https://api.cloudflare.com"), {
method: "PUT",
body: JSON.stringify({ name, text, type: "secret_text" }),
headers: {
Authorization: `Bearer ${cf.apiToken}`,
"Content-Type": "application/json",
},
});

if (!response.ok) throw new Error(`Failed to create secret ${name}.`);

let result = await response.json();
let parser = new ObjectParser(result);

consola.success(`Created secret ${name}.`);

return new Secret(parser.object("result"));
}
}
81 changes: 81 additions & 0 deletions scripts/setup/worker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { Data } from "@edgefirst-dev/data";
import { ObjectParser } from "@edgefirst-dev/data/parser";
import type { Cloudflare } from "cloudflare";
import consola from "consola";
import { generatePath, resolvePath } from "react-router";
import type { Account } from "./account";

export class Worker extends Data<ObjectParser> {
get name() {
return this.parser.string("id");
}

static async create(cf: Cloudflare, account: Account, name: string) {
consola.info(`Creating worker ${name}.`);

let formData = new FormData();
formData.set("account_id", account.id);
formData.set("metadata", JSON.stringify({ main_module: "worker.ts" }));
formData.set(
"worker.ts",
new File(["export default { fetch() {} }"], "worker.ts", {
type: "application/javascript+module",
}),
);

let path = generatePath(
"/client/v4/accounts/:accountId/workers/services/:name/environments/staging",
{ accountId: account.id, name },
);

let response = await fetch(new URL(path, "https://api.cloudflare.com"), {
method: "PUT",
body: formData,
headers: { Authorization: `Bearer ${cf.apiToken}` },
});

let result = await response.json();

let parser = new ObjectParser(result);

let worker = new Worker(parser.object("result"));

consola.success(`Created worker ${worker.name}.`);

return worker;
}

static async find(cf: Cloudflare, account: Account, name: string) {
consola.info(`Looking up for Worker named ${name}...`);

let { result } = await cf.workers.scripts.list({
account_id: account.id,
});

let workers = result
.map((item) => new Worker(new ObjectParser(item)))
.filter((worker) => worker.name === name);

if (workers.length === 0) {
consola.info(`No workers found named ${name}.`);
return null;
}

if (workers.length > 1) {
throw new Error(`Found more than one worker named ${name}.`);
}

return workers.at(0) ?? null;
}

static async upsert(cf: Cloudflare, account: Account, projectName: string) {
let worker = await Worker.find(cf, account, projectName);

if (worker) {
consola.success(`Using found worker ${projectName}.`);
return worker;
}

return await Worker.create(cf, account, projectName);
}
}

0 comments on commit 35165ac

Please sign in to comment.