@theholocron/holocron-plugin-cloudflare 3.31.1 → 3.32.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 CHANGED
@@ -1,8 +1,35 @@
1
- import { AuthError, Dns, DnsRecord, ResolveTokenInput } from "@theholocron/cli";
1
+ import { AuthError, Deployment, DeploymentProject, DeploymentProjectSettings, DeploymentRecord, DeploymentTarget, DeploymentTrigger, Dns, DnsRecord, ResolveTokenInput } from "@theholocron/cli";
2
2
  import { CloudflareClient, CloudflareClientOptions, createCloudflareClient } from "@theholocron/cloudflare-client";
3
3
  //#region src/auth.d.ts
4
4
  declare const resolveToken: (input?: ResolveTokenInput) => string;
5
5
  //#endregion
6
+ //#region src/capabilities/deployment.d.ts
7
+ declare class CloudflareDeployment implements Deployment {
8
+ private readonly client;
9
+ private readonly accountId;
10
+ readonly key: "deployment";
11
+ readonly providerName = "cloudflare";
12
+ constructor(client: CloudflareClient, accountId: string);
13
+ listProjects(): Promise<DeploymentProject[]>;
14
+ ensureProject(input: {
15
+ name: string;
16
+ framework?: string;
17
+ repo?: string;
18
+ rootDirectory?: string;
19
+ }): Promise<DeploymentProject>;
20
+ updateProjectSettings(projectId: string, settings: DeploymentProjectSettings): Promise<DeploymentProject>;
21
+ listEnvVars(projectId: string, target: DeploymentTarget): Promise<string[]>;
22
+ setEnvVar(projectId: string, target: DeploymentTarget, name: string, value: string): Promise<void>;
23
+ triggerDeployment(input: {
24
+ projectId: string;
25
+ branch: string;
26
+ target?: DeploymentTrigger;
27
+ }): Promise<DeploymentRecord>;
28
+ getDeployment(deploymentId: string): Promise<DeploymentRecord>;
29
+ ensureCustomDomain(projectId: string, hostname: string): Promise<void>;
30
+ private getProjectByName;
31
+ }
32
+ //#endregion
6
33
  //#region src/capabilities/dns.d.ts
7
34
  declare class CloudflareDns implements Dns {
8
35
  private readonly client;
@@ -42,8 +69,8 @@ declare function verifyToken(token: string, opts?: VerifyTokenOptions): Promise<
42
69
  //#region src/index.d.ts
43
70
  interface CloudflarePluginOptions extends ResolveTokenInput {
44
71
  /**
45
- * Cloudflare account id. Optional for DNS operations; required only
46
- * for account-scoped endpoints (tunnels, custom nameservers).
72
+ * Cloudflare account ID. Required for Pages (deployment) operations;
73
+ * optional for DNS-only use.
47
74
  */
48
75
  accountId?: string;
49
76
  /** Override base URL for tests. */
@@ -56,12 +83,14 @@ interface PluginContext {
56
83
  }
57
84
  declare function createContext(options?: CloudflarePluginOptions): PluginContext;
58
85
  declare function dns(ctx: PluginContext): Dns;
86
+ declare function deployment(ctx: PluginContext): Deployment;
59
87
  declare function createPlugin(options?: CloudflarePluginOptions): {
60
88
  name: string;
61
89
  capabilities: {
90
+ deployment?: (() => Deployment) | undefined;
62
91
  dns: () => Dns;
63
92
  };
64
93
  };
65
94
  declare const AUTH_HINT: string;
66
95
  //#endregion
67
- export { AUTH_HINT, AuthError, type CloudflareClient, type CloudflareClientOptions, CloudflareDns, CloudflarePluginOptions, PluginContext, type ResolveTokenInput, type VerifyTokenFailure, type VerifyTokenResult, type VerifyTokenSuccess, createCloudflareClient, createContext, createPlugin, dns, resolveToken, verifyToken };
96
+ export { AUTH_HINT, AuthError, type CloudflareClient, type CloudflareClientOptions, CloudflareDeployment, CloudflareDns, CloudflarePluginOptions, PluginContext, type ResolveTokenInput, type VerifyTokenFailure, type VerifyTokenResult, type VerifyTokenSuccess, createCloudflareClient, createContext, createPlugin, deployment, dns, resolveToken, verifyToken };
package/dist/index.mjs CHANGED
@@ -8,6 +8,102 @@ const resolveToken = createResolveToken({
8
8
  errorMessage: "no Cloudflare API token found. Pass --token <TOKEN>, set HOLOCRON_CLOUDFLARE_TOKEN / CLOUDFLARE_API_TOKEN, or run: holocron auth set cloudflare <TOKEN>"
9
9
  });
10
10
  //#endregion
11
+ //#region src/capabilities/deployment.ts
12
+ var CloudflareDeployment = class {
13
+ client;
14
+ accountId;
15
+ key = "deployment";
16
+ providerName = "cloudflare";
17
+ constructor(client, accountId) {
18
+ this.client = client;
19
+ this.accountId = accountId;
20
+ }
21
+ async listProjects() {
22
+ return (await this.client.pages.listProjects(this.accountId)).map(mapProject);
23
+ }
24
+ async ensureProject(input) {
25
+ const existing = await this.getProjectByName(input.name);
26
+ if (existing) return existing;
27
+ return mapProject(await this.client.pages.createProject(this.accountId, {
28
+ name: input.name,
29
+ production_branch: "main"
30
+ }));
31
+ }
32
+ async updateProjectSettings(projectId, settings) {
33
+ return mapProject(await this.client.pages.getProject(this.accountId, projectId));
34
+ }
35
+ async listEnvVars(projectId, target) {
36
+ const project = await this.client.pages.getProject(this.accountId, projectId);
37
+ const envConfig = target === "production" ? project.deployment_configs.production : project.deployment_configs.preview;
38
+ return Object.keys(envConfig.env_vars);
39
+ }
40
+ async setEnvVar(projectId, target, name, value) {
41
+ const cfg = (await this.client.pages.getProject(this.accountId, projectId)).deployment_configs;
42
+ const scope = target === "production" ? "production" : "preview";
43
+ const updated = {
44
+ ...cfg[scope].env_vars,
45
+ [name]: {
46
+ value,
47
+ type: "plain_text"
48
+ }
49
+ };
50
+ await this.client.pages.updateProject(this.accountId, projectId, { deployment_configs: {
51
+ ...cfg,
52
+ [scope]: { env_vars: updated }
53
+ } });
54
+ }
55
+ async triggerDeployment(input) {
56
+ return mapDeployment(await this.client.pages.createDeployment(this.accountId, input.projectId, input.branch), input.projectId, input.branch, input.target);
57
+ }
58
+ async getDeployment(deploymentId) {
59
+ const sep = deploymentId.indexOf(":");
60
+ if (sep === -1) throw new ProviderApiError(`Invalid Cloudflare Pages deployment id "${deploymentId}" — expected "projectName:deploymentId"`, 400, void 0);
61
+ const projectName = deploymentId.slice(0, sep);
62
+ const cfDeployId = deploymentId.slice(sep + 1);
63
+ const raw = await this.client.pages.getDeployment(this.accountId, projectName, cfDeployId);
64
+ return mapDeployment(raw, projectName, raw.deployment_trigger.metadata.branch, void 0);
65
+ }
66
+ async ensureCustomDomain(projectId, hostname) {
67
+ if ((await this.client.pages.listDomains(this.accountId, projectId)).some((d) => d.name === hostname)) return;
68
+ await this.client.pages.addDomain(this.accountId, projectId, hostname);
69
+ }
70
+ async getProjectByName(name) {
71
+ try {
72
+ return mapProject(await this.client.pages.getProject(this.accountId, name));
73
+ } catch (err) {
74
+ if (err instanceof ProviderApiError && err.status === 404) return null;
75
+ throw err;
76
+ }
77
+ }
78
+ };
79
+ function mapProject(raw) {
80
+ return {
81
+ id: raw.name,
82
+ name: raw.name
83
+ };
84
+ }
85
+ function mapDeployment(raw, projectName, branch, target) {
86
+ const record = {
87
+ id: `${projectName}:${raw.id}`,
88
+ url: raw.url,
89
+ branch,
90
+ status: normalizeStatus(raw.latest_stage.status)
91
+ };
92
+ if (target) record.target = target;
93
+ return record;
94
+ }
95
+ function normalizeStatus(status) {
96
+ switch (status) {
97
+ case "idle": return "queued";
98
+ case "active": return "building";
99
+ case "success": return "ready";
100
+ case "failure": return "error";
101
+ case "canceled": return "cancelled";
102
+ /* c8 ignore next */
103
+ default: return "error";
104
+ }
105
+ }
106
+ //#endregion
11
107
  //#region src/capabilities/dns.ts
12
108
  var CloudflareDns = class {
13
109
  client;
@@ -111,13 +207,20 @@ function createContext(options = {}) {
111
207
  function dns(ctx) {
112
208
  return new CloudflareDns(ctx.client);
113
209
  }
210
+ function deployment(ctx) {
211
+ if (!ctx.options.accountId) throw new Error("Cloudflare accountId is required for Pages deployments — set accountId in the plugin options or CLOUDFLARE_ACCOUNT_ID env var");
212
+ return new CloudflareDeployment(ctx.client, ctx.options.accountId);
213
+ }
114
214
  function createPlugin(options = {}) {
115
215
  const ctx = createContext(options);
116
216
  return {
117
217
  name: "@theholocron/holocron-plugin-cloudflare",
118
- capabilities: { dns: () => dns(ctx) }
218
+ capabilities: {
219
+ dns: () => dns(ctx),
220
+ ...ctx.options.accountId ? { deployment: () => deployment(ctx) } : {}
221
+ }
119
222
  };
120
223
  }
121
- const AUTH_HINT = "create an API token at https://dash.cloudflare.com/profile/api-tokens with Zone:Read and DNS:Edit permissions, then run: holocron auth set cloudflare <TOKEN>";
224
+ const AUTH_HINT = "create an API token at https://dash.cloudflare.com/profile/api-tokens with Zone:Read, DNS:Edit, and Cloudflare Pages:Edit permissions, then run: holocron auth set cloudflare <TOKEN>";
122
225
  //#endregion
123
- export { AUTH_HINT, AuthError, CloudflareDns, createCloudflareClient, createContext, createPlugin, dns, resolveToken, verifyToken };
226
+ export { AUTH_HINT, AuthError, CloudflareDeployment, CloudflareDns, createCloudflareClient, createContext, createPlugin, deployment, dns, resolveToken, verifyToken };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theholocron/holocron-plugin-cloudflare",
3
- "version": "3.31.1",
3
+ "version": "3.32.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",
@@ -30,7 +30,7 @@
30
30
  "dist"
31
31
  ],
32
32
  "devDependencies": {
33
- "@theholocron/cloudflare-client": "^1.9.0",
33
+ "@theholocron/cloudflare-client": "^1.11.2",
34
34
  "@theholocron/eslint-config": "^7.25.3",
35
35
  "@theholocron/tsconfig": "^7.20.0",
36
36
  "@theholocron/tsdown-config": "^7.20.0",
@@ -46,11 +46,11 @@
46
46
  "tsx": "4.23.12",
47
47
  "typescript": "^5.9.3",
48
48
  "vitest": "^4.1.10",
49
- "@theholocron/cli": "3.31.1"
49
+ "@theholocron/cli": "3.32.0"
50
50
  },
51
51
  "peerDependencies": {
52
- "@theholocron/cloudflare-client": "^1.9.0",
53
- "@theholocron/cli": "3.31.1"
52
+ "@theholocron/cloudflare-client": "^1.11.2",
53
+ "@theholocron/cli": "3.32.0"
54
54
  },
55
55
  "peerDependenciesMeta": {
56
56
  "@theholocron/cloudflare-client": {}