@theholocron/cloudflare-client 1.32.0 → 1.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +184 -0
- package/dist/index.mjs +148 -0
- package/package.json +3 -3
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import "@theholocron/http-client";
|
|
2
|
+
import { ErrorSink, Logger } from "@theholocron/observability/core";
|
|
3
|
+
//#region ../../../../../src/utils.d.ts
|
|
4
|
+
interface CloudflareClientOptions {
|
|
5
|
+
token: string;
|
|
6
|
+
/** Override base URL for testing. Defaults to https://api.cloudflare.com/client/v4 */
|
|
7
|
+
baseUrl?: string;
|
|
8
|
+
/** Override fetch for testing. Defaults to globalThis.fetch. */
|
|
9
|
+
fetch?: typeof fetch;
|
|
10
|
+
/** Structured logger for request/response diagnostics. Defaults to a no-op. */
|
|
11
|
+
logger?: Logger;
|
|
12
|
+
/** Reports transport failures and unexpected 5xx. Defaults to a no-op. */
|
|
13
|
+
errors?: ErrorSink;
|
|
14
|
+
}
|
|
15
|
+
interface CfEnvelope<T> {
|
|
16
|
+
success: boolean;
|
|
17
|
+
errors: unknown[];
|
|
18
|
+
result: T;
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region ../../../../../src/dns/dns.d.ts
|
|
22
|
+
type CfDnsRecordType = "A" | "AAAA" | "CNAME" | "TXT" | "MX" | "NS" | "SRV" | "CAA";
|
|
23
|
+
interface CfDnsRecord {
|
|
24
|
+
id: string;
|
|
25
|
+
type: CfDnsRecordType;
|
|
26
|
+
name: string;
|
|
27
|
+
content: string;
|
|
28
|
+
ttl: number;
|
|
29
|
+
proxied: boolean;
|
|
30
|
+
}
|
|
31
|
+
interface CfDnsRecordInput {
|
|
32
|
+
type: CfDnsRecordType;
|
|
33
|
+
name: string;
|
|
34
|
+
content: string;
|
|
35
|
+
ttl?: number;
|
|
36
|
+
proxied?: boolean;
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region ../../../../../src/pages/pages.d.ts
|
|
40
|
+
type CfPagesEnvVarType = "plain_text" | "secret_text";
|
|
41
|
+
interface CfPagesEnvVar {
|
|
42
|
+
value: string;
|
|
43
|
+
type: CfPagesEnvVarType;
|
|
44
|
+
}
|
|
45
|
+
interface CfPagesEnvConfig {
|
|
46
|
+
env_vars: Record<string, CfPagesEnvVar>;
|
|
47
|
+
}
|
|
48
|
+
interface CfPagesProject {
|
|
49
|
+
id: string;
|
|
50
|
+
name: string;
|
|
51
|
+
subdomain: string;
|
|
52
|
+
domains: string[];
|
|
53
|
+
production_branch: string;
|
|
54
|
+
deployment_configs: {
|
|
55
|
+
preview: CfPagesEnvConfig;
|
|
56
|
+
production: CfPagesEnvConfig;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
interface CfPagesProjectInput {
|
|
60
|
+
name: string;
|
|
61
|
+
production_branch: string;
|
|
62
|
+
}
|
|
63
|
+
interface CfPagesDeploymentStage {
|
|
64
|
+
name: string;
|
|
65
|
+
status: "idle" | "active" | "canceled" | "success" | "failure";
|
|
66
|
+
}
|
|
67
|
+
interface CfPagesDomain {
|
|
68
|
+
id: string;
|
|
69
|
+
name: string;
|
|
70
|
+
status: "active" | "pending" | "blocked" | "error" | "moved" | "pending_tls";
|
|
71
|
+
}
|
|
72
|
+
interface CfPagesDeployment {
|
|
73
|
+
id: string;
|
|
74
|
+
url: string;
|
|
75
|
+
environment: "preview" | "production";
|
|
76
|
+
deployment_trigger: {
|
|
77
|
+
type: string;
|
|
78
|
+
metadata: {
|
|
79
|
+
branch: string;
|
|
80
|
+
commit_hash: string;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
latest_stage: CfPagesDeploymentStage;
|
|
84
|
+
created_on: string;
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region ../../../../../src/zones/zones.d.ts
|
|
88
|
+
interface CfZone {
|
|
89
|
+
id: string;
|
|
90
|
+
name: string;
|
|
91
|
+
status: string;
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region ../../../../../src/tunnels/tunnels.d.ts
|
|
95
|
+
interface CfTunnel {
|
|
96
|
+
id: string;
|
|
97
|
+
name: string;
|
|
98
|
+
}
|
|
99
|
+
interface CfIngressRule {
|
|
100
|
+
hostname?: string;
|
|
101
|
+
service: string;
|
|
102
|
+
path?: string;
|
|
103
|
+
}
|
|
104
|
+
interface CfTunnelConfig {
|
|
105
|
+
ingress: CfIngressRule[];
|
|
106
|
+
}
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region ../../../../../src/tokens/tokens.d.ts
|
|
109
|
+
interface CfTokenVerification {
|
|
110
|
+
id: string;
|
|
111
|
+
status: "active" | "disabled" | "expired";
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region ../../../../../src/workers/workers.d.ts
|
|
115
|
+
interface CfWorkerRoute {
|
|
116
|
+
id: string;
|
|
117
|
+
pattern: string;
|
|
118
|
+
script: string | null;
|
|
119
|
+
}
|
|
120
|
+
/** https://developers.cloudflare.com/api/operations/worker-script-put-encrypted-secret-binding */
|
|
121
|
+
interface CfWorkerSecret {
|
|
122
|
+
name: string;
|
|
123
|
+
type: "secret_text";
|
|
124
|
+
}
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region ../../../../../src/index.d.ts
|
|
127
|
+
declare function createCloudflareClient(opts: CloudflareClientOptions): {
|
|
128
|
+
dns: {
|
|
129
|
+
list: (zoneId: string, query?: {
|
|
130
|
+
type?: string;
|
|
131
|
+
name?: string;
|
|
132
|
+
}) => Promise<CfDnsRecord[]>;
|
|
133
|
+
create: (zoneId: string, record: CfDnsRecordInput) => Promise<CfDnsRecord>;
|
|
134
|
+
update: (zoneId: string, recordId: string, record: Partial<CfDnsRecordInput>) => Promise<CfDnsRecord>;
|
|
135
|
+
delete: (zoneId: string, recordId: string) => Promise<{
|
|
136
|
+
id: string;
|
|
137
|
+
}>;
|
|
138
|
+
};
|
|
139
|
+
pages: {
|
|
140
|
+
listProjects: (accountId: string) => Promise<CfPagesProject[]>;
|
|
141
|
+
getProject: (accountId: string, name: string) => Promise<CfPagesProject>;
|
|
142
|
+
createProject: (accountId: string, input: CfPagesProjectInput) => Promise<CfPagesProject>;
|
|
143
|
+
updateProject: (accountId: string, name: string, patch: Partial<Pick<CfPagesProject, "deployment_configs" | "production_branch">>) => Promise<CfPagesProject>;
|
|
144
|
+
createDeployment: (accountId: string, projectName: string, branch: string) => Promise<CfPagesDeployment>;
|
|
145
|
+
getDeployment: (accountId: string, projectName: string, deploymentId: string) => Promise<CfPagesDeployment>;
|
|
146
|
+
listDeployments: (accountId: string, projectName: string) => Promise<CfPagesDeployment[]>;
|
|
147
|
+
deleteDeployment: (accountId: string, projectName: string, deploymentId: string) => Promise<void>;
|
|
148
|
+
listDomains: (accountId: string, projectName: string) => Promise<CfPagesDomain[]>;
|
|
149
|
+
addDomain: (accountId: string, projectName: string, hostname: string) => Promise<CfPagesDomain>;
|
|
150
|
+
};
|
|
151
|
+
zones: {
|
|
152
|
+
list: (query?: {
|
|
153
|
+
name?: string;
|
|
154
|
+
per_page?: number;
|
|
155
|
+
}) => Promise<CfZone[]>;
|
|
156
|
+
};
|
|
157
|
+
tunnels: {
|
|
158
|
+
create: (accountId: string, input: {
|
|
159
|
+
name: string;
|
|
160
|
+
}) => Promise<CfTunnel>;
|
|
161
|
+
list: (accountId: string) => Promise<CfTunnel[]>;
|
|
162
|
+
token: (accountId: string, tunnelId: string) => Promise<string>;
|
|
163
|
+
delete: (accountId: string, tunnelId: string) => Promise<void>;
|
|
164
|
+
getConfig: (accountId: string, tunnelId: string) => Promise<{
|
|
165
|
+
config: CfTunnelConfig;
|
|
166
|
+
}>;
|
|
167
|
+
putConfig: (accountId: string, tunnelId: string, config: CfTunnelConfig) => Promise<void>;
|
|
168
|
+
};
|
|
169
|
+
tokens: {
|
|
170
|
+
verify: () => Promise<CfTokenVerification>;
|
|
171
|
+
};
|
|
172
|
+
workers: {
|
|
173
|
+
putScript: (accountId: string, scriptName: string, script: string) => Promise<void>;
|
|
174
|
+
listRoutes: (zoneId: string) => Promise<CfWorkerRoute[]>;
|
|
175
|
+
createRoute: (zoneId: string, pattern: string, script: string) => Promise<CfWorkerRoute>;
|
|
176
|
+
updateRoute: (zoneId: string, routeId: string, pattern: string, script: string) => Promise<CfWorkerRoute>;
|
|
177
|
+
putSecret: (accountId: string, scriptName: string, name: string, value: string) => Promise<CfWorkerSecret>;
|
|
178
|
+
listSecrets: (accountId: string, scriptName: string) => Promise<CfWorkerSecret[]>;
|
|
179
|
+
deleteSecret: (accountId: string, scriptName: string, name: string) => Promise<void>;
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
type CloudflareClient = ReturnType<typeof createCloudflareClient>;
|
|
183
|
+
//#endregion
|
|
184
|
+
export { type CfDnsRecord, type CfDnsRecordInput, type CfDnsRecordType, type CfEnvelope, type CfIngressRule, type CfPagesDeployment, type CfPagesDeploymentStage, type CfPagesDomain, type CfPagesEnvConfig, type CfPagesEnvVar, type CfPagesEnvVarType, type CfPagesProject, type CfPagesProjectInput, type CfTokenVerification, type CfTunnel, type CfTunnelConfig, type CfWorkerRoute, type CfWorkerSecret, type CfZone, CloudflareClient, type CloudflareClientOptions, createCloudflareClient };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { ProviderApiError, createRestClient } from "@theholocron/http-client";
|
|
2
|
+
//#region ../../../../../src/utils.ts
|
|
3
|
+
function createCloudflareRestClient(opts) {
|
|
4
|
+
return createRestClient({
|
|
5
|
+
baseUrl: opts.baseUrl ?? "https://api.cloudflare.com/client/v4",
|
|
6
|
+
token: opts.token,
|
|
7
|
+
vendor: "Cloudflare",
|
|
8
|
+
fetch: opts.fetch,
|
|
9
|
+
logger: opts.logger,
|
|
10
|
+
errors: opts.errors
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Unwrap Cloudflare's `{ result, success, errors }` envelope.
|
|
15
|
+
* `createRestClient` already throws on HTTP 4xx/5xx; this handles the rare
|
|
16
|
+
* 200 + `success: false` case Cloudflare emits for some validation failures.
|
|
17
|
+
*/
|
|
18
|
+
async function cfRequest(rest, method, path, body, query) {
|
|
19
|
+
const envelope = await rest.request(path, {
|
|
20
|
+
method,
|
|
21
|
+
...body !== void 0 ? { body } : {},
|
|
22
|
+
...query !== void 0 ? { query } : {}
|
|
23
|
+
});
|
|
24
|
+
if (!envelope) return void 0;
|
|
25
|
+
if (!envelope.success) throw new ProviderApiError(`Cloudflare ${method} ${path} returned success:false`, 0, JSON.stringify(envelope.errors));
|
|
26
|
+
return envelope.result;
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region ../../../../../src/dns/dns.ts
|
|
30
|
+
function dns(rest) {
|
|
31
|
+
return {
|
|
32
|
+
list: (zoneId, query) => cfRequest(rest, "GET", `/zones/${zoneId}/dns_records`, void 0, {
|
|
33
|
+
...query?.type ? { type: query.type } : {},
|
|
34
|
+
...query?.name ? { name: query.name } : {},
|
|
35
|
+
per_page: "100"
|
|
36
|
+
}),
|
|
37
|
+
create: (zoneId, record) => cfRequest(rest, "POST", `/zones/${zoneId}/dns_records`, {
|
|
38
|
+
type: record.type,
|
|
39
|
+
name: record.name,
|
|
40
|
+
content: record.content,
|
|
41
|
+
ttl: record.ttl ?? 1,
|
|
42
|
+
proxied: record.proxied ?? false
|
|
43
|
+
}),
|
|
44
|
+
update: (zoneId, recordId, record) => cfRequest(rest, "PATCH", `/zones/${zoneId}/dns_records/${recordId}`, record),
|
|
45
|
+
delete: (zoneId, recordId) => cfRequest(rest, "DELETE", `/zones/${zoneId}/dns_records/${recordId}`)
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region ../../../../../src/pages/pages.ts
|
|
50
|
+
function pages(rest) {
|
|
51
|
+
return {
|
|
52
|
+
listProjects: (accountId) => cfRequest(rest, "GET", `/accounts/${accountId}/pages/projects`, void 0, { per_page: "100" }),
|
|
53
|
+
getProject: (accountId, name) => cfRequest(rest, "GET", `/accounts/${accountId}/pages/projects/${name}`),
|
|
54
|
+
createProject: (accountId, input) => cfRequest(rest, "POST", `/accounts/${accountId}/pages/projects`, input),
|
|
55
|
+
updateProject: (accountId, name, patch) => cfRequest(rest, "PATCH", `/accounts/${accountId}/pages/projects/${name}`, patch),
|
|
56
|
+
createDeployment: (accountId, projectName, branch) => cfRequest(rest, "POST", `/accounts/${accountId}/pages/projects/${projectName}/deployments`, { branch }),
|
|
57
|
+
getDeployment: (accountId, projectName, deploymentId) => cfRequest(rest, "GET", `/accounts/${accountId}/pages/projects/${projectName}/deployments/${deploymentId}`),
|
|
58
|
+
listDeployments: (accountId, projectName) => cfRequest(rest, "GET", `/accounts/${accountId}/pages/projects/${projectName}/deployments`, void 0, { per_page: "25" }),
|
|
59
|
+
deleteDeployment: (accountId, projectName, deploymentId) => cfRequest(rest, "DELETE", `/accounts/${accountId}/pages/projects/${projectName}/deployments/${deploymentId}`, void 0, { force: "true" }),
|
|
60
|
+
listDomains: (accountId, projectName) => cfRequest(rest, "GET", `/accounts/${accountId}/pages/projects/${projectName}/domains`),
|
|
61
|
+
addDomain: (accountId, projectName, hostname) => cfRequest(rest, "POST", `/accounts/${accountId}/pages/projects/${projectName}/domains`, { name: hostname })
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region ../../../../../src/tokens/tokens.ts
|
|
66
|
+
function tokens(rest) {
|
|
67
|
+
return { verify: () => cfRequest(rest, "GET", "/user/tokens/verify") };
|
|
68
|
+
}
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region ../../../../../src/tunnels/tunnels.ts
|
|
71
|
+
function tunnels(rest) {
|
|
72
|
+
return {
|
|
73
|
+
create: (accountId, input) => cfRequest(rest, "POST", `/accounts/${accountId}/cfd_tunnel`, {
|
|
74
|
+
name: input.name,
|
|
75
|
+
config_src: "cloudflare"
|
|
76
|
+
}),
|
|
77
|
+
list: (accountId) => cfRequest(rest, "GET", `/accounts/${accountId}/cfd_tunnel`, void 0, { is_deleted: "false" }),
|
|
78
|
+
token: (accountId, tunnelId) => cfRequest(rest, "GET", `/accounts/${accountId}/cfd_tunnel/${tunnelId}/token`),
|
|
79
|
+
delete: (accountId, tunnelId) => cfRequest(rest, "DELETE", `/accounts/${accountId}/cfd_tunnel/${tunnelId}`, void 0, { cascade: "true" }),
|
|
80
|
+
getConfig: (accountId, tunnelId) => cfRequest(rest, "GET", `/accounts/${accountId}/cfd_tunnel/${tunnelId}/configurations`),
|
|
81
|
+
putConfig: (accountId, tunnelId, config) => cfRequest(rest, "PUT", `/accounts/${accountId}/cfd_tunnel/${tunnelId}/configurations`, { config })
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
//#endregion
|
|
85
|
+
//#region ../../../../../src/workers/workers.ts
|
|
86
|
+
function workers(rest, opts) {
|
|
87
|
+
const baseUrl = opts.baseUrl ?? "https://api.cloudflare.com/client/v4";
|
|
88
|
+
const fetchImpl = opts.fetch ?? globalThis.fetch;
|
|
89
|
+
return {
|
|
90
|
+
putScript: async (accountId, scriptName, script) => {
|
|
91
|
+
const form = new FormData();
|
|
92
|
+
form.append("metadata", new Blob([JSON.stringify({
|
|
93
|
+
main_module: "index.js",
|
|
94
|
+
compatibility_date: "2025-08-31"
|
|
95
|
+
})], { type: "application/json" }));
|
|
96
|
+
form.append("index.js", new Blob([script], { type: "application/javascript+module" }), "index.js");
|
|
97
|
+
const path = `/accounts/${accountId}/workers/scripts/${encodeURIComponent(scriptName)}`;
|
|
98
|
+
const res = await fetchImpl(`${baseUrl}${path}`, {
|
|
99
|
+
method: "PUT",
|
|
100
|
+
headers: { authorization: `Bearer ${opts.token}` },
|
|
101
|
+
body: form
|
|
102
|
+
});
|
|
103
|
+
if (!res.ok) {
|
|
104
|
+
const body = await res.text().catch(() => "");
|
|
105
|
+
throw new ProviderApiError(`Cloudflare PUT ${path} → ${res.status}`, res.status, body);
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
listRoutes: (zoneId) => cfRequest(rest, "GET", `/zones/${zoneId}/workers/routes`),
|
|
109
|
+
createRoute: (zoneId, pattern, script) => cfRequest(rest, "POST", `/zones/${zoneId}/workers/routes`, {
|
|
110
|
+
pattern,
|
|
111
|
+
script
|
|
112
|
+
}),
|
|
113
|
+
updateRoute: (zoneId, routeId, pattern, script) => cfRequest(rest, "PUT", `/zones/${zoneId}/workers/routes/${routeId}`, {
|
|
114
|
+
pattern,
|
|
115
|
+
script
|
|
116
|
+
}),
|
|
117
|
+
putSecret: (accountId, scriptName, name, value) => cfRequest(rest, "PUT", `/accounts/${accountId}/workers/scripts/${encodeURIComponent(scriptName)}/secrets`, {
|
|
118
|
+
name,
|
|
119
|
+
text: value,
|
|
120
|
+
type: "secret_text"
|
|
121
|
+
}),
|
|
122
|
+
listSecrets: (accountId, scriptName) => cfRequest(rest, "GET", `/accounts/${accountId}/workers/scripts/${encodeURIComponent(scriptName)}/secrets`),
|
|
123
|
+
deleteSecret: (accountId, scriptName, name) => cfRequest(rest, "DELETE", `/accounts/${accountId}/workers/scripts/${encodeURIComponent(scriptName)}/secrets/${encodeURIComponent(name)}`)
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
127
|
+
//#region ../../../../../src/zones/zones.ts
|
|
128
|
+
function zones(rest) {
|
|
129
|
+
return { list: (query) => cfRequest(rest, "GET", "/zones", void 0, {
|
|
130
|
+
...query?.name ? { name: query.name } : {},
|
|
131
|
+
per_page: String(query?.per_page ?? 100)
|
|
132
|
+
}) };
|
|
133
|
+
}
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region ../../../../../src/index.ts
|
|
136
|
+
function createCloudflareClient(opts) {
|
|
137
|
+
const rest = createCloudflareRestClient(opts);
|
|
138
|
+
return {
|
|
139
|
+
dns: dns(rest),
|
|
140
|
+
pages: pages(rest),
|
|
141
|
+
zones: zones(rest),
|
|
142
|
+
tunnels: tunnels(rest),
|
|
143
|
+
tokens: tokens(rest),
|
|
144
|
+
workers: workers(rest, opts)
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
//#endregion
|
|
148
|
+
export { createCloudflareClient };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theholocron/cloudflare-client",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.33.0",
|
|
4
4
|
"description": "A TypeScript client for the Cloudflare API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -33,13 +33,13 @@
|
|
|
33
33
|
],
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@theholocron/observability": "^0.3.0",
|
|
36
|
-
"@theholocron/http-client": "^1.
|
|
36
|
+
"@theholocron/http-client": "^1.33.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@theholocron/cli": "5.0.0-alpha.79",
|
|
40
40
|
"@theholocron/eslint-config": "^8.4.3",
|
|
41
41
|
"@theholocron/tsconfig": "^8.2.0",
|
|
42
|
-
"@theholocron/tsdown-config": "^8.
|
|
42
|
+
"@theholocron/tsdown-config": "^8.6.1",
|
|
43
43
|
"@theholocron/vitest-config": "^8.2.0",
|
|
44
44
|
"@types/node": "^26.4.1",
|
|
45
45
|
"@vitest/coverage-v8": "^5.0.0",
|