quality / changes (push) Successful in 9s
quality / commitlint (push) Skipped
quality / docker-check (push) Skipped
CD / update-wiki (push) Successful in 6s
quality / web (push) Successful in 1m4s
quality / api (push) Successful in 54s
CD / quality (push) Successful in 2m17s
CD / publish (push) Successful in 2m21s
Worker сам ходит на origin по Cron Trigger; CFDM кладёт цели в KV и забирает результаты без POST /probe. Co-authored-by: Cursor <[email protected]>
143 lines
4.4 KiB
TypeScript
143 lines
4.4 KiB
TypeScript
import {
|
|
CF_API_BASE,
|
|
handleCfResponse,
|
|
handleCfSuccess,
|
|
mapCloudflareFailure,
|
|
} from "./http.js";
|
|
|
|
export interface CfAccount {
|
|
id: string;
|
|
name?: string;
|
|
}
|
|
|
|
export interface CfWorkersSubdomain {
|
|
subdomain?: string;
|
|
enabled?: boolean;
|
|
}
|
|
|
|
export function createWorkersAdapter(token: string) {
|
|
return {
|
|
async listAccounts(): Promise<CfAccount[]> {
|
|
const response = await fetch(`${CF_API_BASE}/accounts?per_page=50`, {
|
|
headers: { Authorization: `Bearer ${token}` },
|
|
signal: AbortSignal.timeout(30_000),
|
|
});
|
|
if (response.status >= 500 || response.status === 429) {
|
|
throw mapCloudflareFailure("list_accounts", response.status, String(response.status));
|
|
}
|
|
return handleCfResponse<CfAccount[]>(response, "list_accounts");
|
|
},
|
|
|
|
async putScript(opts: {
|
|
accountId: string;
|
|
scriptName: string;
|
|
source: string;
|
|
kvNamespaceId: string;
|
|
filename?: string;
|
|
}): Promise<void> {
|
|
const filename = opts.filename ?? "index.mjs";
|
|
const metadata = {
|
|
main_module: filename,
|
|
compatibility_date: "2025-04-01",
|
|
bindings: [
|
|
{
|
|
type: "kv_namespace",
|
|
name: "HEALTH_KV",
|
|
namespace_id: opts.kvNamespaceId,
|
|
},
|
|
],
|
|
};
|
|
const form = new FormData();
|
|
form.append(
|
|
"metadata",
|
|
new Blob([JSON.stringify(metadata)], { type: "application/json" }),
|
|
);
|
|
form.append(
|
|
filename,
|
|
new Blob([opts.source], { type: "application/javascript+module" }),
|
|
filename,
|
|
);
|
|
const response = await fetch(
|
|
`${CF_API_BASE}/accounts/${opts.accountId}/workers/scripts/${opts.scriptName}`,
|
|
{
|
|
method: "PUT",
|
|
headers: { Authorization: `Bearer ${token}` },
|
|
body: form,
|
|
signal: AbortSignal.timeout(60_000),
|
|
},
|
|
);
|
|
if (response.status >= 500 || response.status === 429) {
|
|
throw mapCloudflareFailure("workers_put_script", response.status, String(response.status));
|
|
}
|
|
await handleCfSuccess(response, "workers_put_script");
|
|
},
|
|
|
|
async putSchedules(
|
|
accountId: string,
|
|
scriptName: string,
|
|
crons: string[],
|
|
): Promise<void> {
|
|
const response = await fetch(
|
|
`${CF_API_BASE}/accounts/${accountId}/workers/scripts/${scriptName}/schedules`,
|
|
{
|
|
method: "PUT",
|
|
headers: {
|
|
Authorization: `Bearer ${token}`,
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(crons.map((cron) => ({ cron }))),
|
|
signal: AbortSignal.timeout(30_000),
|
|
},
|
|
);
|
|
if (response.status >= 500 || response.status === 429) {
|
|
throw mapCloudflareFailure("workers_put_schedules", response.status, String(response.status));
|
|
}
|
|
await handleCfSuccess(response, "workers_put_schedules");
|
|
},
|
|
|
|
async enableWorkersDev(
|
|
accountId: string,
|
|
scriptName: string,
|
|
): Promise<void> {
|
|
const response = await fetch(
|
|
`${CF_API_BASE}/accounts/${accountId}/workers/scripts/${scriptName}/subdomain`,
|
|
{
|
|
method: "POST",
|
|
headers: {
|
|
Authorization: `Bearer ${token}`,
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({ enabled: true }),
|
|
signal: AbortSignal.timeout(30_000),
|
|
},
|
|
);
|
|
if (response.status === 409) return;
|
|
if (response.status >= 500 || response.status === 429) {
|
|
throw mapCloudflareFailure("workers_subdomain", response.status, String(response.status));
|
|
}
|
|
if (!response.ok && response.status !== 200 && response.status !== 201) {
|
|
await handleCfSuccess(response, "workers_subdomain");
|
|
}
|
|
},
|
|
|
|
async getWorkersSubdomain(accountId: string): Promise<string | null> {
|
|
const response = await fetch(
|
|
`${CF_API_BASE}/accounts/${accountId}/workers/subdomain`,
|
|
{
|
|
headers: { Authorization: `Bearer ${token}` },
|
|
signal: AbortSignal.timeout(30_000),
|
|
},
|
|
);
|
|
if (response.status === 404) return null;
|
|
if (response.status >= 500 || response.status === 429) {
|
|
throw mapCloudflareFailure("workers_get_subdomain", response.status, String(response.status));
|
|
}
|
|
const result = await handleCfResponse<CfWorkersSubdomain>(
|
|
response,
|
|
"workers_get_subdomain",
|
|
);
|
|
return result.subdomain?.trim() || null;
|
|
},
|
|
};
|
|
}
|