From 2670a7ff4e704b4d47832a4f2dc95d09669adb5e Mon Sep 17 00:00:00 2001 From: Thanukamax Date: Mon, 6 Jul 2026 20:38:35 +0530 Subject: [PATCH] refactor(cloudflare): extract list + createAndResolve helpers De-duplicate the resource provisioning logic in cloudflare.ts: - Replace six copies of the verbose `(await wranglerJson([...], { allowFail: true })) ?? []` list expression with named `listD1()` / `listKv()` helpers. - Fold the repeated "create -> re-list -> resolve -> throw if missing" idempotent-create dance (duplicated across ensureD1 and ensureKv) into a single generic `createAndResolve` helper. Behavior is unchanged: same wrangler calls, same reuse-vs-create paths, same single batched KV list per run. Purely a readability/DRY refactor. typecheck, tests, lint, and build all pass. --- dist/index.cjs | 47 ++++++++++++++++---------------- src/cloudflare.ts | 69 ++++++++++++++++++++++++++++++----------------- 2 files changed, 69 insertions(+), 47 deletions(-) diff --git a/dist/index.cjs b/dist/index.cjs index 96691a2..9461858 100644 --- a/dist/index.cjs +++ b/dist/index.cjs @@ -22996,39 +22996,40 @@ async function resolveSubdomain(accountId, token) { throw new Error("account has no workers.dev subdomain configured"); return sub; } +var listD1 = () => wranglerJson(["d1", "list", "--json"], { allowFail: true }).then((l) => l ?? []); +var listKv = () => wranglerJson(["kv", "namespace", "list"], { allowFail: true }).then((l) => l ?? []); +async function createAndResolve(label, create, list, match) { + core2.info(`creating ${label}`); + await create(); + const hit = (await list()).find(match); + if (!hit) + throw new Error(`failed to resolve ${label} after create`); + return hit; +} async function ensureD1(dbName, location) { - const list = await wranglerJson(["d1", "list", "--json"], { allowFail: true }) ?? []; - let found = list.find((d) => d.name === dbName); - if (!found) { - core2.info(`creating preview D1 ${dbName}`); - await wrangler(["d1", "create", dbName, "--location", location]); - const relist = await wranglerJson(["d1", "list", "--json"], { allowFail: true }) ?? []; - found = relist.find((d) => d.name === dbName); - } else { + const match = (d) => d.name === dbName; + const found = (await listD1()).find(match); + if (found) { core2.info(`reusing preview D1 ${dbName} (${found.uuid})`); + return found.uuid; } - if (!found) - throw new Error(`failed to resolve preview D1 id for ${dbName}`); - return found.uuid; + const created = await createAndResolve(`preview D1 ${dbName}`, () => wrangler(["d1", "create", dbName, "--location", location]), listD1, match); + return created.uuid; } async function ensureKv(sourceKv, workerName) { if (!Array.isArray(sourceKv)) return []; const out = []; - const existing = await wranglerJson(["kv", "namespace", "list"], { allowFail: true }) ?? []; + const existing = await listKv(); for (const ns of sourceKv) { const title = bindingResourceName(workerName, ns.binding); - let hit = existing.find((e) => e.title === title); - if (!hit) { - core2.info(`creating preview KV namespace ${title}`); - await wrangler(["kv", "namespace", "create", title]); - const relist = await wranglerJson(["kv", "namespace", "list"], { allowFail: true }) ?? []; - hit = relist.find((e) => e.title === title); - } else { + const match = (e) => e.title === title; + let hit = existing.find(match); + if (hit) { core2.info(`reusing preview KV namespace ${title} (${hit.id})`); + } else { + hit = await createAndResolve(`preview KV namespace ${title}`, () => wrangler(["kv", "namespace", "create", title]), listKv, match); } - if (!hit) - throw new Error(`failed to resolve preview KV id for ${title}`); out.push({ binding: ns.binding, id: hit.id }); } return out; @@ -23050,7 +23051,7 @@ async function deleteWorker(name) { await wrangler(["delete", "--name", name, "--force"], { allowFail: true }); } async function deleteD1(dbName) { - const dbs = await wranglerJson(["d1", "list", "--json"], { allowFail: true }) ?? []; + const dbs = await listD1(); if (dbs.find((d) => d.name === dbName)) { core2.info(`deleting preview D1 ${dbName}`); await wrangler(["d1", "delete", dbName, "-y"], { allowFail: true }); @@ -23061,7 +23062,7 @@ async function deleteD1(dbName) { async function deleteKv(sourceKv, workerName) { if (!Array.isArray(sourceKv)) return; - const existing = await wranglerJson(["kv", "namespace", "list"], { allowFail: true }) ?? []; + const existing = await listKv(); for (const ns of sourceKv) { const title = bindingResourceName(workerName, ns.binding); const hit = existing.find((e) => e.title === title); diff --git a/src/cloudflare.ts b/src/cloudflare.ts index 7d17d90..8daab1c 100644 --- a/src/cloudflare.ts +++ b/src/cloudflare.ts @@ -14,39 +14,61 @@ export async function resolveSubdomain(accountId: string, token: string): Promis return sub } +// wrangler list commands tolerate failure and may print nothing; normalize to []. +const listD1 = () => + wranglerJson(['d1', 'list', '--json'], { allowFail: true }).then((l) => l ?? []) +const listKv = () => + wranglerJson(['kv', 'namespace', 'list'], { allowFail: true }).then((l) => l ?? []) + +// Create a resource, then re-list to resolve the freshly created entry. +// Throws if it still can't be found (create silently no-op'd or the list failed). +async function createAndResolve( + label: string, + create: () => Promise, + list: () => Promise, + match: (item: T) => boolean, +): Promise { + core.info(`creating ${label}`) + await create() + const hit = (await list()).find(match) + if (!hit) throw new Error(`failed to resolve ${label} after create`) + return hit +} + export async function ensureD1(dbName: string, location: string): Promise { - const list = (await wranglerJson(['d1', 'list', '--json'], { allowFail: true })) ?? [] - let found = list.find((d) => d.name === dbName) - if (!found) { - core.info(`creating preview D1 ${dbName}`) - await wrangler(['d1', 'create', dbName, '--location', location]) - const relist = (await wranglerJson(['d1', 'list', '--json'], { allowFail: true })) ?? [] - found = relist.find((d) => d.name === dbName) - } else { + const match = (d: any) => d.name === dbName + const found = (await listD1()).find(match) + if (found) { core.info(`reusing preview D1 ${dbName} (${found.uuid})`) + return found.uuid } - if (!found) throw new Error(`failed to resolve preview D1 id for ${dbName}`) - return found.uuid + const created = await createAndResolve( + `preview D1 ${dbName}`, + () => wrangler(['d1', 'create', dbName, '--location', location]), + listD1, + match, + ) + return created.uuid } export async function ensureKv(sourceKv: any, workerName: string): Promise { if (!Array.isArray(sourceKv)) return [] const out: KvBinding[] = [] - const existing = - (await wranglerJson(['kv', 'namespace', 'list'], { allowFail: true })) ?? [] + const existing = await listKv() for (const ns of sourceKv) { const title = bindingResourceName(workerName, ns.binding) - let hit = existing.find((e) => e.title === title) - if (!hit) { - core.info(`creating preview KV namespace ${title}`) - await wrangler(['kv', 'namespace', 'create', title]) - const relist = - (await wranglerJson(['kv', 'namespace', 'list'], { allowFail: true })) ?? [] - hit = relist.find((e) => e.title === title) - } else { + const match = (e: any) => e.title === title + let hit = existing.find(match) + if (hit) { core.info(`reusing preview KV namespace ${title} (${hit.id})`) + } else { + hit = await createAndResolve( + `preview KV namespace ${title}`, + () => wrangler(['kv', 'namespace', 'create', title]), + listKv, + match, + ) } - if (!hit) throw new Error(`failed to resolve preview KV id for ${title}`) out.push({ binding: ns.binding, id: hit.id }) } return out @@ -70,7 +92,7 @@ export async function deleteWorker(name: string): Promise { } export async function deleteD1(dbName: string): Promise { - const dbs = (await wranglerJson(['d1', 'list', '--json'], { allowFail: true })) ?? [] + const dbs = await listD1() if (dbs.find((d) => d.name === dbName)) { core.info(`deleting preview D1 ${dbName}`) await wrangler(['d1', 'delete', dbName, '-y'], { allowFail: true }) @@ -81,8 +103,7 @@ export async function deleteD1(dbName: string): Promise { export async function deleteKv(sourceKv: any, workerName: string): Promise { if (!Array.isArray(sourceKv)) return - const existing = - (await wranglerJson(['kv', 'namespace', 'list'], { allowFail: true })) ?? [] + const existing = await listKv() for (const ns of sourceKv) { const title = bindingResourceName(workerName, ns.binding) const hit = existing.find((e) => e.title === title)