@void/deploy-cloudflare 0.20.3 → 0.21.1
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 +12 -2
- package/dist/index.mjs +30 -7
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -107,6 +107,10 @@ type CloudflareFrameworkDeployConfig = Readonly<{
|
|
|
107
107
|
assetsIgnore?: ReadonlyArray<string>;
|
|
108
108
|
crons?: ReadonlyArray<string>;
|
|
109
109
|
requiredSecrets?: ReadonlyArray<string>;
|
|
110
|
+
ai?: Readonly<{
|
|
111
|
+
binding: string;
|
|
112
|
+
gateway?: string;
|
|
113
|
+
}>;
|
|
110
114
|
}>;
|
|
111
115
|
/**
|
|
112
116
|
* Point a standalone framework Worker at the canonical root Cloudflare state.
|
|
@@ -227,6 +231,8 @@ export declare function deployCloudflareVersionTriggers(options: {
|
|
|
227
231
|
previousTriggerConfig?: CloudflareTriggerConfig;
|
|
228
232
|
/** Wrangler skips an empty Custom Domain set, so the caller may publish it directly. */
|
|
229
233
|
publishEmptyCustomDomains?: () => Promise<CloudflareCommandResult>;
|
|
234
|
+
/** cf skips an empty Cron Trigger set, so the caller may publish it directly. */
|
|
235
|
+
publishEmptyCrons?: () => Promise<CloudflareCommandResult>;
|
|
230
236
|
manageRoutes?: boolean;
|
|
231
237
|
}): Promise<CloudflareCommandResult>;
|
|
232
238
|
type CloudflareTriggerStabilization = Readonly<{
|
|
@@ -256,10 +262,13 @@ export declare function stabilizeCloudflareVersionTriggers(options: {
|
|
|
256
262
|
previousTriggerConfig?: CloudflareTriggerConfig;
|
|
257
263
|
knownTriggerConfigs?: Readonly<Record<string, CloudflareTriggerConfig>>;
|
|
258
264
|
publishEmptyCustomDomains?: () => Promise<CloudflareCommandResult>;
|
|
265
|
+
publishEmptyCrons?: () => Promise<CloudflareCommandResult>;
|
|
259
266
|
manageRoutes?: boolean;
|
|
260
267
|
attempts?: number;
|
|
261
268
|
}): Promise<CloudflareTriggerStabilization>;
|
|
262
269
|
type CloudflareVersionActivationOptions = {
|
|
270
|
+
/** Human-readable deployment phases; the caller owns terminal rendering. */
|
|
271
|
+
onProgress?: (message: string) => void;
|
|
263
272
|
/** Reuse an inspected Worker without republishing its domains or other triggers. */
|
|
264
273
|
preserveTriggers?: boolean;
|
|
265
274
|
expectedPreviousVersionId?: string;
|
|
@@ -284,6 +293,7 @@ type CloudflareVersionActivationOptions = {
|
|
|
284
293
|
message: string;
|
|
285
294
|
/** Direct empty-domain publisher for the Wrangler reconciliation gap. */
|
|
286
295
|
publishEmptyCustomDomains?: () => Promise<CloudflareCommandResult>;
|
|
296
|
+
publishEmptyCrons?: () => Promise<CloudflareCommandResult>;
|
|
287
297
|
/** Last successfully published traffic state, newer than immutable version annotations. */
|
|
288
298
|
previousTrafficConfig?: CloudflareTrafficConfig;
|
|
289
299
|
/** Explicitly Void-owned queue consumers retained for schema-1 cleanup and failed retries. */
|
|
@@ -324,7 +334,7 @@ export declare function extractWorkersDevSubdomain(url: string): string | undefi
|
|
|
324
334
|
//#region src/metadata.d.ts
|
|
325
335
|
/**
|
|
326
336
|
* Share one authenticated transport for the activator's read-only metadata calls.
|
|
327
|
-
* Writes and unsupported commands
|
|
337
|
+
* Writes and unsupported commands use the pinned cf command adapter. Responses
|
|
328
338
|
* keep its JSON contract so activation and concurrency checks remain unchanged.
|
|
329
339
|
*/
|
|
330
340
|
export declare function createCloudflareMetadataRunner(options: {
|
|
@@ -336,7 +346,7 @@ export declare function createCloudflareMetadataRunner(options: {
|
|
|
336
346
|
getToken: () => Promise<string | null>;
|
|
337
347
|
verifyUploader: () => boolean;
|
|
338
348
|
fetch?: typeof globalThis.fetch;
|
|
339
|
-
/** Environment used to decide whether
|
|
349
|
+
/** Environment used to decide whether the CLI's proxy-aware transport is required. */
|
|
340
350
|
env?: Readonly<Record<string, string | undefined>>;
|
|
341
351
|
}): CloudflareCommandRunner;
|
|
342
352
|
//#endregion
|
package/dist/index.mjs
CHANGED
|
@@ -541,6 +541,13 @@ function writeCloudflareFrameworkDeployConfig(options) {
|
|
|
541
541
|
if (required !== void 0 && (!Array.isArray(required) || !required.every((name) => typeof name === "string"))) throw new Error("Cloudflare framework config has a malformed secrets.required field.");
|
|
542
542
|
upsert(["secrets", "required"], [.../* @__PURE__ */ new Set([...required ?? [], ...options.requiredSecrets])]);
|
|
543
543
|
}
|
|
544
|
+
if (options.ai) {
|
|
545
|
+
const config = parse(content);
|
|
546
|
+
if (config.ai === void 0) upsert(["ai"], { binding: options.ai.binding });
|
|
547
|
+
const binding = typeof config.ai?.binding === "string" ? config.ai.binding : options.ai.binding;
|
|
548
|
+
if (binding !== "AI") upsert(["vars", "__VOID_AI_BINDING"], binding);
|
|
549
|
+
if (options.ai.gateway) upsert(["vars", "__VOID_AI_GATEWAY"], options.ai.gateway);
|
|
550
|
+
}
|
|
544
551
|
let changed = content !== initial;
|
|
545
552
|
if (changed) writeFileSync(options.configPath, content);
|
|
546
553
|
const pointer = `${JSON.stringify({
|
|
@@ -790,6 +797,10 @@ async function deployCloudflareVersionTriggers(options) {
|
|
|
790
797
|
options.workerName
|
|
791
798
|
], { capture: false });
|
|
792
799
|
if (!isCleanCommandExit(deployed)) return deployed;
|
|
800
|
+
if (options.triggerConfig.crons.length === 0 && options.publishEmptyCrons) {
|
|
801
|
+
const published = await options.publishEmptyCrons();
|
|
802
|
+
if (!isCleanCommandExit(published)) return published;
|
|
803
|
+
}
|
|
793
804
|
for (const queue of removedQueueConsumers(options.triggerConfig, options.previousTriggerConfig)) {
|
|
794
805
|
const removed = await options.runWrangler([
|
|
795
806
|
"queues",
|
|
@@ -807,7 +818,7 @@ async function deployCloudflareVersionTriggers(options) {
|
|
|
807
818
|
if (!options.publishEmptyCustomDomains) return {
|
|
808
819
|
status: 1,
|
|
809
820
|
stdout: "",
|
|
810
|
-
stderr: "
|
|
821
|
+
stderr: "Cloudflare could not publish an empty Custom Domain set and no direct publisher was available."
|
|
811
822
|
};
|
|
812
823
|
const published = await options.publishEmptyCustomDomains();
|
|
813
824
|
if (!isCleanCommandExit(published)) return published;
|
|
@@ -877,6 +888,7 @@ async function stabilizeCloudflareVersionTriggers(options) {
|
|
|
877
888
|
triggerConfig: activeTriggerConfig,
|
|
878
889
|
previousTriggerConfig: cleanupBaseline,
|
|
879
890
|
publishEmptyCustomDomains: options.publishEmptyCustomDomains,
|
|
891
|
+
publishEmptyCrons: options.publishEmptyCrons,
|
|
880
892
|
manageRoutes: options.manageRoutes
|
|
881
893
|
});
|
|
882
894
|
if (!isCleanCommandExit(triggers)) return {
|
|
@@ -1109,6 +1121,7 @@ async function activateCloudflareVersionWithSecretsFile(options) {
|
|
|
1109
1121
|
ok: false,
|
|
1110
1122
|
reason: "uploader-changed"
|
|
1111
1123
|
};
|
|
1124
|
+
options.onProgress?.("Checking the current Worker deployment...");
|
|
1112
1125
|
const previous = await readCurrentProductionVersion(options, commonArgs);
|
|
1113
1126
|
if (previous.kind === "failed") return {
|
|
1114
1127
|
ok: false,
|
|
@@ -1201,6 +1214,7 @@ async function activateCloudflareVersionWithSecretsFile(options) {
|
|
|
1201
1214
|
} : versionedPreviousTriggerConfig;
|
|
1202
1215
|
const previousTriggerConfig = triggerConfigWithQueueConsumerCleanup(versionedPreviousTriggerConfigWithTraffic, options.queueConsumerCleanup);
|
|
1203
1216
|
const alias = `void-ready-${Date.now().toString(36)}`;
|
|
1217
|
+
options.onProgress?.("Uploading the Worker and assets...");
|
|
1204
1218
|
const upload = await Promise.resolve(options.runWrangler([
|
|
1205
1219
|
"versions",
|
|
1206
1220
|
"upload",
|
|
@@ -1240,6 +1254,7 @@ async function activateCloudflareVersionWithSecretsFile(options) {
|
|
|
1240
1254
|
ok: false,
|
|
1241
1255
|
reason: "upload-output-invalid"
|
|
1242
1256
|
};
|
|
1257
|
+
options.onProgress?.("Verifying the uploaded Worker...");
|
|
1243
1258
|
if (inheritanceBaseline) {
|
|
1244
1259
|
const recent = await readRecentCloudflareVersionIds(options, commonArgs);
|
|
1245
1260
|
const previousLatest = inheritanceBaseline.at(-1);
|
|
@@ -1306,6 +1321,7 @@ async function activateCloudflareVersionWithSecretsFile(options) {
|
|
|
1306
1321
|
};
|
|
1307
1322
|
stagedVersionOverride = true;
|
|
1308
1323
|
}
|
|
1324
|
+
options.onProgress?.("Waiting for the Worker to become ready...");
|
|
1309
1325
|
let ready = await probeReadiness(`${readinessUrl.replace(/\/$/, "")}/__void/ready`, options.workerName, readinessUsesCustomRoute ? void 0 : options.readinessHeaders, authenticatedWorkersDevSubdomain, stagedVersionOverride ? versionId : void 0, options.fetch ?? globalThis.fetch, options.sleep ?? defaultSleep, options.readinessAttempts ?? 6);
|
|
1310
1326
|
if (ready === "access-denied" && !stagedVersionOverride && previous.versionId !== null) {
|
|
1311
1327
|
const stableReadinessUrl = desiredTriggerConfig.workers_dev ? workersDevReadinessUrl(options.workerName, extractWorkersDevSubdomain(readinessUrl) ?? options.workersDevSubdomain) : customRouteReadinessUrl(desiredTriggerConfig.routes);
|
|
@@ -1376,6 +1392,7 @@ async function activateCloudflareVersionWithSecretsFile(options) {
|
|
|
1376
1392
|
rollback: "not-needed",
|
|
1377
1393
|
triggerRepair: "succeeded"
|
|
1378
1394
|
};
|
|
1395
|
+
options.onProgress?.("Activating the Worker...");
|
|
1379
1396
|
const activate = await deployVersionPercentages(options, commonArgs, [`${versionId}@100`], message);
|
|
1380
1397
|
if (!isCleanCommandExit(activate)) return {
|
|
1381
1398
|
ok: false,
|
|
@@ -1416,6 +1433,7 @@ async function activateCloudflareVersionWithSecretsFile(options) {
|
|
|
1416
1433
|
}
|
|
1417
1434
|
const knownTriggerConfigs = { [versionId]: desiredTriggerConfig };
|
|
1418
1435
|
if (previous.versionId && previousTriggerConfig) knownTriggerConfigs[previous.versionId] = previousTriggerConfig;
|
|
1436
|
+
options.onProgress?.("Updating routes and triggers...");
|
|
1419
1437
|
const triggers = await stabilizeCloudflareVersionTriggers({
|
|
1420
1438
|
runWrangler: options.runWrangler,
|
|
1421
1439
|
workerName: options.workerName,
|
|
@@ -1424,7 +1442,8 @@ async function activateCloudflareVersionWithSecretsFile(options) {
|
|
|
1424
1442
|
targetTriggerConfig: desiredTriggerConfig,
|
|
1425
1443
|
previousTriggerConfig,
|
|
1426
1444
|
knownTriggerConfigs,
|
|
1427
|
-
publishEmptyCustomDomains: options.publishEmptyCustomDomains
|
|
1445
|
+
publishEmptyCustomDomains: options.publishEmptyCustomDomains,
|
|
1446
|
+
publishEmptyCrons: options.publishEmptyCrons
|
|
1428
1447
|
});
|
|
1429
1448
|
if (!triggers.ok) {
|
|
1430
1449
|
if (triggers.activeVersionId && triggers.activeVersionId !== versionId) return {
|
|
@@ -1463,7 +1482,8 @@ async function activateCloudflareVersionWithSecretsFile(options) {
|
|
|
1463
1482
|
targetTriggerConfig: desiredTriggerConfig,
|
|
1464
1483
|
previousTriggerConfig,
|
|
1465
1484
|
knownTriggerConfigs,
|
|
1466
|
-
publishEmptyCustomDomains: options.publishEmptyCustomDomains
|
|
1485
|
+
publishEmptyCustomDomains: options.publishEmptyCustomDomains,
|
|
1486
|
+
publishEmptyCrons: options.publishEmptyCrons
|
|
1467
1487
|
});
|
|
1468
1488
|
return {
|
|
1469
1489
|
ok: false,
|
|
@@ -1532,7 +1552,8 @@ async function restorePreviousVersionAndTriggers(options, commonArgs, previousVe
|
|
|
1532
1552
|
targetTriggerConfig,
|
|
1533
1553
|
previousTriggerConfig: failedTriggerConfig,
|
|
1534
1554
|
knownTriggerConfigs: { [previousVersionId]: targetTriggerConfig },
|
|
1535
|
-
publishEmptyCustomDomains: options.publishEmptyCustomDomains
|
|
1555
|
+
publishEmptyCustomDomains: options.publishEmptyCustomDomains,
|
|
1556
|
+
publishEmptyCrons: options.publishEmptyCrons
|
|
1536
1557
|
});
|
|
1537
1558
|
return triggers.ok && triggers.targetOwnsTraffic ? "succeeded" : "failed";
|
|
1538
1559
|
}
|
|
@@ -1664,6 +1685,7 @@ async function bootstrapFirstDeployment(options, commonArgs, previousVersionId)
|
|
|
1664
1685
|
ok: false,
|
|
1665
1686
|
reason: "uploader-changed"
|
|
1666
1687
|
};
|
|
1688
|
+
options.onProgress?.("Publishing the first Worker deployment...");
|
|
1667
1689
|
const bootstrap = await Promise.resolve(options.runWrangler([
|
|
1668
1690
|
"deploy",
|
|
1669
1691
|
...commonArgs,
|
|
@@ -1702,6 +1724,7 @@ async function bootstrapFirstDeployment(options, commonArgs, previousVersionId)
|
|
|
1702
1724
|
...versionId ? { versionId } : {}
|
|
1703
1725
|
};
|
|
1704
1726
|
const previewUrl = publishedCloudflareUrl(options.workerName, desiredTriggerConfig, reportedOrConfiguredUrl);
|
|
1727
|
+
options.onProgress?.("Waiting for the Worker to become ready...");
|
|
1705
1728
|
const ready = await probeReadiness(`${previewUrl.replace(/\/$/, "")}/__void/ready`, options.workerName, reportedUrl || desiredTriggerConfig.workers_dev ? options.readinessHeaders : void 0, extractWorkersDevSubdomain(previewUrl), void 0, options.fetch ?? globalThis.fetch, options.sleep ?? defaultSleep, options.readinessAttempts ?? 30, 6e4);
|
|
1706
1729
|
if (ready !== "ready") return {
|
|
1707
1730
|
ok: false,
|
|
@@ -1970,7 +1993,7 @@ function defaultSleep(milliseconds) {
|
|
|
1970
1993
|
//#region src/metadata.ts
|
|
1971
1994
|
/**
|
|
1972
1995
|
* Share one authenticated transport for the activator's read-only metadata calls.
|
|
1973
|
-
* Writes and unsupported commands
|
|
1996
|
+
* Writes and unsupported commands use the pinned cf command adapter. Responses
|
|
1974
1997
|
* keep its JSON contract so activation and concurrency checks remain unchanged.
|
|
1975
1998
|
*/
|
|
1976
1999
|
function createCloudflareMetadataRunner(options) {
|
|
@@ -1985,7 +2008,7 @@ function createCloudflareMetadataRunner(options) {
|
|
|
1985
2008
|
const prefix = `${options.apiBaseUrl.replace(/\/$/, "")}/accounts/${encodeURIComponent(options.accountId)}/workers/scripts/${encodeURIComponent(options.workerName)}`;
|
|
1986
2009
|
const fetcher = options.fetch ?? globalThis.fetch;
|
|
1987
2010
|
const proxyEnv = options.env ?? process.env;
|
|
1988
|
-
const
|
|
2011
|
+
const requiresProxyTransport = Boolean(proxyEnv.https_proxy || proxyEnv.HTTPS_PROXY || proxyEnv.http_proxy || proxyEnv.HTTP_PROXY);
|
|
1989
2012
|
const refused = {
|
|
1990
2013
|
status: 1,
|
|
1991
2014
|
stdout: "",
|
|
@@ -2011,7 +2034,7 @@ function createCloudflareMetadataRunner(options) {
|
|
|
2011
2034
|
rest = args.slice(3);
|
|
2012
2035
|
}
|
|
2013
2036
|
if (!kind || !runOptions.capture || rest.length !== common.length || rest.some((value, i) => value !== common[i])) return fallback(args, runOptions);
|
|
2014
|
-
if (
|
|
2037
|
+
if (requiresProxyTransport) return fallback(args, runOptions);
|
|
2015
2038
|
let response;
|
|
2016
2039
|
try {
|
|
2017
2040
|
if (!tokenPromise && !options.verifyUploader()) return refused;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@void/deploy-cloudflare",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/voidzero-dev/void.git",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"access": "public"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@void/deploy-core": "0.
|
|
23
|
+
"@void/deploy-core": "0.21.1",
|
|
24
24
|
"jsonc-parser": "3.3.1"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|