@theholocron/holocron-plugin-cloudflare 3.63.0 → 3.64.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 +10 -4
- package/dist/index.mjs +39 -34
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -9,7 +9,7 @@ declare class CloudflareDeployment implements Deployment {
|
|
|
9
9
|
private readonly accountId;
|
|
10
10
|
readonly key: "deployment";
|
|
11
11
|
readonly providerName = "cloudflare";
|
|
12
|
-
constructor(client: CloudflareClient, accountId: string);
|
|
12
|
+
constructor(client: () => CloudflareClient, accountId: string);
|
|
13
13
|
listProjects(): Promise<DeploymentProject[]>;
|
|
14
14
|
ensureProject(input: {
|
|
15
15
|
name: string;
|
|
@@ -38,7 +38,7 @@ declare class CloudflareDns implements Dns {
|
|
|
38
38
|
readonly key: "dns";
|
|
39
39
|
readonly providerName = "cloudflare";
|
|
40
40
|
private readonly zoneCache;
|
|
41
|
-
constructor(client: CloudflareClient);
|
|
41
|
+
constructor(client: () => CloudflareClient);
|
|
42
42
|
listRecords(domain: string): Promise<DnsRecord[]>;
|
|
43
43
|
upsertRecord(domain: string, record: DnsRecord): Promise<DnsRecord>;
|
|
44
44
|
deleteRecord(domain: string, id: string): Promise<void>;
|
|
@@ -69,8 +69,11 @@ declare class CloudflareWorkers implements Workers {
|
|
|
69
69
|
private readonly zoneCache;
|
|
70
70
|
private readonly baseUrl;
|
|
71
71
|
private readonly fetchImpl;
|
|
72
|
+
/** Memoized token thunk — resolved on the first authenticated request. */
|
|
72
73
|
private readonly token;
|
|
73
|
-
constructor(zones: ZonesClient, accountId: string, opts:
|
|
74
|
+
constructor(zones: () => ZonesClient, accountId: string, opts: {
|
|
75
|
+
token: () => string;
|
|
76
|
+
} & Pick<CloudflareClientOptions$1, "baseUrl" | "fetch">);
|
|
74
77
|
upsertProxy(hostname: string, config: WikiProxyConfig): Promise<void>;
|
|
75
78
|
private putScript;
|
|
76
79
|
private listRoutes;
|
|
@@ -109,7 +112,10 @@ interface CloudflarePluginOptions extends ResolveTokenInput {
|
|
|
109
112
|
}
|
|
110
113
|
interface PluginContext {
|
|
111
114
|
options: CloudflarePluginOptions;
|
|
112
|
-
client
|
|
115
|
+
/** Memoized client — the token is resolved on first use, not at plugin load. */
|
|
116
|
+
client: () => CloudflareClient;
|
|
117
|
+
/** Memoized token resolver — shared by the client and the Workers capability. */
|
|
118
|
+
token: () => string;
|
|
113
119
|
}
|
|
114
120
|
declare function createContext(options?: CloudflarePluginOptions): PluginContext;
|
|
115
121
|
declare function dns(ctx: PluginContext): Dns;
|
package/dist/index.mjs
CHANGED
|
@@ -19,26 +19,26 @@ var CloudflareDeployment = class {
|
|
|
19
19
|
this.accountId = accountId;
|
|
20
20
|
}
|
|
21
21
|
async listProjects() {
|
|
22
|
-
return (await this.client.pages.listProjects(this.accountId)).map(mapProject);
|
|
22
|
+
return (await this.client().pages.listProjects(this.accountId)).map(mapProject);
|
|
23
23
|
}
|
|
24
24
|
async ensureProject(input) {
|
|
25
25
|
const existing = await this.getProjectByName(input.name);
|
|
26
26
|
if (existing) return existing;
|
|
27
|
-
return mapProject(await this.client.pages.createProject(this.accountId, {
|
|
27
|
+
return mapProject(await this.client().pages.createProject(this.accountId, {
|
|
28
28
|
name: input.name,
|
|
29
29
|
production_branch: "main"
|
|
30
30
|
}));
|
|
31
31
|
}
|
|
32
32
|
async updateProjectSettings(projectId, settings) {
|
|
33
|
-
return mapProject(await this.client.pages.getProject(this.accountId, projectId));
|
|
33
|
+
return mapProject(await this.client().pages.getProject(this.accountId, projectId));
|
|
34
34
|
}
|
|
35
35
|
async listEnvVars(projectId, target) {
|
|
36
|
-
const project = await this.client.pages.getProject(this.accountId, projectId);
|
|
36
|
+
const project = await this.client().pages.getProject(this.accountId, projectId);
|
|
37
37
|
const envConfig = target === "production" ? project.deployment_configs.production : project.deployment_configs.preview;
|
|
38
38
|
return Object.keys(envConfig.env_vars);
|
|
39
39
|
}
|
|
40
40
|
async setEnvVar(projectId, target, name, value) {
|
|
41
|
-
const cfg = (await this.client.pages.getProject(this.accountId, projectId)).deployment_configs;
|
|
41
|
+
const cfg = (await this.client().pages.getProject(this.accountId, projectId)).deployment_configs;
|
|
42
42
|
const scope = target === "production" ? "production" : "preview";
|
|
43
43
|
const updated = {
|
|
44
44
|
...cfg[scope].env_vars,
|
|
@@ -47,39 +47,39 @@ var CloudflareDeployment = class {
|
|
|
47
47
|
type: "plain_text"
|
|
48
48
|
}
|
|
49
49
|
};
|
|
50
|
-
await this.client.pages.updateProject(this.accountId, projectId, { deployment_configs: {
|
|
50
|
+
await this.client().pages.updateProject(this.accountId, projectId, { deployment_configs: {
|
|
51
51
|
...cfg,
|
|
52
52
|
[scope]: { env_vars: updated }
|
|
53
53
|
} });
|
|
54
54
|
}
|
|
55
55
|
async triggerDeployment(input) {
|
|
56
|
-
return mapDeployment(await this.client.pages.createDeployment(this.accountId, input.projectId, input.branch), input.projectId, input.branch, input.target);
|
|
56
|
+
return mapDeployment(await this.client().pages.createDeployment(this.accountId, input.projectId, input.branch), input.projectId, input.branch, input.target);
|
|
57
57
|
}
|
|
58
58
|
async getDeployment(deploymentId) {
|
|
59
59
|
const sep = deploymentId.indexOf(":");
|
|
60
60
|
if (sep === -1) throw new ProviderApiError(`Invalid Cloudflare Pages deployment id "${deploymentId}" — expected "projectName:deploymentId"`, 400, void 0);
|
|
61
61
|
const projectName = deploymentId.slice(0, sep);
|
|
62
62
|
const cfDeployId = deploymentId.slice(sep + 1);
|
|
63
|
-
const raw = await this.client.pages.getDeployment(this.accountId, projectName, cfDeployId);
|
|
63
|
+
const raw = await this.client().pages.getDeployment(this.accountId, projectName, cfDeployId);
|
|
64
64
|
return mapDeployment(raw, projectName, raw.deployment_trigger.metadata.branch, void 0);
|
|
65
65
|
}
|
|
66
66
|
async listPreviewDeployments(projectId, branch) {
|
|
67
|
-
return (await this.client.pages.listDeployments(this.accountId, projectId)).filter((d) => d.deployment_trigger.metadata.branch === branch).map((d) => mapDeployment(d, projectId, d.deployment_trigger.metadata.branch, void 0));
|
|
67
|
+
return (await this.client().pages.listDeployments(this.accountId, projectId)).filter((d) => d.deployment_trigger.metadata.branch === branch).map((d) => mapDeployment(d, projectId, d.deployment_trigger.metadata.branch, void 0));
|
|
68
68
|
}
|
|
69
69
|
async deletePreviewDeployments(projectId, deploymentIds) {
|
|
70
70
|
await Promise.all(deploymentIds.map((id) => {
|
|
71
71
|
const cfId = id.includes(":") ? id.slice(id.indexOf(":") + 1) : id;
|
|
72
|
-
return this.client.pages.deleteDeployment(this.accountId, projectId, cfId);
|
|
72
|
+
return this.client().pages.deleteDeployment(this.accountId, projectId, cfId);
|
|
73
73
|
}));
|
|
74
74
|
return deploymentIds.length;
|
|
75
75
|
}
|
|
76
76
|
async ensureCustomDomain(projectId, hostname) {
|
|
77
|
-
if ((await this.client.pages.listDomains(this.accountId, projectId)).some((d) => d.name === hostname)) return;
|
|
78
|
-
await this.client.pages.addDomain(this.accountId, projectId, hostname);
|
|
77
|
+
if ((await this.client().pages.listDomains(this.accountId, projectId)).some((d) => d.name === hostname)) return;
|
|
78
|
+
await this.client().pages.addDomain(this.accountId, projectId, hostname);
|
|
79
79
|
}
|
|
80
80
|
async getProjectByName(name) {
|
|
81
81
|
try {
|
|
82
|
-
return mapProject(await this.client.pages.getProject(this.accountId, name));
|
|
82
|
+
return mapProject(await this.client().pages.getProject(this.accountId, name));
|
|
83
83
|
} catch (err) {
|
|
84
84
|
if (err instanceof ProviderApiError && err.status === 404) return null;
|
|
85
85
|
throw err;
|
|
@@ -125,22 +125,23 @@ var CloudflareDns = class {
|
|
|
125
125
|
}
|
|
126
126
|
async listRecords(domain) {
|
|
127
127
|
const zoneId = await this.resolveZone(domain);
|
|
128
|
-
return (await this.client.dns.list(zoneId)).map(mapRecord);
|
|
128
|
+
return (await this.client().dns.list(zoneId)).map(mapRecord);
|
|
129
129
|
}
|
|
130
130
|
async upsertRecord(domain, record) {
|
|
131
|
+
const client = this.client();
|
|
131
132
|
const zoneId = await this.resolveZone(domain);
|
|
132
|
-
const existing = await
|
|
133
|
+
const existing = await client.dns.list(zoneId, {
|
|
133
134
|
type: record.type,
|
|
134
135
|
name: record.name
|
|
135
136
|
});
|
|
136
|
-
if (existing.length > 0) return mapRecord(await
|
|
137
|
+
if (existing.length > 0) return mapRecord(await client.dns.update(zoneId, existing[0].id, {
|
|
137
138
|
type: record.type,
|
|
138
139
|
name: record.name,
|
|
139
140
|
content: record.content,
|
|
140
141
|
...record.ttl !== void 0 ? { ttl: record.ttl } : {},
|
|
141
142
|
...record.proxied !== void 0 ? { proxied: record.proxied } : {}
|
|
142
143
|
}));
|
|
143
|
-
return mapRecord(await
|
|
144
|
+
return mapRecord(await client.dns.create(zoneId, {
|
|
144
145
|
type: record.type,
|
|
145
146
|
name: record.name,
|
|
146
147
|
content: record.content,
|
|
@@ -150,7 +151,7 @@ var CloudflareDns = class {
|
|
|
150
151
|
}
|
|
151
152
|
async deleteRecord(domain, id) {
|
|
152
153
|
const zoneId = await this.resolveZone(domain);
|
|
153
|
-
await this.client.dns.delete(zoneId, id);
|
|
154
|
+
await this.client().dns.delete(zoneId, id);
|
|
154
155
|
}
|
|
155
156
|
/**
|
|
156
157
|
* Walk from full domain up to apex to find the Cloudflare zone.
|
|
@@ -165,7 +166,7 @@ var CloudflareDns = class {
|
|
|
165
166
|
const parts = domain.split(".");
|
|
166
167
|
for (let i = 0; i < parts.length - 1; i++) {
|
|
167
168
|
const candidate = parts.slice(i).join(".");
|
|
168
|
-
const zones = await this.client.zones.list({ name: candidate });
|
|
169
|
+
const zones = await this.client().zones.list({ name: candidate });
|
|
169
170
|
if (zones.length > 0) {
|
|
170
171
|
this.zoneCache.set(domain, zones[0].id);
|
|
171
172
|
return zones[0].id;
|
|
@@ -193,6 +194,7 @@ var CloudflareWorkers = class {
|
|
|
193
194
|
zoneCache = /* @__PURE__ */ new Map();
|
|
194
195
|
baseUrl;
|
|
195
196
|
fetchImpl;
|
|
197
|
+
/** Memoized token thunk — resolved on the first authenticated request. */
|
|
196
198
|
token;
|
|
197
199
|
constructor(zones, accountId, opts) {
|
|
198
200
|
this.zones = zones;
|
|
@@ -222,7 +224,7 @@ var CloudflareWorkers = class {
|
|
|
222
224
|
const path = `/accounts/${this.accountId}/workers/scripts/${encodeURIComponent(scriptName)}`;
|
|
223
225
|
const res = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
224
226
|
method: "PUT",
|
|
225
|
-
headers: { authorization: `Bearer ${this.token}` },
|
|
227
|
+
headers: { authorization: `Bearer ${this.token()}` },
|
|
226
228
|
body: form
|
|
227
229
|
});
|
|
228
230
|
if (!res.ok) {
|
|
@@ -247,7 +249,7 @@ var CloudflareWorkers = class {
|
|
|
247
249
|
}
|
|
248
250
|
async cfRequest(method, path, body) {
|
|
249
251
|
const headers = {
|
|
250
|
-
authorization: `Bearer ${this.token}`,
|
|
252
|
+
authorization: `Bearer ${this.token()}`,
|
|
251
253
|
accept: "application/json"
|
|
252
254
|
};
|
|
253
255
|
const init = {
|
|
@@ -273,7 +275,7 @@ var CloudflareWorkers = class {
|
|
|
273
275
|
const parts = domain.split(".");
|
|
274
276
|
for (let i = 0; i < parts.length - 1; i++) {
|
|
275
277
|
const candidate = parts.slice(i).join(".");
|
|
276
|
-
const zones = await this.zones.list({ name: candidate });
|
|
278
|
+
const zones = await this.zones().list({ name: candidate });
|
|
277
279
|
if (zones.length > 0) {
|
|
278
280
|
this.zoneCache.set(domain, zones[0].id);
|
|
279
281
|
return zones[0].id;
|
|
@@ -330,17 +332,21 @@ async function verifyToken(token, opts = {}) {
|
|
|
330
332
|
//#endregion
|
|
331
333
|
//#region src/index.ts
|
|
332
334
|
function createContext(options = {}) {
|
|
333
|
-
const token = resolveToken(options);
|
|
334
335
|
const accountId = options.accountId ?? process.env.CLOUDFLARE_ACCOUNT_ID;
|
|
336
|
+
const opts = {
|
|
337
|
+
...options,
|
|
338
|
+
accountId
|
|
339
|
+
};
|
|
340
|
+
let token;
|
|
341
|
+
let client;
|
|
342
|
+
const resolve = () => token ??= resolveToken(opts);
|
|
335
343
|
return {
|
|
336
|
-
options:
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
baseUrl: options.baseUrl,
|
|
343
|
-
fetch: options.fetch
|
|
344
|
+
options: opts,
|
|
345
|
+
token: resolve,
|
|
346
|
+
client: () => client ??= createCloudflareClient({
|
|
347
|
+
token: resolve(),
|
|
348
|
+
baseUrl: opts.baseUrl,
|
|
349
|
+
fetch: opts.fetch
|
|
344
350
|
})
|
|
345
351
|
};
|
|
346
352
|
}
|
|
@@ -353,9 +359,8 @@ function deployment(ctx) {
|
|
|
353
359
|
}
|
|
354
360
|
function workersCapability(ctx) {
|
|
355
361
|
if (!ctx.options.accountId) throw new Error("Cloudflare accountId is required for Workers — set accountId in the plugin options or CLOUDFLARE_ACCOUNT_ID env var");
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
token,
|
|
362
|
+
return new CloudflareWorkers(() => ctx.client().zones, ctx.options.accountId, {
|
|
363
|
+
token: ctx.token,
|
|
359
364
|
baseUrl: ctx.options.baseUrl,
|
|
360
365
|
fetch: ctx.options.fetch
|
|
361
366
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theholocron/holocron-plugin-cloudflare",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.64.0",
|
|
4
4
|
"description": "Holocron plugin for Cloudflare. Implements the dns capability against Cloudflare's REST API — zone resolution, DNS record management.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -46,11 +46,11 @@
|
|
|
46
46
|
"tsx": "4.23.12",
|
|
47
47
|
"typescript": "^5.9.3",
|
|
48
48
|
"vitest": "^4.1.11",
|
|
49
|
-
"@theholocron/cli": "3.
|
|
49
|
+
"@theholocron/cli": "3.64.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"@theholocron/cloudflare-client": "^1.14.2",
|
|
53
|
-
"@theholocron/cli": "3.
|
|
53
|
+
"@theholocron/cli": "3.64.0"
|
|
54
54
|
},
|
|
55
55
|
"peerDependenciesMeta": {
|
|
56
56
|
"@theholocron/cloudflare-client": {}
|