@cloudhal/cli 0.3.9 → 0.3.10

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.
@@ -14,18 +14,18 @@
14
14
  "astro": "astro"
15
15
  },
16
16
  "dependencies": {
17
- "@cloudhal/astro-renderer": "0.3.9",
18
- "@cloudhal/core-ts": "0.3.9",
17
+ "@cloudhal/astro-renderer": "0.3.10",
18
+ "@cloudhal/core-ts": "0.3.10",
19
19
  "@tailwindcss/vite": "^4.3.3",
20
20
  "astro": "7.3.6",
21
21
  "better-sqlite3": "13.0.3",
22
22
  "tailwindcss": "^4.3.3",
23
23
  "@astrojs/cloudflare": "14.3.4",
24
- "@cloudhal/cli": "0.3.9"
24
+ "@cloudhal/cli": "0.3.10"
25
25
  },
26
26
  "devDependencies": {
27
27
  "wrangler": "^4.148.0",
28
- "@cloudhal/cloudflare": "0.3.9"
28
+ "@cloudhal/cloudflare": "0.3.10"
29
29
  },
30
30
  "trustedDependencies": [
31
31
  "better-sqlite3",
@@ -24,5 +24,15 @@ export declare const BUNDLE_LIFECYCLE_DAYS = 30;
24
24
  */
25
25
  export declare function ensureBundleLifecycle(run: WranglerRunner, cwd: string, bucket: string, log: (l: string) => void): Promise<void>;
26
26
  export declare function waitForHealth(adminUrl: string, f: typeof fetch, log: (line: string) => void, timeoutMs: number): Promise<void>;
27
+ /**
28
+ * Runs `step` again while it fails with 401. Right after a deploy the edge can still answer from
29
+ * the previous admin Worker version, which holds the previous deployment token (Workers Builds
30
+ * makes a new one on every build), for a few seconds. Gives up after `timeoutMs`.
31
+ */
32
+ export declare function whileTokenPropagates<T>(step: () => Promise<T>, options: {
33
+ log: (line: string) => void;
34
+ timeoutMs?: number;
35
+ waitMs?: number;
36
+ }): Promise<T>;
27
37
  /** Purges the site Worker's whole cache once (the script tag lives in cached HTML). */
28
38
  export declare function purgeSite(siteUrl: string, token: string, f: typeof fetch, log: (line: string) => void): Promise<boolean>;
@@ -139,6 +139,31 @@ export async function waitForHealth(
139
139
  }
140
140
  }
141
141
 
142
+ /**
143
+ * Runs `step` again while it fails with 401. Right after a deploy the edge can still answer from
144
+ * the previous admin Worker version, which holds the previous deployment token (Workers Builds
145
+ * makes a new one on every build), for a few seconds. Gives up after `timeoutMs`.
146
+ */
147
+ export async function whileTokenPropagates (
148
+ step ,
149
+ options ,
150
+ ) {
151
+ const deadline = Date.now() + (options.timeoutMs ?? 90_000);
152
+ let announced = false;
153
+ for (;;) {
154
+ try {
155
+ return await step();
156
+ } catch (e) {
157
+ if (!/\(401\)/.test(e instanceof Error ? e.message : "") || Date.now() > deadline) throw e;
158
+ if (!announced) {
159
+ options.log("the deployment does not accept the new token yet; retrying while it spreads…");
160
+ announced = true;
161
+ }
162
+ await new Promise((r) => setTimeout(r, options.waitMs ?? 5000));
163
+ }
164
+ }
165
+ }
166
+
142
167
  /** Purges the site Worker's whole cache once (the script tag lives in cached HTML). */
143
168
  export async function purgeSite(
144
169
  siteUrl ,
@@ -14,7 +14,7 @@ import { openLocalStore } from "@cloudhal/core-ts/local";
14
14
  import { deployedUrls, isCronLimitError, must, WranglerError } from "../../cloudflare/wrangler.js";
15
15
  import { pushSite, setPrimaryDomain } from "../sync.js";
16
16
 
17
- import { purgeSite, waitForHealth } from "./resources.js";
17
+ import { purgeSite, waitForHealth, whileTokenPropagates } from "./resources.js";
18
18
  import { CRON_REFUSED_MESSAGE } from "./schedules-guard.js";
19
19
 
20
20
 
@@ -111,29 +111,35 @@ export async function afterDeploy(
111
111
  });
112
112
  await l.close();
113
113
  }
114
- const result = await pushSite({
115
- projectDir: options.projectDir,
116
- ifAbsent: true,
117
- log,
118
- ...(options.fetch ? { fetch: options.fetch } : {}),
119
- });
120
- // A custom domain becomes the site's primary hostname (the workers.dev one stays secondary).
121
- if (cfg.domains?.site) {
122
- await setPrimaryDomain({
114
+ const retry = (step ) => whileTokenPropagates(step, { log });
115
+ const result = await retry(() =>
116
+ pushSite({
123
117
  projectDir: options.projectDir,
124
- hostname: cfg.domains.site,
118
+ ifAbsent: true,
119
+ log,
125
120
  ...(options.fetch ? { fetch: options.fetch } : {}),
126
- });
127
- log(
128
- `site domain: https://${cfg.domains.site} (Cloudflare issues the certificate on first use)`,
121
+ }),
122
+ );
123
+ // A custom domain becomes the site's primary hostname (the workers.dev one stays secondary).
124
+ const domain = cfg.domains?.site;
125
+ if (domain) {
126
+ await retry(() =>
127
+ setPrimaryDomain({
128
+ projectDir: options.projectDir,
129
+ hostname: domain,
130
+ ...(options.fetch ? { fetch: options.fetch } : {}),
131
+ }),
129
132
  );
133
+ log(`site domain: https://${domain} (Cloudflare issues the certificate on first use)`);
130
134
  } else if (previous?.siteDomain && siteUrl) {
131
135
  // The custom domain was removed from cloudhal.json: workers.dev is primary again.
132
- await setPrimaryDomain({
133
- projectDir: options.projectDir,
134
- hostname: new URL(siteUrl).hostname,
135
- ...(options.fetch ? { fetch: options.fetch } : {}),
136
- });
136
+ await retry(() =>
137
+ setPrimaryDomain({
138
+ projectDir: options.projectDir,
139
+ hostname: new URL(siteUrl).hostname,
140
+ ...(options.fetch ? { fetch: options.fetch } : {}),
141
+ }),
142
+ );
137
143
  log(
138
144
  `site domain ${previous.siteDomain} removed from cloudhal.json; if Cloudflare still lists it under the Worker's Domains & Routes, remove it there`,
139
145
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudhal/cli",
3
- "version": "0.3.9",
3
+ "version": "0.3.10",
4
4
  "description": "cloudhal — create, run and build Cloudhal sites locally",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://cloudhal.dev",
@@ -27,16 +27,16 @@
27
27
  "README.md"
28
28
  ],
29
29
  "dependencies": {
30
- "@cloudhal/agent-runtime": "0.3.9",
31
- "@cloudhal/analytics": "0.3.9",
32
- "@cloudhal/api": "0.3.9",
33
- "@cloudhal/cloudflare": "0.3.9",
34
- "@cloudhal/comments": "0.3.9",
35
- "@cloudhal/core-contracts": "0.3.9",
36
- "@cloudhal/core-ts": "0.3.9",
37
- "@cloudhal/mcp-server": "0.3.9",
38
- "@cloudhal/schedules": "0.3.9",
39
- "@cloudhal/storage": "0.3.9",
30
+ "@cloudhal/agent-runtime": "0.3.10",
31
+ "@cloudhal/analytics": "0.3.10",
32
+ "@cloudhal/api": "0.3.10",
33
+ "@cloudhal/cloudflare": "0.3.10",
34
+ "@cloudhal/comments": "0.3.10",
35
+ "@cloudhal/core-contracts": "0.3.10",
36
+ "@cloudhal/core-ts": "0.3.10",
37
+ "@cloudhal/mcp-server": "0.3.10",
38
+ "@cloudhal/schedules": "0.3.10",
39
+ "@cloudhal/storage": "0.3.10",
40
40
  "@hono/node-server": "^2.1.4",
41
41
  "better-sqlite3": "13.0.3"
42
42
  },