wrangler 4.104.0 → 4.105.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.
@@ -17921,7 +17921,7 @@ var require_snapshot_recorder = __commonJS({
17921
17921
  init_import_meta_url();
17922
17922
  var { writeFile: writeFile14, readFile: readFile19, mkdir: mkdir8 } = __require("fs/promises");
17923
17923
  var { dirname: dirname29, resolve: resolve32 } = __require("path");
17924
- var { setTimeout: setTimeout9, clearTimeout: clearTimeout2 } = __require("timers");
17924
+ var { setTimeout: setTimeout10, clearTimeout: clearTimeout2 } = __require("timers");
17925
17925
  var { InvalidArgumentError, UndiciError } = require_errors();
17926
17926
  var { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = require_snapshot_utils();
17927
17927
  function formatRequestKey(opts, headerFilters, matchOptions = {}) {
@@ -18262,7 +18262,7 @@ var require_snapshot_recorder = __commonJS({
18262
18262
  * Schedules a flush (debounced to avoid excessive writes)
18263
18263
  */
18264
18264
  #scheduleFlush() {
18265
- this.#flushTimeout = setTimeout9(() => {
18265
+ this.#flushTimeout = setTimeout10(() => {
18266
18266
  this.saveSnapshots().catch(() => {
18267
18267
  });
18268
18268
  if (this.#autoFlush) {
@@ -44488,7 +44488,7 @@ var name, version;
44488
44488
  var init_package = __esm({
44489
44489
  "package.json"() {
44490
44490
  name = "wrangler";
44491
- version = "4.104.0";
44491
+ version = "4.105.0";
44492
44492
  }
44493
44493
  });
44494
44494
 
@@ -124876,6 +124876,103 @@ Current account: "${accountId}"`
124876
124876
  }
124877
124877
  return `${url5.hostname}/${accountId}${url5.pathname}`;
124878
124878
  }
124879
+ function invalidGarCredentialError() {
124880
+ return new UserError(
124881
+ "The Google service account key must be a JSON key file or its base64-encoded form.",
124882
+ {
124883
+ telemetryMessage: "containers registries configure invalid gar credential"
124884
+ }
124885
+ );
124886
+ }
124887
+ function tryParseJson(value) {
124888
+ try {
124889
+ return JSON.parse(value);
124890
+ } catch {
124891
+ return void 0;
124892
+ }
124893
+ }
124894
+ function assertJsonObject(parsed) {
124895
+ if (typeof parsed !== "object" || parsed === null) {
124896
+ throw invalidGarCredentialError();
124897
+ }
124898
+ return parsed;
124899
+ }
124900
+ function validateServiceAccountKey(accountKey) {
124901
+ const privateKey = accountKey.private_key;
124902
+ const clientEmail = accountKey.client_email;
124903
+ const rawPrivateKeyId = accountKey.private_key_id;
124904
+ if (typeof privateKey !== "string" || typeof clientEmail !== "string") {
124905
+ throw new UserError(
124906
+ "The Google service account key is missing required fields (private_key, client_email).",
124907
+ {
124908
+ telemetryMessage: "containers registries configure gar credential missing fields"
124909
+ }
124910
+ );
124911
+ }
124912
+ if (privateKey.length === 0 || clientEmail.length === 0) {
124913
+ throw new UserError(
124914
+ "The Google service account key has an empty private_key or client_email.",
124915
+ {
124916
+ telemetryMessage: "containers registries configure gar credential empty fields"
124917
+ }
124918
+ );
124919
+ }
124920
+ let privateKeyId;
124921
+ if (rawPrivateKeyId === void 0) {
124922
+ privateKeyId = void 0;
124923
+ } else if (typeof rawPrivateKeyId === "string" && rawPrivateKeyId.length > 0) {
124924
+ privateKeyId = rawPrivateKeyId;
124925
+ } else {
124926
+ throw new UserError(
124927
+ "The Google service account key has an empty or invalid private_key_id.",
124928
+ {
124929
+ telemetryMessage: "containers registries configure gar credential invalid private key id"
124930
+ }
124931
+ );
124932
+ }
124933
+ return {
124934
+ private_key: privateKey,
124935
+ client_email: clientEmail,
124936
+ private_key_id: privateKeyId
124937
+ };
124938
+ }
124939
+ function validateAndEncodeGarKey(rawKey, expectedEmail) {
124940
+ const trimmed = rawKey.trim();
124941
+ let base64Key;
124942
+ let json2;
124943
+ const rawJson = tryParseJson(trimmed);
124944
+ if (rawJson !== void 0) {
124945
+ json2 = assertJsonObject(rawJson);
124946
+ base64Key = Buffer.from(trimmed, "utf8").toString("base64");
124947
+ } else {
124948
+ if (trimmed.startsWith("-----BEGIN")) {
124949
+ throw new UserError(
124950
+ "The provided key appears to be a PEM private key. Provide the full Google service-account JSON key file, not just the private key.",
124951
+ {
124952
+ telemetryMessage: "containers registries configure gar credential pem key"
124953
+ }
124954
+ );
124955
+ }
124956
+ base64Key = trimmed.replace(/\s+/g, "");
124957
+ const decodedJson = tryParseJson(
124958
+ Buffer.from(base64Key, "base64").toString("utf8")
124959
+ );
124960
+ if (decodedJson === void 0) {
124961
+ throw invalidGarCredentialError();
124962
+ }
124963
+ json2 = assertJsonObject(decodedJson);
124964
+ }
124965
+ const key = validateServiceAccountKey(json2);
124966
+ if (key.client_email !== expectedEmail) {
124967
+ throw new UserError(
124968
+ `The provided --gar-email "${expectedEmail}" does not match the service account email "${key.client_email}" in the key.`,
124969
+ {
124970
+ telemetryMessage: "containers registries configure gar email mismatch"
124971
+ }
124972
+ );
124973
+ }
124974
+ return base64Key;
124975
+ }
124879
124976
  var DEFAULT_CONTAINER_EGRESS_INTERCEPTOR_IMAGE, getAndValidateRegistryType;
124880
124977
  var init_images2 = __esm({
124881
124978
  "../containers-shared/src/images.ts"() {
@@ -124924,6 +125021,12 @@ ${e9.message}`);
124924
125021
  name: "DockerHub",
124925
125022
  secretType: "DockerHub PAT Token"
124926
125023
  },
125024
+ {
125025
+ type: "GAR" /* GAR */,
125026
+ pattern: /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?-docker\.pkg\.dev$/,
125027
+ name: "Google Artifact Registry",
125028
+ secretType: "Google Service Account JSON Key"
125029
+ },
124927
125030
  {
124928
125031
  type: "cloudflare",
124929
125032
  // Make a regex based on the env var CLOUDFLARE_CONTAINER_REGISTRY
@@ -124947,6 +125050,11 @@ To use an existing image from another repository, see https://developers.cloudfl
124947
125050
  }
124948
125051
  return match3;
124949
125052
  }, "getAndValidateRegistryType");
125053
+ __name(invalidGarCredentialError, "invalidGarCredentialError");
125054
+ __name(tryParseJson, "tryParseJson");
125055
+ __name(assertJsonObject, "assertJsonObject");
125056
+ __name(validateServiceAccountKey, "validateServiceAccountKey");
125057
+ __name(validateAndEncodeGarKey, "validateAndEncodeGarKey");
124950
125058
  }
124951
125059
  });
124952
125060
 
@@ -148013,61 +148121,6 @@ function errIsStartupErr(err) {
148013
148121
  }
148014
148122
  return false;
148015
148123
  }
148016
- async function verifyWorkerMatchesCITag(complianceConfig, accountId, workerName, configPath) {
148017
- const matchTag = getCIMatchTag();
148018
- logger.debug(
148019
- `Starting verifyWorkerMatchesCITag() with tag: ${matchTag}, name: ${workerName}`
148020
- );
148021
- if (!matchTag) {
148022
- logger.debug(
148023
- "No WRANGLER_CI_MATCH_TAG variable provided, aborting verifyWorkerMatchesCITag()"
148024
- );
148025
- return;
148026
- }
148027
- const envAccountID = getCloudflareAccountIdFromEnv2();
148028
- if (accountId !== envAccountID) {
148029
- throw new FatalError(
148030
- `The \`account_id\` in your ${configFileName(configPath)} file must match the \`account_id\` for this account. Please update your ${configFileName(configPath)} file with \`${formatConfigSnippet({ account_id: envAccountID }, configPath, false)}\``,
148031
- { telemetryMessage: "ci match tag account mismatch" }
148032
- );
148033
- }
148034
- let tag;
148035
- try {
148036
- const worker = await fetchResult(
148037
- complianceConfig,
148038
- `/accounts/${accountId}/workers/services/${workerName}`
148039
- );
148040
- tag = worker.default_environment.script.tag;
148041
- logger.debug(`API returned with tag: ${tag} for worker: ${workerName}`);
148042
- } catch (e9) {
148043
- logger.debug(e9);
148044
- if (isWorkerNotFoundError(e9)) {
148045
- throw new FatalError(
148046
- `The name in your ${configFileName(configPath)} file (${workerName}) must match the name of your Worker. Please update the name field in your ${configFileName(configPath)} file.`,
148047
- { telemetryMessage: "ci match tag worker not found" }
148048
- );
148049
- } else if (e9 instanceof APIError) {
148050
- throw new FatalError(
148051
- "An error occurred while trying to validate that the Worker name matches what is expected by the build system.\n" + e9.message + "\n" + e9.notes.map((note) => note.text).join("\n"),
148052
- { telemetryMessage: "ci match tag validation api error" }
148053
- );
148054
- } else {
148055
- throw new FatalError(
148056
- "Wrangler cannot validate that your Worker name matches what is expected by the build system. Please retry the build. If the problem persists, please contact support.",
148057
- { telemetryMessage: "ci match tag validation failed" }
148058
- );
148059
- }
148060
- }
148061
- if (tag !== matchTag) {
148062
- logger.debug(
148063
- `Failed to match Worker tag. The API returned "${tag}", but the CI system expected "${matchTag}"`
148064
- );
148065
- throw new FatalError(
148066
- `The name in your ${configFileName(configPath)} file (${workerName}) must match the name of your Worker. Please update the name field in your ${configFileName(configPath)} file.`,
148067
- { telemetryMessage: "ci match tag tag mismatch" }
148068
- );
148069
- }
148070
- }
148071
148124
  function validateFileSecrets(content, jsonFilePath) {
148072
148125
  if (content === null || typeof content !== "object") {
148073
148126
  throw new FatalError(
@@ -149632,6 +149685,128 @@ function lineMatchToCallSite(lineMatch) {
149632
149685
  native: isNative
149633
149686
  });
149634
149687
  }
149688
+ async function verifyWorkerMatchesCITag(complianceConfig, accountId, workerName, configPath) {
149689
+ const matchTag = getCIMatchTag();
149690
+ logger.debug(
149691
+ `Starting verifyWorkerMatchesCITag() with tag: ${matchTag}, name: ${workerName}`
149692
+ );
149693
+ if (!matchTag) {
149694
+ logger.debug(
149695
+ "No WRANGLER_CI_MATCH_TAG variable provided, aborting verifyWorkerMatchesCITag()"
149696
+ );
149697
+ return;
149698
+ }
149699
+ const envAccountID = getCloudflareAccountIdFromEnv2();
149700
+ if (accountId !== envAccountID) {
149701
+ throw new FatalError(
149702
+ `The \`account_id\` in your ${configFileName(configPath)} file must match the \`account_id\` for this account. Please update your ${configFileName(configPath)} file with \`${formatConfigSnippet({ account_id: envAccountID }, configPath, false)}\``,
149703
+ { telemetryMessage: "ci match tag account mismatch" }
149704
+ );
149705
+ }
149706
+ let tag;
149707
+ try {
149708
+ const worker = await fetchResult(
149709
+ complianceConfig,
149710
+ `/accounts/${accountId}/workers/services/${workerName}`
149711
+ );
149712
+ tag = worker.default_environment.script.tag;
149713
+ logger.debug(`API returned with tag: ${tag} for worker: ${workerName}`);
149714
+ } catch (e9) {
149715
+ logger.debug(e9);
149716
+ if (isWorkerNotFoundError(e9)) {
149717
+ throw new FatalError(
149718
+ `The name in your ${configFileName(configPath)} file (${workerName}) must match the name of your Worker. Please update the name field in your ${configFileName(configPath)} file.`,
149719
+ { telemetryMessage: "ci match tag worker not found" }
149720
+ );
149721
+ } else if (e9 instanceof APIError) {
149722
+ throw new FatalError(
149723
+ "An error occurred while trying to validate that the Worker name matches what is expected by the build system.\n" + e9.message + "\n" + e9.notes.map((note) => note.text).join("\n"),
149724
+ { telemetryMessage: "ci match tag validation api error" }
149725
+ );
149726
+ } else {
149727
+ throw new FatalError(
149728
+ "Wrangler cannot validate that your Worker name matches what is expected by the build system. Please retry the build. If the problem persists, please contact support.",
149729
+ { telemetryMessage: "ci match tag validation failed" }
149730
+ );
149731
+ }
149732
+ }
149733
+ if (tag !== matchTag) {
149734
+ logger.debug(
149735
+ `Failed to match Worker tag. The API returned "${tag}", but the CI system expected "${matchTag}"`
149736
+ );
149737
+ throw new FatalError(
149738
+ `The name in your ${configFileName(configPath)} file (${workerName}) must match the name of your Worker. Please update the name field in your ${configFileName(configPath)} file.`,
149739
+ { telemetryMessage: "ci match tag tag mismatch" }
149740
+ );
149741
+ }
149742
+ }
149743
+ async function validateWorkerProps(props, config2) {
149744
+ const { name: name2, dryRun, accountId, compatibilityDate } = props;
149745
+ const { format: format32 } = props.entry;
149746
+ if (!name2) {
149747
+ throw new UserError(
149748
+ `You need to provide the name of your worker. Either pass it as a cli arg with --name <name> or in your config file as ${formatConfigSnippet({ name: "<name>" }, config2.userConfigPath)}`,
149749
+ {
149750
+ telemetryMessage: props.command === "deploy" ? "deploy command missing worker name" : "versions upload missing worker name"
149751
+ }
149752
+ );
149753
+ }
149754
+ if (!compatibilityDate) {
149755
+ const compatibilityDateStr = getTodaysCompatDate();
149756
+ throw new UserError(
149757
+ `A compatibility_date is required when uploading a Worker. Add the following to your ${configFileName(config2.configPath)} file:
149758
+ \`\`\`
149759
+ ${formatConfigSnippet({ compatibility_date: compatibilityDateStr }, config2.configPath, false)}
149760
+ \`\`\`
149761
+ Or you could pass it in your terminal as \`--compatibility-date ${compatibilityDateStr}\`
149762
+ See https://developers.cloudflare.com/workers/platform/compatibility-dates for more information.`,
149763
+ {
149764
+ telemetryMessage: props.command === "deploy" ? "missing compatibility date when deploying" : "versions upload missing compatibility date"
149765
+ }
149766
+ );
149767
+ }
149768
+ if (config2.wasm_modules && format32 === "modules") {
149769
+ throw new UserError(
149770
+ "You cannot configure [wasm_modules] with an ES module worker. Instead, import the .wasm module directly in your code",
149771
+ { telemetryMessage: "wasm_modules with es module worker" }
149772
+ );
149773
+ }
149774
+ if (config2.text_blobs && format32 === "modules") {
149775
+ throw new UserError(
149776
+ `You cannot configure [text_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure \`[rules]\` in your ${configFileName(config2.configPath)} file`,
149777
+ { telemetryMessage: "text_blobs with es module worker" }
149778
+ );
149779
+ }
149780
+ if (config2.data_blobs && format32 === "modules") {
149781
+ throw new UserError(
149782
+ `You cannot configure [data_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure \`[rules]\` in your ${configFileName(config2.configPath)} file`,
149783
+ { telemetryMessage: "data_blobs with es module worker" }
149784
+ );
149785
+ }
149786
+ if (props.command === "deploy") {
149787
+ validateRoutes2(props.routes, props.assetsOptions);
149788
+ assert5__default.default(
149789
+ !config2.site || config2.site.bucket,
149790
+ "A [site] definition requires a `bucket` field with a path to the site's assets directory."
149791
+ );
149792
+ if (!props.isWorkersSite && Boolean(props.legacyAssetPaths) && format32 === "service-worker") {
149793
+ throw new UserError(
149794
+ "You cannot use the service-worker format with an `assets` directory yet. For information on how to migrate to the module-worker format, see: https://developers.cloudflare.com/workers/learning/migrating-to-module-workers/",
149795
+ { telemetryMessage: "deploy service worker assets unsupported" }
149796
+ );
149797
+ }
149798
+ } else {
149799
+ if (config2.containers && config2.containers.length > 0) {
149800
+ logger.warn(
149801
+ `Your Worker has Containers configured. Container configuration changes (such as image, max_instances, etc.) will not be gradually rolled out with versions. These changes will only take effect after running \`wrangler deploy\`.`
149802
+ );
149803
+ }
149804
+ }
149805
+ if (!dryRun) {
149806
+ assert5__default.default(accountId, "Missing account ID");
149807
+ await verifyWorkerMatchesCITag(config2, accountId, name2, config2.configPath);
149808
+ }
149809
+ }
149635
149810
  function addWorkersSitesBindings(bindings2, namespace, manifest, format32) {
149636
149811
  const withSites = { ...bindings2 };
149637
149812
  if (namespace) {
@@ -149649,12 +149824,6 @@ function addWorkersSitesBindings(bindings2, namespace, manifest, format32) {
149649
149824
  return withSites;
149650
149825
  }
149651
149826
  async function deploy(props, config2, buildResult, callbacks) {
149652
- if (!props.name) {
149653
- throw new UserError(
149654
- 'You need to provide a name when publishing a worker. Either pass it as a cli arg with `--name <name>` or in your config file as `name = "<name>"`',
149655
- { telemetryMessage: "deploy command missing worker name" }
149656
- );
149657
- }
149658
149827
  const {
149659
149828
  entry,
149660
149829
  name: name2,
@@ -149664,10 +149833,8 @@ async function deploy(props, config2, buildResult, callbacks) {
149664
149833
  accountId
149665
149834
  } = props;
149666
149835
  const assetsOptions = resolveAssetOptions(props, config2);
149667
- if (!props.dryRun) {
149668
- assert5__default.default(accountId, "Missing account ID");
149669
- await verifyWorkerMatchesCITag(config2, accountId, name2, config2.configPath);
149670
- }
149836
+ await validateWorkerProps({ ...props, assetsOptions }, config2);
149837
+ assert5__default.default(name2);
149671
149838
  const deployConfirm = getDeployConfirmFunction({
149672
149839
  strictMode: props.strict
149673
149840
  });
@@ -149675,7 +149842,6 @@ async function deploy(props, config2, buildResult, callbacks) {
149675
149842
  let versionId = null;
149676
149843
  let tags = [];
149677
149844
  let workerExists = true;
149678
- const allDeploymentRoutes = props.routes;
149679
149845
  if (!props.dispatchNamespace && accountId) {
149680
149846
  try {
149681
149847
  const serviceMetaData = await fetchResult(config2, `/accounts/${accountId}/workers/services/${name2}`);
@@ -149694,7 +149860,7 @@ async function deploy(props, config2, buildResult, callbacks) {
149694
149860
  const configDiff = getRemoteConfigDiff(remoteWorkerConfig, {
149695
149861
  ...config2,
149696
149862
  // We also want to include all the routes used for deployment
149697
- routes: allDeploymentRoutes
149863
+ routes: props.routes
149698
149864
  });
149699
149865
  if (!configDiff.nonDestructive) {
149700
149866
  logger.warn(
@@ -149765,24 +149931,7 @@ Edits that have been made via the script API will be overridden by your local co
149765
149931
  }
149766
149932
  }
149767
149933
  }
149768
- if (!compatibilityDate) {
149769
- const compatibilityDateStr = getTodaysCompatDate();
149770
- throw new UserError(
149771
- `A compatibility_date is required when publishing. Add the following to your ${configFileName(config2.configPath)} file:
149772
- \`\`\`
149773
- ${formatConfigSnippet({ compatibility_date: compatibilityDateStr }, config2.configPath, false)}
149774
- \`\`\`
149775
- Or you could pass it in your terminal as \`--compatibility-date ${compatibilityDateStr}\`
149776
- See https://developers.cloudflare.com/workers/platform/compatibility-dates for more information.`,
149777
- { telemetryMessage: "missing compatibility date when deploying" }
149778
- );
149779
- }
149780
- validateRoutes2(allDeploymentRoutes, assetsOptions);
149781
149934
  const scriptName = name2;
149782
- assert5__default.default(
149783
- !config2.site || config2.site.bucket,
149784
- "A [site] definition requires a `bucket` field with a path to the site's assets directory."
149785
- );
149786
149935
  const envName = props.env ?? "production";
149787
149936
  const start = Date.now();
149788
149937
  const useServiceEnvironments2 = props.useServiceEnvApiPath;
@@ -149801,30 +149950,6 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
149801
149950
  return { versionId, workerTag };
149802
149951
  }
149803
149952
  }
149804
- if (!props.isWorkersSite && Boolean(props.legacyAssetPaths) && format32 === "service-worker") {
149805
- throw new UserError(
149806
- "You cannot use the service-worker format with an `assets` directory yet. For information on how to migrate to the module-worker format, see: https://developers.cloudflare.com/workers/learning/migrating-to-module-workers/",
149807
- { telemetryMessage: "deploy service worker assets unsupported" }
149808
- );
149809
- }
149810
- if (config2.wasm_modules && format32 === "modules") {
149811
- throw new UserError(
149812
- "You cannot configure [wasm_modules] with an ES module worker. Instead, import the .wasm module directly in your code",
149813
- { telemetryMessage: "deploy wasm modules with es module worker" }
149814
- );
149815
- }
149816
- if (config2.text_blobs && format32 === "modules") {
149817
- throw new UserError(
149818
- `You cannot configure [text_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure \`[rules]\` in your ${configFileName(config2.configPath)} file`,
149819
- { telemetryMessage: "[text_blobs] with an ES module worker" }
149820
- );
149821
- }
149822
- if (config2.data_blobs && format32 === "modules") {
149823
- throw new UserError(
149824
- `You cannot configure [data_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure \`[rules]\` in your ${configFileName(config2.configPath)} file`,
149825
- { telemetryMessage: "[data_blobs] with an ES module worker" }
149826
- );
149827
- }
149828
149953
  const isDryRun = props.dryRun;
149829
149954
  const normalisedContainerConfig = callbacks.getNormalizedContainerOptions ? await callbacks.getNormalizedContainerOptions(config2, props) : [];
149830
149955
  const {
@@ -150225,7 +150350,7 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
150225
150350
  crons: props.triggers,
150226
150351
  useServiceEnvironments: useServiceEnvironments2,
150227
150352
  firstDeploy: !workerExists,
150228
- routes: allDeploymentRoutes
150353
+ routes: props.routes
150229
150354
  });
150230
150355
  logger.log("Current Version ID:", versionId);
150231
150356
  return {
@@ -150236,12 +150361,6 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
150236
150361
  };
150237
150362
  }
150238
150363
  async function versionsUpload(props, config2, buildResult, callbacks) {
150239
- if (!props.name) {
150240
- throw new UserError(
150241
- 'You need to provide a name of your worker. Either pass it as a cli arg with `--name <name>` or in your config file as `name = "<name>"`',
150242
- { telemetryMessage: "versions upload missing worker name" }
150243
- );
150244
- }
150245
150364
  const {
150246
150365
  entry,
150247
150366
  name: name2,
@@ -150251,14 +150370,12 @@ async function versionsUpload(props, config2, buildResult, callbacks) {
150251
150370
  accountId
150252
150371
  } = props;
150253
150372
  const assetsOptions = resolveAssetOptions(props, config2);
150254
- if (!props.dryRun) {
150255
- assert5__default.default(accountId, "Missing account ID");
150256
- await verifyWorkerMatchesCITag(config2, accountId, name2, config2.configPath);
150257
- }
150373
+ await validateWorkerProps(props, config2);
150374
+ assert5__default.default(name2);
150258
150375
  let versionId = null;
150259
150376
  let workerTag = null;
150260
150377
  let tags = [];
150261
- if (accountId && name2) {
150378
+ if (accountId) {
150262
150379
  try {
150263
150380
  const {
150264
150381
  default_environment: { script }
@@ -150298,56 +150415,11 @@ Edits that have been made via the API will be overridden by your local code and
150298
150415
  }
150299
150416
  }
150300
150417
  }
150301
- if (!compatibilityDate) {
150302
- const compatibilityDateStr = getTodaysCompatDate();
150303
- throw new UserError(
150304
- `A compatibility_date is required when uploading a Worker Version. Add the following to your ${configFileName(config2.configPath)} file:
150305
- \`\`\`
150306
- ${formatConfigSnippet({ compatibility_date: compatibilityDateStr }, config2.configPath, false)}
150307
- \`\`\`
150308
- Or you could pass it in your terminal as \`--compatibility-date ${compatibilityDateStr}\`
150309
- See https://developers.cloudflare.com/workers/platform/compatibility-dates for more information.`,
150310
- {
150311
- telemetryMessage: "versions upload missing compatibility date"
150312
- }
150313
- );
150314
- }
150315
150418
  const scriptName = name2;
150316
- if (config2.site && !config2.site.bucket) {
150317
- throw new UserError(
150318
- "A [site] definition requires a `bucket` field with a path to the site's assets directory.",
150319
- { telemetryMessage: "versions upload sites missing bucket" }
150320
- );
150321
- }
150322
150419
  const start = Date.now();
150323
150420
  const workerName = scriptName;
150324
150421
  const workerUrl = `/accounts/${accountId}/workers/scripts/${scriptName}`;
150325
- const { format: format32 } = entry;
150326
150422
  const projectRoot = entry.projectRoot;
150327
- if (config2.wasm_modules && format32 === "modules") {
150328
- throw new UserError(
150329
- "You cannot configure [wasm_modules] with an ES module worker. Instead, import the .wasm module directly in your code",
150330
- {
150331
- telemetryMessage: "versions upload wasm modules unsupported module worker"
150332
- }
150333
- );
150334
- }
150335
- if (config2.text_blobs && format32 === "modules") {
150336
- throw new UserError(
150337
- `You cannot configure [text_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure \`[rules]\` in your ${configFileName(config2.configPath)} file`,
150338
- {
150339
- telemetryMessage: "versions upload text blobs unsupported module worker"
150340
- }
150341
- );
150342
- }
150343
- if (config2.data_blobs && format32 === "modules") {
150344
- throw new UserError(
150345
- `You cannot configure [data_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure \`[rules]\` in your ${configFileName(config2.configPath)} file`,
150346
- {
150347
- telemetryMessage: "versions upload data blobs unsupported module worker"
150348
- }
150349
- );
150350
- }
150351
150423
  let hasPreview = false;
150352
150424
  const {
150353
150425
  modules,
@@ -150429,11 +150501,6 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
150429
150501
  cache: config2.cache
150430
150502
  // cache is a versioned setting
150431
150503
  };
150432
- if (config2.containers && config2.containers.length > 0) {
150433
- logger.warn(
150434
- `Your Worker has Containers configured. Container configuration changes (such as image, max_instances, etc.) will not be gradually rolled out with versions. These changes will only take effect after running \`wrangler deploy\`.`
150435
- );
150436
- }
150437
150504
  await printBundleSize(
150438
150505
  { name: path3__namespace.default.basename(resolvedEntryPointPath), content },
150439
150506
  modules
@@ -150560,11 +150627,7 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
150560
150627
  logger.log(`--dry-run: exiting now.`);
150561
150628
  return { versionId, workerTag };
150562
150629
  }
150563
- if (!accountId) {
150564
- throw new UserError("Missing accountId", {
150565
- telemetryMessage: "versions upload missing account id"
150566
- });
150567
- }
150630
+ assert5__default.default(accountId);
150568
150631
  const uploadMs = Date.now() - start;
150569
150632
  logger.log("Uploaded", workerName, formatTime(uploadMs));
150570
150633
  logger.log("Worker Version ID:", versionId);
@@ -150677,7 +150740,7 @@ function validateNodeCompatMode(compatibilityDateStr = "2000-01-01", compatibili
150677
150740
  }
150678
150741
  return mode;
150679
150742
  }
150680
- var import_undici4, import_command_exists2, import_dotenv, require_ignore, require_heap, require_heap2, require_difflib, require_difflib2, require_util9, require_styles2, require_has_flag2, require_supports_colors2, require_trap2, require_zalgo2, require_america2, require_zebra2, require_rainbow2, require_random2, require_colors2, require_safe2, require_colorize, require_lib4, __getOwnPropNames4, __commonJS22, __defProp5, __name22, UserError2, FatalError2, JsonFriendlyFatalError2, CharacterCodes2, ParseOptions2, ScanError2, SyntaxKind2, parse22, ParseErrorCode2, TomlError3, DATE_TIME_RE3, TomlDate3, INT_REGEX3, FLOAT_REGEX3, LEADING_ZERO3, ESCAPE_REGEX3, ESC_MAP3, KEY_PART_RE3, BARE_KEY3, dist_default5, ParseError2, units2, UNSUPPORTED_BOMS2, PATH_TO_DEPLOY_CONFIG2, esm_default5, AssetsSchema, KnownBindingSchema, UnsafeBindingSchema, BindingSchema, CacheSchema, SINGLETON_BINDING_TYPES, listFormatter, EnvSchema, ExportSchema, LimitsSchema, ObservabilitySchema, PlacementSchema, TailConsumerSchema, TriggerSchema, UnsafeSchema, BaseWorkerSchema, InputWorkerSchema, ModuleTypeSchema, ManifestSchema, require_dist2, ApplicationRollout2, BadRequestWithCodeError2, CreateApplicationRolloutRequest2, DeploymentNotFoundError2, ImageRegistryAlreadyExistsError2, ImageRegistryIsPublic2, ImageRegistryNotAllowedError2, ImageRegistryNotFoundError2, ImageRegistryProtocolAlreadyExists2, ImageRegistryProtocolIsReferencedError2, ImageRegistryProtocolNotFound2, ProvisionerConfiguration2, RolloutStep2, SecretNameAlreadyExists2, SecretNotFound2, SSHPublicKeyNotFoundError2, UpdateApplicationRolloutRequest2, runDockerCmd2, isDockerRunning2, verifyDockerInstalled2, queuesUrl, MAX_ROUTES_RULES, MAX_ROUTES_RULE_LENGTH, formatInvalidRoutes, MAX_ASSET_SIZE, CF_ASSETS_IGNORE_FILENAME, REDIRECTS_FILENAME, HEADERS_FILENAME, import_ignore, types, other_default, types2, standard_default, __classPrivateFieldGet7, _Mime_extensionToType, _Mime_typeToExtension, _Mime_typeToExtensions, Mime, Mime_default, src_default, normalizeFilePath, getContentType, hashFile, isJwtExpired, BULK_UPLOAD_CONCURRENCY, MAX_UPLOAD_ATTEMPTS, MAX_UPLOAD_GATEWAY_ERRORS, MAX_DIFF_LINES, syncAssets, buildAssetManifest, WORKER_JS_FILENAME, nameBindings, ONE_KIB_BYTES, MAX_GZIP_SIZE_BYTES, WORKER_NOT_FOUND_ERR_CODE, WORKER_LEGACY_ENVIRONMENT_NOT_FOUND_ERR_CODE, WORKFLOW_NOT_FOUND_CODE, import_json_diff, reorderableBindings, BLANK_INPUT, moduleTypeMimeType, suppressNotFoundError, esm_default22, getCloudflareAccountIdFromEnv2, isConnectedStatusExplained, ProvisionResourceHandler, R2Handler, AISearchNamespaceHandler, AgentMemoryNamespaceHandler, KVHandler, D1Handler, HANDLERS, INVALID_INHERIT_BINDING_CODE, InternalConfigSchema, StaticRoutingSchema, MetadataStaticRedirectEntry, MetadataRedirectEntry, MetadataStaticRedirects, MetadataRedirects, MetadataHeaderEntry, MetadataHeaders, RedirectsSchema, HeadersSchema, sourceMappingPrepareStackTrace, retrieveSourceMapOverride, placeholderError, CALL_SITE_REGEXP, CallSite, validateRoutes2, MAX_DNS_LABEL_LENGTH, HASH_LENGTH, ALIAS_VALIDATION_REGEX;
150743
+ var import_undici4, import_command_exists2, import_dotenv, require_ignore, require_heap, require_heap2, require_difflib, require_difflib2, require_util9, require_styles2, require_has_flag2, require_supports_colors2, require_trap2, require_zalgo2, require_america2, require_zebra2, require_rainbow2, require_random2, require_colors2, require_safe2, require_colorize, require_lib4, __getOwnPropNames4, __commonJS22, __defProp5, __name22, UserError2, FatalError2, JsonFriendlyFatalError2, CharacterCodes2, ParseOptions2, ScanError2, SyntaxKind2, parse22, ParseErrorCode2, TomlError3, DATE_TIME_RE3, TomlDate3, INT_REGEX3, FLOAT_REGEX3, LEADING_ZERO3, ESCAPE_REGEX3, ESC_MAP3, KEY_PART_RE3, BARE_KEY3, dist_default5, ParseError2, units2, UNSUPPORTED_BOMS2, PATH_TO_DEPLOY_CONFIG2, esm_default5, AssetsSchema, KnownBindingSchema, UnsafeBindingSchema, BindingSchema, CacheSchema, SINGLETON_BINDING_TYPES, listFormatter, EnvSchema, ExportSchema, LimitsSchema, ObservabilitySchema, PlacementSchema, TailConsumerSchema, TriggerSchema, UnsafeSchema, BaseWorkerSchema, InputWorkerSchema, ModuleTypeSchema, ManifestSchema, require_dist2, ApplicationRollout2, BadRequestWithCodeError2, CreateApplicationRolloutRequest2, DeploymentNotFoundError2, ImageRegistryAlreadyExistsError2, ImageRegistryIsPublic2, ImageRegistryNotAllowedError2, ImageRegistryNotFoundError2, ImageRegistryProtocolAlreadyExists2, ImageRegistryProtocolIsReferencedError2, ImageRegistryProtocolNotFound2, ProvisionerConfiguration2, RolloutStep2, SecretNameAlreadyExists2, SecretNotFound2, SSHPublicKeyNotFoundError2, UpdateApplicationRolloutRequest2, runDockerCmd2, isDockerRunning2, verifyDockerInstalled2, queuesUrl, MAX_ROUTES_RULES, MAX_ROUTES_RULE_LENGTH, formatInvalidRoutes, MAX_ASSET_SIZE, CF_ASSETS_IGNORE_FILENAME, REDIRECTS_FILENAME, HEADERS_FILENAME, import_ignore, types, other_default, types2, standard_default, __classPrivateFieldGet7, _Mime_extensionToType, _Mime_typeToExtension, _Mime_typeToExtensions, Mime, Mime_default, src_default, normalizeFilePath, getContentType, hashFile, isJwtExpired, BULK_UPLOAD_CONCURRENCY, MAX_UPLOAD_ATTEMPTS, MAX_UPLOAD_GATEWAY_ERRORS, MAX_DIFF_LINES, syncAssets, buildAssetManifest, WORKER_JS_FILENAME, nameBindings, ONE_KIB_BYTES, MAX_GZIP_SIZE_BYTES, WORKER_NOT_FOUND_ERR_CODE, WORKER_LEGACY_ENVIRONMENT_NOT_FOUND_ERR_CODE, WORKFLOW_NOT_FOUND_CODE, import_json_diff, reorderableBindings, BLANK_INPUT, moduleTypeMimeType, suppressNotFoundError, esm_default22, isConnectedStatusExplained, ProvisionResourceHandler, R2Handler, AISearchNamespaceHandler, AgentMemoryNamespaceHandler, KVHandler, D1Handler, HANDLERS, INVALID_INHERIT_BINDING_CODE, InternalConfigSchema, StaticRoutingSchema, MetadataStaticRedirectEntry, MetadataRedirectEntry, MetadataStaticRedirects, MetadataRedirects, MetadataHeaderEntry, MetadataHeaders, RedirectsSchema, HeadersSchema, sourceMappingPrepareStackTrace, retrieveSourceMapOverride, placeholderError, CALL_SITE_REGEXP, CallSite, getCloudflareAccountIdFromEnv2, validateRoutes2, MAX_DNS_LABEL_LENGTH, HASH_LENGTH, ALIAS_VALIDATION_REGEX;
150681
150744
  var init_dist9 = __esm({
150682
150745
  "../deploy-helpers/dist/index.mjs"() {
150683
150746
  init_import_meta_url();
@@ -151371,10 +151434,10 @@ var init_dist9 = __esm({
151371
151434
  require_difflib = __commonJS3({
151372
151435
  "../../node_modules/.pnpm/@ewoudenberg+difflib@0.1.0/node_modules/@ewoudenberg/difflib/lib/difflib.js"(exports2) {
151373
151436
  (function() {
151374
- var Differ, Heap, IS_CHARACTER_JUNK, IS_LINE_JUNK, SequenceMatcher, _any2, _arrayCmp, _calculateRatio, _countLeading, _formatRangeContext, _formatRangeUnified, _has, assert92, contextDiff, floor, getCloseMatches, max, min, ndiff, restore, unifiedDiff2, indexOf = [].indexOf;
151437
+ var Differ, Heap, IS_CHARACTER_JUNK, IS_LINE_JUNK, SequenceMatcher, _any2, _arrayCmp, _calculateRatio, _countLeading, _formatRangeContext, _formatRangeUnified, _has, assert102, contextDiff, floor, getCloseMatches, max, min, ndiff, restore, unifiedDiff2, indexOf = [].indexOf;
151375
151438
  ({ floor, max, min } = Math);
151376
151439
  Heap = require_heap2();
151377
- assert92 = __require3("assert");
151440
+ assert102 = __require3("assert");
151378
151441
  _calculateRatio = /* @__PURE__ */ __name3(function(matches, length) {
151379
151442
  if (length) {
151380
151443
  return 2 * matches / length;
@@ -151951,7 +152014,7 @@ var init_dist9 = __esm({
151951
152014
  }
151952
152015
  _plainReplace(a7, alo, ahi, b9, blo, bhi) {
151953
152016
  var first, g6, l7, len, len1, line, lines, m6, ref, second;
151954
- assert92(alo < ahi && blo < bhi);
152017
+ assert102(alo < ahi && blo < bhi);
151955
152018
  if (bhi - blo < ahi - alo) {
151956
152019
  first = this._dump("+", b9, blo, bhi);
151957
152020
  second = this._dump("-", a7, alo, ahi);
@@ -156464,12 +156527,6 @@ Ensure all assets in your assets directory "${dir2}" conform with the Workers ma
156464
156527
  __name3(errIsScriptSize, "errIsScriptSize");
156465
156528
  __name(errIsStartupErr, "errIsStartupErr");
156466
156529
  __name3(errIsStartupErr, "errIsStartupErr");
156467
- getCloudflareAccountIdFromEnv2 = getEnvironmentVariableFactory({
156468
- variableName: "CLOUDFLARE_ACCOUNT_ID",
156469
- deprecatedName: "CF_ACCOUNT_ID"
156470
- });
156471
- __name(verifyWorkerMatchesCITag, "verifyWorkerMatchesCITag");
156472
- __name3(verifyWorkerMatchesCITag, "verifyWorkerMatchesCITag");
156473
156530
  __name(validateFileSecrets, "validateFileSecrets");
156474
156531
  __name3(validateFileSecrets, "validateFileSecrets");
156475
156532
  (class extends Error {
@@ -157118,6 +157175,12 @@ Ensure all assets in your assets directory "${dir2}" conform with the Workers ma
157118
157175
  return null;
157119
157176
  }
157120
157177
  };
157178
+ getCloudflareAccountIdFromEnv2 = getEnvironmentVariableFactory({
157179
+ variableName: "CLOUDFLARE_ACCOUNT_ID",
157180
+ deprecatedName: "CF_ACCOUNT_ID"
157181
+ });
157182
+ __name(verifyWorkerMatchesCITag, "verifyWorkerMatchesCITag");
157183
+ __name3(verifyWorkerMatchesCITag, "verifyWorkerMatchesCITag");
157121
157184
  validateRoutes2 = /* @__PURE__ */ __name3((routes, assets) => {
157122
157185
  const invalidRoutes = {};
157123
157186
  const mountedAssetRoutes = [];
@@ -157172,6 +157235,8 @@ ${mountedAssetRoutes.map((route) => {
157172
157235
  );
157173
157236
  }
157174
157237
  }, "validateRoutes");
157238
+ __name(validateWorkerProps, "validateWorkerProps");
157239
+ __name3(validateWorkerProps, "validateWorkerProps");
157175
157240
  __name(addWorkersSitesBindings, "addWorkersSitesBindings");
157176
157241
  __name3(addWorkersSitesBindings, "addWorkersSitesBindings");
157177
157242
  __name(deploy, "deploy");
@@ -159381,7 +159446,7 @@ var init_dist10 = __esm({
159381
159446
  }
159382
159447
  });
159383
159448
 
159384
- // ../../node_modules/.pnpm/am-i-vibing@0.4.0/node_modules/am-i-vibing/dist/detector-Boc_-HQ9.mjs
159449
+ // ../../node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/detector-1yx2Hoe0.mjs
159385
159450
  function checkEnvVar(envVarDef, env7 = process.env) {
159386
159451
  const [envVar, expectedValue] = typeof envVarDef === "string" ? [envVarDef, void 0] : envVarDef;
159387
159452
  const actualValue = env7[envVar];
@@ -159455,8 +159520,8 @@ function detectAgenticEnvironment(envOrOptions, legacyAncestry) {
159455
159520
  };
159456
159521
  }
159457
159522
  var providers;
159458
- var init_detector_Boc_HQ9 = __esm({
159459
- "../../node_modules/.pnpm/am-i-vibing@0.4.0/node_modules/am-i-vibing/dist/detector-Boc_-HQ9.mjs"() {
159523
+ var init_detector_1yx2Hoe0 = __esm({
159524
+ "../../node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/detector-1yx2Hoe0.mjs"() {
159460
159525
  init_import_meta_url();
159461
159526
  init_dist10();
159462
159527
  providers = [
@@ -159638,6 +159703,12 @@ var init_detector_Boc_HQ9 = __esm({
159638
159703
  name: "Factory Droid",
159639
159704
  type: "agent",
159640
159705
  processChecks: ["droid"]
159706
+ },
159707
+ {
159708
+ id: "pi",
159709
+ name: "Pi",
159710
+ type: "agent",
159711
+ envVars: [["PI_CODING_AGENT", "true"]]
159641
159712
  }
159642
159713
  ];
159643
159714
  __name(checkEnvVar, "checkEnvVar");
@@ -159650,11 +159721,11 @@ var init_detector_Boc_HQ9 = __esm({
159650
159721
  }
159651
159722
  });
159652
159723
 
159653
- // ../../node_modules/.pnpm/am-i-vibing@0.4.0/node_modules/am-i-vibing/dist/index.mjs
159724
+ // ../../node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/index.mjs
159654
159725
  var init_dist11 = __esm({
159655
- "../../node_modules/.pnpm/am-i-vibing@0.4.0/node_modules/am-i-vibing/dist/index.mjs"() {
159726
+ "../../node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/index.mjs"() {
159656
159727
  init_import_meta_url();
159657
- init_detector_Boc_HQ9();
159728
+ init_detector_1yx2Hoe0();
159658
159729
  }
159659
159730
  });
159660
159731
  function write(p7, bytes) {
@@ -197161,6 +197232,52 @@ var init_limits2 = __esm({
197161
197232
  __name(ensureImageFitsLimits, "ensureImageFitsLimits");
197162
197233
  }
197163
197234
  });
197235
+ function getRepositoryOnly(externalAccountId, imageTag) {
197236
+ return resolveImageName(externalAccountId, imageTag).replace(DIGEST_SUFFIX_REGEXP, "").replace(TAG_SUFFIX_REGEXP, "");
197237
+ }
197238
+ function imageRefWithDigest(externalAccountId, imageTag, digest) {
197239
+ if (!DIGEST_VALUE_REGEXP.test(digest)) {
197240
+ throw new Error(
197241
+ `Expected image digest to match algorithm:hex format, got ${digest}`
197242
+ );
197243
+ }
197244
+ return `${getRepositoryOnly(externalAccountId, imageTag)}@${digest}`;
197245
+ }
197246
+ function findManifestDigest(manifestOutput) {
197247
+ const parsedManifest = JSON.parse(manifestOutput);
197248
+ const digest = parsedManifest?.Descriptor?.digest;
197249
+ if (typeof digest !== "string" || digest.length === 0) {
197250
+ throw new Error(
197251
+ `Expected docker manifest inspect output to include Descriptor.digest, got ${manifestOutput}`
197252
+ );
197253
+ }
197254
+ return digest;
197255
+ }
197256
+ function findRemoteDigest(repoDigestsJson, externalAccountId, imageTag) {
197257
+ const parsedDigests = JSON.parse(repoDigestsJson);
197258
+ if (!Array.isArray(parsedDigests)) {
197259
+ throw new Error(
197260
+ `Expected RepoDigests from docker inspect to be an array but got ${JSON.stringify(parsedDigests)}`
197261
+ );
197262
+ }
197263
+ const repositoryOnly = getRepositoryOnly(externalAccountId, imageTag);
197264
+ logger2.debug("respositoryOnly:", repositoryOnly);
197265
+ const digest = parsedDigests.find((d8) => {
197266
+ if (typeof d8 !== "string" || !d8.includes("@")) {
197267
+ return false;
197268
+ }
197269
+ const resolved = resolveImageName(externalAccountId, d8);
197270
+ logger2.debug(`Comparing ${resolved.split("@")[0]} to ${repositoryOnly}`);
197271
+ return typeof d8 === "string" && resolved.split("@")[0] === repositoryOnly;
197272
+ });
197273
+ if (!digest) {
197274
+ throw new Error(
197275
+ `Could not find a digest for the image ${repositoryOnly}. Found digests: ${parsedDigests.join(", ")}`
197276
+ );
197277
+ }
197278
+ const [, hash3] = digest.split("@");
197279
+ return imageRefWithDigest(externalAccountId, imageTag, hash3);
197280
+ }
197164
197281
  async function buildAndMaybePush(args, pathToDocker, push3, containerConfig) {
197165
197282
  try {
197166
197283
  const imageTag = args.tag;
@@ -197199,44 +197316,20 @@ async function buildAndMaybePush(args, pathToDocker, push3, containerConfig) {
197199
197316
  getCloudflareContainerRegistry()
197200
197317
  );
197201
197318
  try {
197202
- const [digests] = imageInfo.split(" ");
197203
- const parsedDigests = JSON.parse(digests);
197204
- if (!Array.isArray(parsedDigests)) {
197205
- throw new Error(
197206
- `Expected RepoDigests from docker inspect to be an array but got ${JSON.stringify(parsedDigests)}`
197207
- );
197208
- }
197209
- const imageUrl = new URL(
197210
- `http://${resolveImageName(account.external_account_id, imageTag)}`
197211
- );
197212
- const repositoryOnly = `${imageUrl.host}${imageUrl.pathname.split(":")[0]}`;
197213
- logger2.debug("respositoryOnly:", repositoryOnly);
197214
- const digest = parsedDigests.find((d8) => {
197215
- const resolved = resolveImageName(account.external_account_id, d8);
197216
- logger2.debug(
197217
- `Comparing ${resolved.split("@")[0]} to ${repositoryOnly}`
197218
- );
197219
- return typeof d8 === "string" && resolved.split("@")[0] === repositoryOnly;
197220
- });
197221
- if (!digest) {
197222
- throw new Error(
197223
- `Could not find a digest for the image ${repositoryOnly}. Found digests: ${parsedDigests.join(", ")}`
197224
- );
197225
- }
197226
- const [image, hash3] = digest.split("@");
197227
- const resolvedImage = resolveImageName(
197319
+ const remoteDigest2 = findRemoteDigest(
197320
+ imageInfo,
197228
197321
  account.external_account_id,
197229
- image
197322
+ imageTag
197230
197323
  );
197231
- const remoteDigest = `${resolvedImage}@${hash3}`;
197324
+ const [, hash3] = remoteDigest2.split("@");
197232
197325
  logger2.debug(
197233
- `'docker manifest inspect -v ${resolveImageName(account.external_account_id, remoteDigest)}:`
197326
+ `'docker manifest inspect -v ${resolveImageName(account.external_account_id, remoteDigest2)}:`
197234
197327
  );
197235
197328
  const remoteManifest = runDockerCmdWithOutput(pathToDocker, [
197236
197329
  "manifest",
197237
197330
  "inspect",
197238
197331
  "-v",
197239
- resolveImageName(account.external_account_id, remoteDigest)
197332
+ resolveImageName(account.external_account_id, remoteDigest2)
197240
197333
  ]);
197241
197334
  const parsedRemoteManifest = JSON.parse(remoteManifest);
197242
197335
  if (parsedRemoteManifest.Descriptor.digest === hash3) {
@@ -197245,7 +197338,7 @@ async function buildAndMaybePush(args, pathToDocker, push3, containerConfig) {
197245
197338
  `Untagging built image: ${args.tag} since there was no change.`
197246
197339
  );
197247
197340
  await runDockerCmd(pathToDocker, ["image", "rm", imageTag]);
197248
- return { remoteDigest };
197341
+ return { remoteDigest: remoteDigest2 };
197249
197342
  }
197250
197343
  } catch (error53) {
197251
197344
  if (error53 instanceof Error) {
@@ -197263,6 +197356,36 @@ async function buildAndMaybePush(args, pathToDocker, push3, containerConfig) {
197263
197356
  );
197264
197357
  await runDockerCmd(pathToDocker, ["tag", imageTag, namespacedImageTag]);
197265
197358
  await runDockerCmd(pathToDocker, ["push", namespacedImageTag]);
197359
+ let remoteDigest;
197360
+ try {
197361
+ const pushedImageInfo = await dockerImageInspect(pathToDocker, {
197362
+ imageTag: namespacedImageTag,
197363
+ formatString: "{{ json .RepoDigests }}"
197364
+ });
197365
+ remoteDigest = findRemoteDigest(
197366
+ pushedImageInfo,
197367
+ account.external_account_id,
197368
+ namespacedImageTag
197369
+ );
197370
+ } catch (error53) {
197371
+ if (error53 instanceof Error) {
197372
+ logger2.debug(
197373
+ `Inspecting pushed image ${namespacedImageTag} failed with error: ${error53.message}`
197374
+ );
197375
+ }
197376
+ const remoteManifest = runDockerCmdWithOutput(pathToDocker, [
197377
+ "manifest",
197378
+ "inspect",
197379
+ "-v",
197380
+ namespacedImageTag
197381
+ ]);
197382
+ remoteDigest = imageRefWithDigest(
197383
+ account.external_account_id,
197384
+ namespacedImageTag,
197385
+ findManifestDigest(remoteManifest)
197386
+ );
197387
+ }
197388
+ return { remoteDigest };
197266
197389
  }
197267
197390
  return { newTag: imageTag };
197268
197391
  } catch (error53) {
@@ -197341,7 +197464,7 @@ async function checkImagePlatform(pathToDocker, imageTag, expectedPlatform = "li
197341
197464
  );
197342
197465
  }
197343
197466
  }
197344
- var cloudchamberBuildCommand, cloudchamberPushCommand;
197467
+ var DIGEST_SUFFIX_REGEXP, DIGEST_VALUE_REGEXP, TAG_SUFFIX_REGEXP, cloudchamberBuildCommand, cloudchamberPushCommand;
197345
197468
  var init_build2 = __esm({
197346
197469
  "src/cloudchamber/build.ts"() {
197347
197470
  init_import_meta_url();
@@ -197353,6 +197476,13 @@ var init_build2 = __esm({
197353
197476
  init_common();
197354
197477
  init_limits2();
197355
197478
  init_locations7();
197479
+ DIGEST_SUFFIX_REGEXP = /@[A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*:[a-fA-F0-9]{32,}$/;
197480
+ DIGEST_VALUE_REGEXP = /^[A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*:[a-fA-F0-9]{32,}$/;
197481
+ TAG_SUFFIX_REGEXP = /:[\w][\w.-]{0,127}$/;
197482
+ __name(getRepositoryOnly, "getRepositoryOnly");
197483
+ __name(imageRefWithDigest, "imageRefWithDigest");
197484
+ __name(findManifestDigest, "findManifestDigest");
197485
+ __name(findRemoteDigest, "findRemoteDigest");
197356
197486
  __name(buildAndMaybePush, "buildAndMaybePush");
197357
197487
  __name(buildCommand, "buildCommand");
197358
197488
  __name(pushCommand, "pushCommand");
@@ -197994,7 +198124,7 @@ async function deployContainers(config2, normalisedContainerConfig, { versionId,
197994
198124
  imageRef = { newTag: container.image_uri };
197995
198125
  }
197996
198126
  if (boundDOs.has(container.class_name)) {
197997
- maybeVersionInfo ??= await fetchVersion2(
198127
+ maybeVersionInfo ??= await fetchUploadedVersion(
197998
198128
  config2,
197999
198129
  accountId,
198000
198130
  scriptName,
@@ -198040,6 +198170,19 @@ async function deployContainers(config2, normalisedContainerConfig, { versionId,
198040
198170
  }
198041
198171
  }
198042
198172
  }
198173
+ async function fetchUploadedVersion(config2, accountId, scriptName, versionId) {
198174
+ for (let attempt = 0; attempt < 5; attempt++) {
198175
+ try {
198176
+ return await fetchVersion2(config2, accountId, scriptName, versionId);
198177
+ } catch (error53) {
198178
+ if (!(error53 instanceof APIError) || error53.code !== 100146 || attempt === 4) {
198179
+ throw error53;
198180
+ }
198181
+ await timersPromises.setTimeout(500);
198182
+ }
198183
+ }
198184
+ throw new Error("Unable to fetch uploaded Worker version");
198185
+ }
198043
198186
  async function listDurableObjects(complianceConfig, accountId) {
198044
198187
  return await fetchResult2(
198045
198188
  complianceConfig,
@@ -198156,7 +198299,7 @@ async function apply(args, containerConfig, config2) {
198156
198299
  const prevApp = existingApplications.find(
198157
198300
  (app) => app.name === containerConfig.name
198158
198301
  );
198159
- const imageRef = "remoteDigest" in args.imageRef ? prevApp?.configuration.image ?? args.imageRef.remoteDigest : args.imageRef.newTag;
198302
+ const imageRef = "remoteDigest" in args.imageRef ? args.imageRef.remoteDigest : args.imageRef.newTag;
198160
198303
  log(dim("Container application changes\n"));
198161
198304
  const accountId = await getOrSelectAccountId(config2);
198162
198305
  const appConfig = mergeIfUnsafe(
@@ -198322,6 +198465,7 @@ var init_deploy = __esm({
198322
198465
  init_api2();
198323
198466
  init_containers2();
198324
198467
  __name(deployContainers, "deployContainers");
198468
+ __name(fetchUploadedVersion, "fetchUploadedVersion");
198325
198469
  __name(listDurableObjects, "listDurableObjects");
198326
198470
  __name(mergeDeep2, "mergeDeep");
198327
198471
  __name(isObject2, "isObject");
@@ -198464,8 +198608,12 @@ ${formatError2(err)}`,
198464
198608
  }, "configRolloutStepsToAPI");
198465
198609
  }
198466
198610
  });
198467
-
198468
- // src/containers/registries.ts
198611
+ function providerSpecificCredentialFlagConflicts(flagName) {
198612
+ return [
198613
+ "public-credential",
198614
+ ...providerSpecificCredentialFlagNames.filter((name2) => name2 !== flagName)
198615
+ ];
198616
+ }
198469
198617
  async function registryConfigureCommand(configureArgs, config2) {
198470
198618
  startSection("Configure a container registry");
198471
198619
  const registryType = getAndValidateRegistryType(configureArgs.DOMAIN);
@@ -198476,9 +198624,10 @@ async function registryConfigureCommand(configureArgs, config2) {
198476
198624
  endSection("No configuration required");
198477
198625
  return;
198478
198626
  }
198479
- const publicCredential = configureArgs.awsAccessKeyId ?? configureArgs.dockerhubUsername ?? configureArgs.publicCredential;
198627
+ validateProviderSpecificCredentialFlags(configureArgs, registryType.type);
198628
+ const publicCredential = configureArgs.awsAccessKeyId ?? configureArgs.dockerhubUsername ?? configureArgs.garEmail ?? configureArgs.publicCredential;
198480
198629
  if (!publicCredential) {
198481
- const arg = registryType.type === "DockerHub" /* DOCKER_HUB */ ? "dockerhub-username" : registryType.type === "ECR" /* ECR */ ? "aws-access-key-id" : "public-credential";
198630
+ const arg = registryType.type === "DockerHub" /* DOCKER_HUB */ ? "dockerhub-username" : registryType.type === "ECR" /* ECR */ ? "aws-access-key-id" : registryType.type === "GAR" /* GAR */ ? "gar-email" : "public-credential";
198482
198631
  throw new UserError(`Missing required argument: ${arg}`, {
198483
198632
  telemetryMessage: "containers registries configure missing public credential"
198484
198633
  });
@@ -198556,8 +198705,10 @@ async function registryConfigureCommand(configureArgs, config2) {
198556
198705
  if (!secretExists) {
198557
198706
  log(`Getting ${registryType.secretType}...
198558
198707
  `);
198559
- const privateCredential = await promptForRegistryPrivateCredential(
198560
- registryType.secretType
198708
+ const privateCredential = await resolvePrivateCredential(
198709
+ registryType.type,
198710
+ registryType.secretType,
198711
+ publicCredential
198561
198712
  );
198562
198713
  await promiseSpinner(
198563
198714
  createSecret(config2, accountId, secretStoreId, {
@@ -198569,6 +198720,11 @@ async function registryConfigureCommand(configureArgs, config2) {
198569
198720
  );
198570
198721
  log(
198571
198722
  `Container-scoped secret "${secretName}" created in Secrets Store.
198723
+ `
198724
+ );
198725
+ } else if (registryType.type === "GAR" /* GAR */) {
198726
+ log(
198727
+ `Reusing existing secret "${secretName}". Wrangler cannot verify it matches --gar-email "${publicCredential}"; the email is validated against the key when images are pulled.
198572
198728
  `
198573
198729
  );
198574
198730
  }
@@ -198579,8 +198735,10 @@ async function registryConfigureCommand(configureArgs, config2) {
198579
198735
  } else {
198580
198736
  log(`Getting ${registryType.secretType}...
198581
198737
  `);
198582
- private_credential = await promptForRegistryPrivateCredential(
198583
- registryType.secretType
198738
+ private_credential = await resolvePrivateCredential(
198739
+ registryType.type,
198740
+ registryType.secretType,
198741
+ publicCredential
198584
198742
  );
198585
198743
  }
198586
198744
  try {
@@ -198688,6 +198846,60 @@ async function promptForRegistryPrivateCredential(secretType) {
198688
198846
  }
198689
198847
  return secret;
198690
198848
  }
198849
+ function validateProviderSpecificCredentialFlags(configureArgs, registryType) {
198850
+ for (const flag of providerSpecificCredentialFlags) {
198851
+ if (configureArgs[flag.argName] !== void 0 && registryType !== flag.registryType) {
198852
+ throw new UserError(
198853
+ `--${flag.flagName} can only be used with ${flag.registryName}.`,
198854
+ { telemetryMessage: flag.telemetryMessage }
198855
+ );
198856
+ }
198857
+ }
198858
+ }
198859
+ async function resolvePrivateCredential(registryType, secretType, publicCredential) {
198860
+ if (registryType === "GAR" /* GAR */) {
198861
+ const rawKey = await getGarServiceAccountKey(secretType);
198862
+ return validateAndEncodeGarKey(rawKey, publicCredential);
198863
+ }
198864
+ return promptForRegistryPrivateCredential(secretType);
198865
+ }
198866
+ async function getGarServiceAccountKey(secretType) {
198867
+ if (isNonInteractiveOrCI2()) {
198868
+ const stdinInput = trimTrailingWhitespace(await readFromStdin());
198869
+ if (!stdinInput) {
198870
+ throw new UserError(
198871
+ "No input provided. In non-interactive mode, pipe the Google service account key (a file path, raw JSON, or base64) via stdin.",
198872
+ {
198873
+ telemetryMessage: "containers registries configure missing gar key input"
198874
+ }
198875
+ );
198876
+ }
198877
+ return fs11.existsSync(stdinInput) ? readGarServiceAccountKeyFile(stdinInput) : stdinInput;
198878
+ }
198879
+ const input = await prompt2(
198880
+ `Enter ${secretType ?? "secret"} (file path or base64):`,
198881
+ { isSecret: true }
198882
+ );
198883
+ if (!input) {
198884
+ throw new UserError("Secret cannot be empty.", {
198885
+ telemetryMessage: "containers registries configure empty secret"
198886
+ });
198887
+ }
198888
+ const trimmed = input.trim();
198889
+ return fs11.existsSync(trimmed) ? readGarServiceAccountKeyFile(trimmed) : input;
198890
+ }
198891
+ function readGarServiceAccountKeyFile(path84) {
198892
+ try {
198893
+ return readFileSync(path84);
198894
+ } catch {
198895
+ throw new UserError(
198896
+ `Could not read the Google service account key file at "${path84}".`,
198897
+ {
198898
+ telemetryMessage: "containers registries configure gar key file unreadable"
198899
+ }
198900
+ );
198901
+ }
198902
+ }
198691
198903
  async function registryListCommand(listArgs2) {
198692
198904
  if (!listArgs2.json && !isNonInteractiveOrCI2()) {
198693
198905
  startSection("List configured container registries");
@@ -198828,7 +199040,7 @@ async function registryCredentialsCommand(credentialsArgs) {
198828
199040
  logger2.log(credentials.password);
198829
199041
  }
198830
199042
  }
198831
- var registryConfigureArgs, registryListArgs, registryDeleteArgs, containersRegistriesNamespace, containersRegistriesConfigureCommand, containersRegistriesListCommand, containersRegistriesDeleteCommand, containersRegistriesCredentialsCommand;
199043
+ var providerSpecificCredentialFlags, providerSpecificCredentialFlagNames, registryConfigureArgs, registryListArgs, registryDeleteArgs, containersRegistriesNamespace, containersRegistriesConfigureCommand, containersRegistriesListCommand, containersRegistriesDeleteCommand, containersRegistriesCredentialsCommand;
198832
199044
  var init_registries2 = __esm({
198833
199045
  "src/containers/registries.ts"() {
198834
199046
  init_import_meta_url();
@@ -198846,6 +199058,33 @@ var init_registries2 = __esm({
198846
199058
  init_std();
198847
199059
  init_deploy();
198848
199060
  init_containers2();
199061
+ providerSpecificCredentialFlags = [
199062
+ {
199063
+ argName: "awsAccessKeyId",
199064
+ flagName: "aws-access-key-id",
199065
+ registryType: "ECR" /* ECR */,
199066
+ registryName: "AWS ECR",
199067
+ telemetryMessage: "containers registries configure aws access key id unsupported registry"
199068
+ },
199069
+ {
199070
+ argName: "dockerhubUsername",
199071
+ flagName: "dockerhub-username",
199072
+ registryType: "DockerHub" /* DOCKER_HUB */,
199073
+ registryName: "DockerHub",
199074
+ telemetryMessage: "containers registries configure dockerhub username unsupported registry"
199075
+ },
199076
+ {
199077
+ argName: "garEmail",
199078
+ flagName: "gar-email",
199079
+ registryType: "GAR" /* GAR */,
199080
+ registryName: "Google Artifact Registry",
199081
+ telemetryMessage: "containers registries configure gar email unsupported registry"
199082
+ }
199083
+ ];
199084
+ providerSpecificCredentialFlagNames = providerSpecificCredentialFlags.map(
199085
+ (flag) => flag.flagName
199086
+ );
199087
+ __name(providerSpecificCredentialFlagConflicts, "providerSpecificCredentialFlagConflicts");
198849
199088
  registryConfigureArgs = {
198850
199089
  DOMAIN: {
198851
199090
  describe: "Domain to configure for the registry",
@@ -198857,19 +199096,26 @@ var init_registries2 = __esm({
198857
199096
  demandOption: false,
198858
199097
  hidden: true,
198859
199098
  deprecated: true,
198860
- conflicts: ["dockerhub-username", "aws-access-key-id"]
199099
+ conflicts: providerSpecificCredentialFlagNames
198861
199100
  },
198862
199101
  "aws-access-key-id": {
198863
199102
  type: "string",
198864
199103
  description: "When configuring Amazon ECR, `AWS_ACCESS_KEY_ID`",
198865
199104
  demandOption: false,
198866
- conflicts: ["public-credential", "dockerhub-username"]
199105
+ conflicts: providerSpecificCredentialFlagConflicts("aws-access-key-id")
198867
199106
  },
198868
199107
  "dockerhub-username": {
198869
199108
  type: "string",
198870
199109
  description: "When configuring DockerHub, the DockerHub username",
198871
199110
  demandOption: false,
198872
- conflicts: ["public-credential", "aws-access-key-id"]
199111
+ conflicts: providerSpecificCredentialFlagConflicts("dockerhub-username")
199112
+ },
199113
+ "gar-email": {
199114
+ type: "string",
199115
+ description: "When configuring Google Artifact Registry, the Google service account email. Must match the `client_email` in the service account key.",
199116
+ demandOption: false,
199117
+ requiresArg: true,
199118
+ conflicts: providerSpecificCredentialFlagConflicts("gar-email")
198873
199119
  },
198874
199120
  "secret-store-id": {
198875
199121
  type: "string",
@@ -198900,6 +199146,10 @@ var init_registries2 = __esm({
198900
199146
  __name(promptForSecretName, "promptForSecretName");
198901
199147
  __name(resolveSecretSelection, "resolveSecretSelection");
198902
199148
  __name(promptForRegistryPrivateCredential, "promptForRegistryPrivateCredential");
199149
+ __name(validateProviderSpecificCredentialFlags, "validateProviderSpecificCredentialFlags");
199150
+ __name(resolvePrivateCredential, "resolvePrivateCredential");
199151
+ __name(getGarServiceAccountKey, "getGarServiceAccountKey");
199152
+ __name(readGarServiceAccountKeyFile, "readGarServiceAccountKeyFile");
198903
199153
  registryListArgs = {
198904
199154
  json: {
198905
199155
  type: "boolean",
@@ -232500,6 +232750,9 @@ function normalizeRelativePath(p7) {
232500
232750
  }
232501
232751
  return normalized;
232502
232752
  }
232753
+ function escapeIdentifier(id) {
232754
+ return `"${id.replace(/"/g, '""')}"`;
232755
+ }
232503
232756
  async function getMigrationsPath({
232504
232757
  projectPath,
232505
232758
  migrationsDir,
@@ -232675,6 +232928,7 @@ var init_helpers6 = __esm({
232675
232928
  __name(resolveMigrationsConfig, "resolveMigrationsConfig");
232676
232929
  __name(stripDirPrefix, "stripDirPrefix");
232677
232930
  __name(normalizeRelativePath, "normalizeRelativePath");
232931
+ __name(escapeIdentifier, "escapeIdentifier");
232678
232932
  __name(getMigrationsPath, "getMigrationsPath");
232679
232933
  __name(getUnappliedMigrations, "getUnappliedMigrations");
232680
232934
  listAppliedMigrations = /* @__PURE__ */ __name(async ({
@@ -232686,6 +232940,7 @@ var init_helpers6 = __esm({
232686
232940
  persistTo,
232687
232941
  preview
232688
232942
  }) => {
232943
+ const escapedTableName = escapeIdentifier(migrationsTableName);
232689
232944
  const response = await executeSql({
232690
232945
  local,
232691
232946
  remote,
@@ -232694,7 +232949,7 @@ var init_helpers6 = __esm({
232694
232949
  shouldPrompt: !isNonInteractiveOrCI2(),
232695
232950
  persistTo,
232696
232951
  command: `SELECT *
232697
- FROM ${migrationsTableName}
232952
+ FROM ${escapedTableName}
232698
232953
  ORDER BY id`,
232699
232954
  file: void 0,
232700
232955
  json: true,
@@ -232721,6 +232976,7 @@ var init_helpers6 = __esm({
232721
232976
  persistTo,
232722
232977
  preview
232723
232978
  }) => {
232979
+ const escapedTableName = escapeIdentifier(migrationsTableName);
232724
232980
  return executeSql({
232725
232981
  local,
232726
232982
  remote,
@@ -232728,7 +232984,7 @@ var init_helpers6 = __esm({
232728
232984
  name: name2,
232729
232985
  shouldPrompt: !isNonInteractiveOrCI2(),
232730
232986
  persistTo,
232731
- command: `CREATE TABLE IF NOT EXISTS ${migrationsTableName}(
232987
+ command: `CREATE TABLE IF NOT EXISTS ${escapedTableName}(
232732
232988
  id INTEGER PRIMARY KEY AUTOINCREMENT,
232733
232989
  name TEXT UNIQUE,
232734
232990
  applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
@@ -232870,9 +233126,12 @@ Your database may not be available to serve requests during the migration, conti
232870
233126
  `${migrationsPath}/${migration.name}`,
232871
233127
  "utf8"
232872
233128
  );
233129
+ const escapedTableName = escapeIdentifier(
233130
+ migrationsConfig.migrationsTableName
233131
+ );
232873
233132
  query += `
232874
- INSERT INTO ${migrationsConfig.migrationsTableName} (name)
232875
- values ('${migration.name}');
233133
+ INSERT INTO ${escapedTableName} (name)
233134
+ values ('${migration.name.replace(/'/g, "''")}');
232876
233135
  `;
232877
233136
  let success3 = true;
232878
233137
  let errorNotes = [];