aws-cdk 2.1140.0 → 2.1141.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/lib/index.js CHANGED
@@ -1609,8 +1609,8 @@ var require_validator = __commonJS({
1609
1609
  if (ctx.schemas[switchSchema]) {
1610
1610
  return { subschema: ctx.schemas[switchSchema], switchSchema };
1611
1611
  }
1612
- let parsed = new URL(switchSchema, "thismessage::/");
1613
- let fragment = parsed.hash;
1612
+ let hashIndex = switchSchema.indexOf("#");
1613
+ let fragment = hashIndex === -1 || hashIndex === switchSchema.length - 1 ? "" : switchSchema.substr(hashIndex);
1614
1614
  var document2 = fragment && fragment.length && switchSchema.substr(0, switchSchema.length - fragment.length);
1615
1615
  if (!document2 || !ctx.schemas[document2]) {
1616
1616
  throw new SchemaError("no such schema <" + switchSchema + ">", schema);
@@ -3695,7 +3695,7 @@ var require_semver2 = __commonJS({
3695
3695
  // ../@aws-cdk/cloud-assembly-schema/cli-version.json
3696
3696
  var require_cli_version = __commonJS({
3697
3697
  "../@aws-cdk/cloud-assembly-schema/cli-version.json"(exports2, module2) {
3698
- module2.exports = { version: "2.1140.0" };
3698
+ module2.exports = { version: "2.1141.0" };
3699
3699
  }
3700
3700
  });
3701
3701
 
@@ -46811,6 +46811,7 @@ var require_dist_cjs15 = __commonJS({
46811
46811
  if (!passiveLock) {
46812
46812
  passiveLock = chain3(options).then((c6) => {
46813
46813
  credentials = c6;
46814
+ }).catch(() => {
46814
46815
  }).finally(() => {
46815
46816
  passiveLock = void 0;
46816
46817
  });
@@ -83391,6 +83392,11 @@ var init_messages = __esm({
83391
83392
  description: "Stack Monitoring error",
83392
83393
  interface: "ErrorPayload"
83393
83394
  }),
83395
+ CDK_TOOLKIT_W5500: warn({
83396
+ code: "CDK_TOOLKIT_W5500",
83397
+ description: "Stack events could not be read; the reported event log may be incomplete",
83398
+ interface: "ErrorPayload"
83399
+ }),
83394
83400
  // 6: Rollback (6xxx)
83395
83401
  CDK_TOOLKIT_I6000: info({
83396
83402
  code: "CDK_TOOLKIT_I6000",
@@ -92912,31 +92918,6 @@ var init_template_body_parameter = __esm({
92912
92918
  }
92913
92919
  });
92914
92920
 
92915
- // ../@aws-cdk/toolkit-lib/lib/api/aws-auth/util.ts
92916
- function isAccessDeniedError(e6) {
92917
- const name = e6?.name ?? e6?.Code ?? "";
92918
- return name === "AccessDenied" || name === "AccessDeniedException";
92919
- }
92920
- function readIfPossible(filename) {
92921
- try {
92922
- if (!fs16.pathExistsSync(filename)) {
92923
- return void 0;
92924
- }
92925
- return fs16.readFileSync(filename, { encoding: "utf-8" });
92926
- } catch (e6) {
92927
- return void 0;
92928
- }
92929
- }
92930
- var fs16;
92931
- var init_util5 = __esm({
92932
- "../@aws-cdk/toolkit-lib/lib/api/aws-auth/util.ts"() {
92933
- "use strict";
92934
- fs16 = __toESM(require_lib4());
92935
- __name(isAccessDeniedError, "isAccessDeniedError");
92936
- __name(readIfPossible, "readIfPossible");
92937
- }
92938
- });
92939
-
92940
92921
  // ../@aws-cdk/toolkit-lib/lib/api/stack-events/hook-result-details.ts
92941
92922
  function formatHookResultDetails(result2) {
92942
92923
  const annotations = ("Annotations" in result2 ? result2.Annotations : void 0) ?? [];
@@ -92971,21 +92952,9 @@ async function fetchHookResultDetails(cfn, hookInvocationId, options) {
92971
92952
  return formatHookResultDetails(result2);
92972
92953
  } catch (e6) {
92973
92954
  const errorMessage = e6 instanceof Error ? e6.message : String(e6);
92974
- const isPermissionsError = isAccessDeniedError(e6) || typeof errorMessage === "string" && errorMessage.toLowerCase().includes("not authorized to perform: cloudformation:gethookresult");
92975
- if (isPermissionsError && options.envResources) {
92976
- let currentVersion = void 0;
92977
- try {
92978
- currentVersion = (await options.envResources.lookupToolkit()).version;
92979
- } catch {
92980
- }
92981
- await options.ioHelper.defaults.warn(
92982
- `Failed to fetch result details for Hook invocation ${hookInvocationId}: ${errorMessage}. Make sure you have permissions to call the GetHookResult API, or re-bootstrap your environment by running 'cdk bootstrap' to update the Bootstrap CDK Toolkit stack. Bootstrap toolkit stack version 31 or later is needed; current version: ${currentVersion ?? "unknown"}.`
92983
- );
92984
- } else {
92985
- await options.ioHelper.defaults.warn(
92986
- util4.format("Failed to fetch Hook details for invocation %s: %s", hookInvocationId, errorMessage)
92987
- );
92988
- }
92955
+ await options.ioHelper.defaults.warn(
92956
+ util4.format("Could not fetch extra detail for Hook invocation %s (%s). Run again with -v to see the full error.", hookInvocationId, errorMessage)
92957
+ );
92989
92958
  return void 0;
92990
92959
  }
92991
92960
  }
@@ -92998,7 +92967,6 @@ var init_hook_result_details = __esm({
92998
92967
  "../@aws-cdk/toolkit-lib/lib/api/stack-events/hook-result-details.ts"() {
92999
92968
  "use strict";
93000
92969
  util4 = __toESM(require("node:util"));
93001
- init_util5();
93002
92970
  __name(formatHookResultDetails, "formatHookResultDetails");
93003
92971
  __name(isFailedHookStatus, "isFailedHookStatus");
93004
92972
  __name(fetchHookResultDetails, "fetchHookResultDetails");
@@ -93590,7 +93558,6 @@ var init_stack_activity_monitor = __esm({
93590
93558
  stackDisplayName;
93591
93559
  stack;
93592
93560
  cfn;
93593
- envResources;
93594
93561
  isStackUpdate;
93595
93562
  constructor({
93596
93563
  cfn,
@@ -93600,14 +93567,12 @@ var init_stack_activity_monitor = __esm({
93600
93567
  resourcesTotal,
93601
93568
  changeSetCreationTime,
93602
93569
  pollingInterval = 2e3,
93603
- envResources,
93604
93570
  isStackUpdate = false
93605
93571
  }) {
93606
93572
  this.ioHelper = ioHelper;
93607
93573
  this.stack = stack;
93608
93574
  this.stackDisplayName = stackNameFromArn(stackArn);
93609
93575
  this.cfn = cfn;
93610
- this.envResources = envResources;
93611
93576
  this.isStackUpdate = isStackUpdate;
93612
93577
  this.progressMonitor = new StackProgressMonitor(resourcesTotal);
93613
93578
  this.pollingInterval = pollingInterval;
@@ -93675,7 +93640,6 @@ var init_stack_activity_monitor = __esm({
93675
93640
  try {
93676
93641
  this.readPromise = this.readNewEvents(this.monitorId);
93677
93642
  await this.readPromise;
93678
- this.readPromise = void 0;
93679
93643
  if (!this.monitorId) {
93680
93644
  return;
93681
93645
  }
@@ -93684,6 +93648,8 @@ var init_stack_activity_monitor = __esm({
93684
93648
  util6.format("Error occurred while monitoring stack: %s", e6),
93685
93649
  { error: e6 }
93686
93650
  ));
93651
+ } finally {
93652
+ this.readPromise = void 0;
93687
93653
  }
93688
93654
  this.scheduleNextTick();
93689
93655
  }
@@ -93705,8 +93671,7 @@ var init_stack_activity_monitor = __esm({
93705
93671
  this.progressMonitor.process(resourceEvent);
93706
93672
  if (resourceEvent.event.HookInvocationId) {
93707
93673
  const details = await fetchHookResultDetails(this.cfn, resourceEvent.event.HookInvocationId, {
93708
- ioHelper: this.ioHelper,
93709
- envResources: this.envResources
93674
+ ioHelper: this.ioHelper
93710
93675
  });
93711
93676
  if (details) {
93712
93677
  resourceEvent.event.HookStatusReason = details;
@@ -93728,10 +93693,20 @@ var init_stack_activity_monitor = __esm({
93728
93693
  * reached the last page.
93729
93694
  */
93730
93695
  async finalPollToEnd(monitorId) {
93731
- if (this.readPromise) {
93696
+ try {
93732
93697
  await this.readPromise;
93698
+ } catch {
93699
+ }
93700
+ try {
93701
+ await this.readNewEvents(monitorId);
93702
+ } catch (e6) {
93703
+ const errorName = e6 instanceof Error ? e6.name : String(e6);
93704
+ await this.ioHelper.notify(IO.CDK_TOOLKIT_W5500.msg(
93705
+ util6.format("Could not read the final stack events, the event log may be incomplete (%s). Run again with -v to see the full error.", errorName),
93706
+ { error: e6 }
93707
+ ));
93708
+ await this.ioHelper.defaults.debug(util6.format("Error occurred during final stack event poll: %s", e6));
93733
93709
  }
93734
- await this.readNewEvents(monitorId);
93735
93710
  }
93736
93711
  /**
93737
93712
  * Formats a stack activity into a basic string
@@ -94055,7 +94030,7 @@ async function getNestedStackTemplates(rootStackArtifact, nestedTemplateAssetPat
94055
94030
  const nestedStackArn = await getNestedStackArn(nestedStackLogicalId, listStackResources);
94056
94031
  const deployedStackName = nestedStackArn?.slice(nestedStackArn.indexOf("/") + 1, nestedStackArn.lastIndexOf("/"));
94057
94032
  return {
94058
- generatedTemplate: JSON.parse(fs17.readFileSync(nestedTemplatePath, "utf-8")),
94033
+ generatedTemplate: JSON.parse(fs16.readFileSync(nestedTemplatePath, "utf-8")),
94059
94034
  deployedTemplate: deployedStackName ? await loadCurrentStackTemplate(deployedStackName, sdk) : {},
94060
94035
  deployedStackName
94061
94036
  };
@@ -94074,12 +94049,12 @@ async function getNestedStackArn(nestedStackLogicalId, listStackResources) {
94074
94049
  function isCdkManagedNestedStack(stackResource) {
94075
94050
  return stackResource.Type === "AWS::CloudFormation::Stack" && stackResource.Metadata && stackResource.Metadata["aws:asset:path"];
94076
94051
  }
94077
- var path16, fs17;
94052
+ var path16, fs16;
94078
94053
  var init_nested_stack_helpers = __esm({
94079
94054
  "../@aws-cdk/toolkit-lib/lib/api/cloudformation/nested-stack-helpers.ts"() {
94080
94055
  "use strict";
94081
94056
  path16 = __toESM(require("path"));
94082
- fs17 = __toESM(require_lib4());
94057
+ fs16 = __toESM(require_lib4());
94083
94058
  init_evaluate_cloudformation_template();
94084
94059
  init_stack_helpers();
94085
94060
  init_util4();
@@ -94344,6 +94319,31 @@ var init_stack_template = __esm({
94344
94319
  }
94345
94320
  });
94346
94321
 
94322
+ // ../@aws-cdk/toolkit-lib/lib/api/aws-auth/util.ts
94323
+ function isAccessDeniedError(e6) {
94324
+ const name = e6?.name ?? e6?.Code ?? "";
94325
+ return name === "AccessDenied" || name === "AccessDeniedException";
94326
+ }
94327
+ function readIfPossible(filename) {
94328
+ try {
94329
+ if (!fs17.pathExistsSync(filename)) {
94330
+ return void 0;
94331
+ }
94332
+ return fs17.readFileSync(filename, { encoding: "utf-8" });
94333
+ } catch (e6) {
94334
+ return void 0;
94335
+ }
94336
+ }
94337
+ var fs17;
94338
+ var init_util5 = __esm({
94339
+ "../@aws-cdk/toolkit-lib/lib/api/aws-auth/util.ts"() {
94340
+ "use strict";
94341
+ fs17 = __toESM(require_lib4());
94342
+ __name(isAccessDeniedError, "isAccessDeniedError");
94343
+ __name(readIfPossible, "readIfPossible");
94344
+ }
94345
+ });
94346
+
94347
94347
  // ../@aws-cdk/toolkit-lib/lib/api/diagnosing/cloudtrail-investigation.ts
94348
94348
  async function investigateStackViaCloudTrail(sdk, errors, ioHelper) {
94349
94349
  const debug2 = /* @__PURE__ */ __name((msg) => ioHelper.defaults.debug(msg), "debug");
@@ -95625,29 +95625,31 @@ var init_stack_diagnoser = __esm({
95625
95625
  if (ev.type === "could-not-check") {
95626
95626
  await this.props.ioHelper.defaults.warn(ev.message);
95627
95627
  }
95628
- const hookErrors = await this._changeSetHookErrors(changeSet);
95628
+ let hookErrors = [];
95629
+ let warnings = [];
95630
+ try {
95631
+ hookErrors = await this._changeSetHookErrors(changeSet);
95632
+ } catch (e6) {
95633
+ const errorMessage = e6 instanceof Error ? e6.message : String(e6);
95634
+ warnings = [`Could not fetch extra hook failure detail for change set ${changeSet.ChangeSetName} (${errorMessage}). Run again with -v to see the full error.`];
95635
+ }
95629
95636
  if (hookErrors.length > 0) {
95630
95637
  return Diagnosis.problem(detectedBy, await this.enhanceErrors(hookErrors));
95631
95638
  }
95632
- return this._nonSpecificChangeSetError(changeSet, detectedBy);
95639
+ return this._nonSpecificChangeSetError(changeSet, detectedBy, warnings);
95633
95640
  }
95634
95641
  /**
95635
95642
  * Find the hooks that failed this change set, and return their failure details as resource errors.
95636
95643
  *
95637
95644
  * Failures of hooks with failure mode WARN don't fail a change set, so those are excluded.
95638
- * Returns an empty array if hook results can't be listed (e.g. for lack of permissions).
95645
+ * Throws if hook results can't be listed (e.g. lack of permissions, or the API being
95646
+ * unavailable).
95639
95647
  */
95640
95648
  async _changeSetHookErrors(changeSet) {
95641
- let hookResults;
95642
- try {
95643
- hookResults = (await this.cfn.listHookResults({
95644
- TargetType: "CHANGE_SET",
95645
- TargetId: changeSet.ChangeSetId
95646
- })).HookResults ?? [];
95647
- } catch (e6) {
95648
- await this.props.ioHelper.defaults.debug(`Could not list hook results for change set ${changeSet.ChangeSetName}: ${e6.message}`);
95649
- return [];
95650
- }
95649
+ const hookResults = (await this.cfn.listHookResults({
95650
+ TargetType: "CHANGE_SET",
95651
+ TargetId: changeSet.ChangeSetId
95652
+ })).HookResults ?? [];
95651
95653
  const failedHooks = hookResults.filter((r6) => isFailedHookStatus(r6.Status) && r6.FailureMode === "FAIL");
95652
95654
  const errors = [];
95653
95655
  for (const hook of failedHooks) {
@@ -95674,8 +95676,7 @@ var init_stack_diagnoser = __esm({
95674
95676
  async _hookResultDetails(hook) {
95675
95677
  if (hook.HookResultId) {
95676
95678
  const details = await fetchHookResultDetails(this.cfn, hook.HookResultId, {
95677
- ioHelper: this.props.ioHelper,
95678
- envResources: this.props.envResources
95679
+ ioHelper: this.props.ioHelper
95679
95680
  });
95680
95681
  if (details) {
95681
95682
  return details;
@@ -95693,7 +95694,11 @@ var init_stack_diagnoser = __esm({
95693
95694
  this.investigateResourceBestEffort(err),
95694
95695
  this.hookFailureContext(err)
95695
95696
  ]);
95696
- const allContext = [...hookContext, ...additionalContext];
95697
+ const allContext = [
95698
+ ...hookContext,
95699
+ ...additionalContext,
95700
+ ...err.warnings?.length ? [{ source: "Warnings", messages: err.warnings }] : []
95701
+ ];
95697
95702
  return {
95698
95703
  ...err,
95699
95704
  sourceTrace,
@@ -95719,8 +95724,7 @@ var init_stack_diagnoser = __esm({
95719
95724
  const ret = [];
95720
95725
  for (const hook of err.hookFailures ?? []) {
95721
95726
  let details = hook.hookInvocationId ? await fetchHookResultDetails(this.cfn, hook.hookInvocationId, {
95722
- ioHelper: this.props.ioHelper,
95723
- envResources: this.props.envResources
95727
+ ioHelper: this.props.ioHelper
95724
95728
  }) : void 0;
95725
95729
  details = details ?? (hook.hookStatusReason ? normalizeHookMessage(hook.hookStatusReason) : void 0);
95726
95730
  if (details) {
@@ -95750,8 +95754,12 @@ var init_stack_diagnoser = __esm({
95750
95754
  * Build a generic stack error from the given change set information
95751
95755
  *
95752
95756
  * We can't point to a specific resource.
95757
+ *
95758
+ * @param warnings - Warnings to attach to the error (e.g. a note that hook detail couldn't
95759
+ * be fetched). Rendered after the main failure message, instead of appearing to precede or
95760
+ * replace it.
95753
95761
  */
95754
- async _nonSpecificChangeSetError(changeSet, detectedBy) {
95762
+ async _nonSpecificChangeSetError(changeSet, detectedBy, warnings = []) {
95755
95763
  return Diagnosis.problem(detectedBy, [
95756
95764
  await this.enhanceError({
95757
95765
  // It's about a stack
@@ -95760,7 +95768,8 @@ var init_stack_diagnoser = __esm({
95760
95768
  parentStackLogicalIds: this.parentStackLogicalIds,
95761
95769
  stackArn: changeSet.StackId ?? "",
95762
95770
  physicalId: changeSet.StackId,
95763
- resourceType: "AWS::CloudFormation::Stack"
95771
+ resourceType: "AWS::CloudFormation::Stack",
95772
+ warnings
95764
95773
  })
95765
95774
  ]);
95766
95775
  }
@@ -99562,6 +99571,28 @@ function contextProperties(context) {
99562
99571
  }
99563
99572
  return parsed && typeof parsed === "object" ? parsed.Properties : void 0;
99564
99573
  }
99574
+ function propertyIsResolvedAtDeployTime(difference2) {
99575
+ return containsDeployTimeValue(difference2.oldValue) || containsDeployTimeValue(difference2.newValue);
99576
+ }
99577
+ function containsDeployTimeValue(value2) {
99578
+ if (typeof value2 === "string") {
99579
+ return value2.includes("{{resolve:");
99580
+ }
99581
+ if (Array.isArray(value2)) {
99582
+ return value2.some(containsDeployTimeValue);
99583
+ }
99584
+ if (typeof value2 === "object" && value2 !== null) {
99585
+ for (const [key, nested] of Object.entries(value2)) {
99586
+ if (key === "Ref" || key.startsWith("Fn::")) {
99587
+ return true;
99588
+ }
99589
+ if (containsDeployTimeValue(nested)) {
99590
+ return true;
99591
+ }
99592
+ }
99593
+ }
99594
+ return false;
99595
+ }
99565
99596
  var TemplateAndChangeSetDiffMerger;
99566
99597
  var init_template_and_changeset_diff_merger = __esm({
99567
99598
  "../@aws-cdk/cloudformation-diff/lib/diff/template-and-changeset-diff-merger.ts"() {
@@ -99632,6 +99663,9 @@ var init_template_and_changeset_diff_merger = __esm({
99632
99663
  change.forEachDifference((type, name, value2) => {
99633
99664
  if (type === "Property") {
99634
99665
  if (!this.changeSetResources[logicalId]) {
99666
+ if (!propertyIsResolvedAtDeployTime(value2)) {
99667
+ return;
99668
+ }
99635
99669
  value2.changeImpact = "NO_CHANGE" /* NO_CHANGE */;
99636
99670
  value2.isDifferent = false;
99637
99671
  return;
@@ -99648,6 +99682,9 @@ var init_template_and_changeset_diff_merger = __esm({
99648
99682
  value2.changeImpact = "MAY_REPLACE" /* MAY_REPLACE */;
99649
99683
  break;
99650
99684
  case void 0:
99685
+ if (!propertyIsResolvedAtDeployTime(value2)) {
99686
+ break;
99687
+ }
99651
99688
  value2.changeImpact = "NO_CHANGE" /* NO_CHANGE */;
99652
99689
  value2.isDifferent = false;
99653
99690
  break;
@@ -99898,6 +99935,8 @@ var init_template_and_changeset_diff_merger = __esm({
99898
99935
  __name(tryJsonParse, "tryJsonParse");
99899
99936
  __name(changeImpactForReplacementMode, "changeImpactForReplacementMode");
99900
99937
  __name(contextProperties, "contextProperties");
99938
+ __name(propertyIsResolvedAtDeployTime, "propertyIsResolvedAtDeployTime");
99939
+ __name(containsDeployTimeValue, "containsDeployTimeValue");
99901
99940
  }
99902
99941
  });
99903
99942
 
@@ -106994,11 +107033,11 @@ function _diffStrings(oldStr, newStr, context) {
106994
107033
  }
106995
107034
  __name(_findIndent, "_findIndent");
106996
107035
  }
106997
- var import_util24, import_chalk7, PATH_METADATA_KEY3, structuredPatch, ADDITION2, CONTEXT, UPDATE2, REMOVAL2, IMPORT, Formatter;
107036
+ var import_util23, import_chalk7, PATH_METADATA_KEY3, structuredPatch, ADDITION2, CONTEXT, UPDATE2, REMOVAL2, IMPORT, Formatter;
106998
107037
  var init_format = __esm({
106999
107038
  "../@aws-cdk/cloudformation-diff/lib/format.ts"() {
107000
107039
  "use strict";
107001
- import_util24 = require("util");
107040
+ import_util23 = require("util");
107002
107041
  import_chalk7 = __toESM(require_source());
107003
107042
  init_util6();
107004
107043
  init_diff_template();
@@ -107030,10 +107069,10 @@ var init_format = __esm({
107030
107069
  __name(this, "Formatter");
107031
107070
  }
107032
107071
  print(fmt, ...args) {
107033
- this.stream.write(import_chalk7.default.reset((0, import_util24.format)(fmt, ...args)) + "\n");
107072
+ this.stream.write(import_chalk7.default.reset((0, import_util23.format)(fmt, ...args)) + "\n");
107034
107073
  }
107035
107074
  warning(fmt, ...args) {
107036
- this.stream.write(import_chalk7.default.yellow((0, import_util24.format)(fmt, ...args)) + "\n");
107075
+ this.stream.write(import_chalk7.default.yellow((0, import_util23.format)(fmt, ...args)) + "\n");
107037
107076
  }
107038
107077
  formatSection(title, entryType, collection, formatter = this.formatDifference.bind(this)) {
107039
107078
  if (collection.differenceCount === 0) {
@@ -108809,6 +108848,8 @@ async function isHotswappableCloudControlChange(logicalId, change, evaluateCfnTe
108809
108848
  patchOps.push({ op: "remove", path: `/${propName}` });
108810
108849
  } else if (diff.isAddition) {
108811
108850
  patchOps.push({ op: "add", path: `/${propName}`, value: newValue });
108851
+ } else if (propName === "Tags" && newValue && typeof newValue === "object") {
108852
+ patchOps.push(...await buildTagPatchOps(cloudControl, resourceType, identifier, newValue));
108812
108853
  } else {
108813
108854
  patchOps.push({ op: "replace", path: `/${propName}`, value: newValue });
108814
108855
  }
@@ -108829,6 +108870,103 @@ async function isHotswappableCloudControlChange(logicalId, change, evaluateCfnTe
108829
108870
  });
108830
108871
  return ret;
108831
108872
  }
108873
+ function isReservedTagKey(key) {
108874
+ return typeof key === "string" && key.toLowerCase().startsWith("aws:");
108875
+ }
108876
+ function escapeJsonPointerToken(key) {
108877
+ return key.replace(/~/g, "~0").replace(/\//g, "~1");
108878
+ }
108879
+ async function buildTagPatchOps(cloudControl, resourceType, identifier, desiredTags) {
108880
+ const readTags = await currentResourceTags(cloudControl, resourceType, identifier);
108881
+ const desiredIsList = Array.isArray(desiredTags);
108882
+ const currentTags = readTags ?? (desiredIsList ? [] : {});
108883
+ if (desiredIsList && Array.isArray(currentTags)) {
108884
+ return buildListTagPatchOps(currentTags, desiredTags);
108885
+ }
108886
+ if (!desiredIsList && !Array.isArray(currentTags) && typeof currentTags === "object") {
108887
+ return buildMapTagPatchOps(currentTags, desiredTags);
108888
+ }
108889
+ throw new ToolkitError(
108890
+ "HotswapTagReadFailed",
108891
+ `could not interpret the current tags of ${identifier} (${resourceType}): the resource reports Tags as ${describeTagsShape(currentTags)} but the template declares ${describeTagsShape(desiredTags)}`
108892
+ );
108893
+ }
108894
+ function describeTagsShape(tags) {
108895
+ if (Array.isArray(tags)) {
108896
+ return "a list";
108897
+ }
108898
+ if (tags === null) {
108899
+ return "null";
108900
+ }
108901
+ if (typeof tags === "object") {
108902
+ return "a map";
108903
+ }
108904
+ return typeof tags;
108905
+ }
108906
+ function buildMapTagPatchOps(currentTags, desiredTags) {
108907
+ const ops = [];
108908
+ for (const [key, value2] of Object.entries(desiredTags)) {
108909
+ const path54 = `/Tags/${escapeJsonPointerToken(key)}`;
108910
+ if (!Object.hasOwn(currentTags, key)) {
108911
+ ops.push({ op: "add", path: path54, value: value2 });
108912
+ } else if (JSON.stringify(currentTags[key]) !== JSON.stringify(value2)) {
108913
+ ops.push({ op: "replace", path: path54, value: value2 });
108914
+ }
108915
+ }
108916
+ for (const key of Object.keys(currentTags)) {
108917
+ if (!Object.hasOwn(desiredTags, key) && !isReservedTagKey(key)) {
108918
+ ops.push({ op: "remove", path: `/Tags/${escapeJsonPointerToken(key)}` });
108919
+ }
108920
+ }
108921
+ return ops;
108922
+ }
108923
+ function buildListTagPatchOps(currentTags, desiredTags) {
108924
+ const isTag = /* @__PURE__ */ __name((tag) => tag && typeof tag === "object" && typeof tag.Key === "string", "isTag");
108925
+ const indexByKey = /* @__PURE__ */ new Map();
108926
+ currentTags.forEach((tag, i6) => {
108927
+ if (isTag(tag) && !indexByKey.has(tag.Key)) {
108928
+ indexByKey.set(tag.Key, i6);
108929
+ }
108930
+ });
108931
+ const replacements = [];
108932
+ const additions = [];
108933
+ for (const tag of desiredTags) {
108934
+ if (!isTag(tag)) {
108935
+ continue;
108936
+ }
108937
+ const index = indexByKey.get(tag.Key);
108938
+ if (index === void 0) {
108939
+ additions.push({ op: "add", path: "/Tags/-", value: tag });
108940
+ } else if (JSON.stringify(currentTags[index]) !== JSON.stringify(tag)) {
108941
+ replacements.push({ op: "replace", path: `/Tags/${index}`, value: tag });
108942
+ }
108943
+ }
108944
+ const desiredKeys = new Set(desiredTags.filter(isTag).map((tag) => tag.Key));
108945
+ const removals = currentTags.map((tag, i6) => ({ tag, i: i6 })).filter(({ tag }) => isTag(tag) && !desiredKeys.has(tag.Key) && !isReservedTagKey(tag.Key)).sort((a6, b6) => b6.i - a6.i).map(({ i: i6 }) => ({ op: "remove", path: `/Tags/${i6}` }));
108946
+ return [...replacements, ...removals, ...additions];
108947
+ }
108948
+ async function currentResourceTags(cloudControl, resourceType, identifier) {
108949
+ const unreadable = /* @__PURE__ */ __name((cause) => ToolkitError.withCause(
108950
+ "HotswapTagReadFailed",
108951
+ `could not read the current tags of ${identifier} (${resourceType}), which are needed to update tags without removing the reserved aws: tags that AWS manages - ensure the deployment role is allowed to call cloudcontrolapi:GetResource for this resource type`,
108952
+ cause
108953
+ ), "unreadable");
108954
+ let current;
108955
+ try {
108956
+ current = await cloudControl.getResource({ TypeName: resourceType, Identifier: identifier });
108957
+ } catch (e6) {
108958
+ throw unreadable(e6);
108959
+ }
108960
+ const properties = current.ResourceDescription?.Properties;
108961
+ if (!properties) {
108962
+ throw unreadable(new Error("GetResource returned no resource properties"));
108963
+ }
108964
+ try {
108965
+ return JSON.parse(properties).Tags;
108966
+ } catch (e6) {
108967
+ throw unreadable(e6);
108968
+ }
108969
+ }
108832
108970
  async function resolveCloudControlIdentifier(logicalId, resourceType, evaluateCfnTemplate) {
108833
108971
  const cfnPhysicalId = await evaluateCfnTemplate.findPhysicalNameFor(logicalId);
108834
108972
  if (!cfnPhysicalId) {
@@ -108844,6 +108982,13 @@ var init_cloud_control_resource = __esm({
108844
108982
  init_toolkit_error();
108845
108983
  init_cloudformation2();
108846
108984
  __name(isHotswappableCloudControlChange, "isHotswappableCloudControlChange");
108985
+ __name(isReservedTagKey, "isReservedTagKey");
108986
+ __name(escapeJsonPointerToken, "escapeJsonPointerToken");
108987
+ __name(buildTagPatchOps, "buildTagPatchOps");
108988
+ __name(describeTagsShape, "describeTagsShape");
108989
+ __name(buildMapTagPatchOps, "buildMapTagPatchOps");
108990
+ __name(buildListTagPatchOps, "buildListTagPatchOps");
108991
+ __name(currentResourceTags, "currentResourceTags");
108847
108992
  __name(resolveCloudControlIdentifier, "resolveCloudControlIdentifier");
108848
108993
  }
108849
108994
  });
@@ -109291,7 +109436,7 @@ async function applyHotswapOperation(sdk, ioSpan, hotswapOperation) {
109291
109436
  sdk.appendCustomUserAgent(customUserAgent);
109292
109437
  const resourceText = /* @__PURE__ */ __name((r6) => r6.description ?? `${r6.resourceType} '${r6.physicalName ?? r6.logicalId}'`, "resourceText");
109293
109438
  await ioSpan.notify(IO.CDK_TOOLKIT_I5402.msg(
109294
- hotswapOperation.change.resources.map((r6) => (0, import_util30.format)(` ${ICON} %s`, import_chalk10.default.bold(resourceText(r6)))).join("\n"),
109439
+ hotswapOperation.change.resources.map((r6) => (0, import_util29.format)(` ${ICON} %s`, import_chalk10.default.bold(resourceText(r6)))).join("\n"),
109295
109440
  hotswapOperation.change
109296
109441
  ));
109297
109442
  try {
@@ -109306,7 +109451,7 @@ async function applyHotswapOperation(sdk, ioSpan, hotswapOperation) {
109306
109451
  throw e6;
109307
109452
  }
109308
109453
  await ioSpan.notify(IO.CDK_TOOLKIT_I5403.msg(
109309
- hotswapOperation.change.resources.map((r6) => (0, import_util30.format)(` ${ICON} %s %s`, import_chalk10.default.bold(resourceText(r6)), import_chalk10.default.green("hotswapped!"))).join("\n"),
109454
+ hotswapOperation.change.resources.map((r6) => (0, import_util29.format)(` ${ICON} %s %s`, import_chalk10.default.bold(resourceText(r6)), import_chalk10.default.green("hotswapped!"))).join("\n"),
109310
109455
  hotswapOperation.change
109311
109456
  ));
109312
109457
  sdk.removeCustomUserAgent(customUserAgent);
@@ -109335,9 +109480,9 @@ async function logRejectedChanges(ioSpan, rejectedChanges, hotswapMode) {
109335
109480
  }
109336
109481
  const messages = [""];
109337
109482
  if (hotswapMode === "hotswap-only") {
109338
- messages.push((0, import_util30.format)("%s %s", import_chalk10.default.red("\u26A0\uFE0F"), import_chalk10.default.red("The following non-hotswappable changes were found. To reconcile these using CloudFormation, specify --hotswap-fallback")));
109483
+ messages.push((0, import_util29.format)("%s %s", import_chalk10.default.red("\u26A0\uFE0F"), import_chalk10.default.red("The following non-hotswappable changes were found. To reconcile these using CloudFormation, specify --hotswap-fallback")));
109339
109484
  } else {
109340
- messages.push((0, import_util30.format)("%s %s", import_chalk10.default.red("\u26A0\uFE0F"), import_chalk10.default.red("The following non-hotswappable changes were found:")));
109485
+ messages.push((0, import_util29.format)("%s %s", import_chalk10.default.red("\u26A0\uFE0F"), import_chalk10.default.red("The following non-hotswappable changes were found:")));
109341
109486
  }
109342
109487
  for (const { change } of rejectedChanges) {
109343
109488
  messages.push(" " + nonHotswappableChangeMessage(change));
@@ -109350,7 +109495,7 @@ function nonHotswappableChangeMessage(change) {
109350
109495
  const reason = change.description ?? change.reason;
109351
109496
  switch (subject.type) {
109352
109497
  case "Output":
109353
- return (0, import_util30.format)(
109498
+ return (0, import_util29.format)(
109354
109499
  "output: %s, reason: %s",
109355
109500
  import_chalk10.default.bold(subject.logicalId),
109356
109501
  import_chalk10.default.red(reason)
@@ -109361,7 +109506,7 @@ function nonHotswappableChangeMessage(change) {
109361
109506
  }
109362
109507
  function nonHotswappableResourceMessage(subject, reason) {
109363
109508
  if (subject.rejectedProperties?.length) {
109364
- return (0, import_util30.format)(
109509
+ return (0, import_util29.format)(
109365
109510
  "resource: %s, type: %s, rejected changes: %s, reason: %s",
109366
109511
  import_chalk10.default.bold(subject.logicalId),
109367
109512
  import_chalk10.default.bold(subject.resourceType),
@@ -109369,18 +109514,18 @@ function nonHotswappableResourceMessage(subject, reason) {
109369
109514
  import_chalk10.default.red(reason)
109370
109515
  );
109371
109516
  }
109372
- return (0, import_util30.format)(
109517
+ return (0, import_util29.format)(
109373
109518
  "resource: %s, type: %s, reason: %s",
109374
109519
  import_chalk10.default.bold(subject.logicalId),
109375
109520
  import_chalk10.default.bold(subject.resourceType),
109376
109521
  import_chalk10.default.red(reason)
109377
109522
  );
109378
109523
  }
109379
- var import_util30, cfn_diff, import_chalk10, pLimit2, RESOURCE_DETECTORS;
109524
+ var import_util29, cfn_diff, import_chalk10, pLimit2, RESOURCE_DETECTORS;
109380
109525
  var init_hotswap_deployments = __esm({
109381
109526
  "../@aws-cdk/toolkit-lib/lib/api/hotswap/hotswap-deployments.ts"() {
109382
109527
  "use strict";
109383
- import_util30 = require("util");
109528
+ import_util29 = require("util");
109384
109529
  cfn_diff = __toESM(require_lib9());
109385
109530
  import_chalk10 = __toESM(require_source());
109386
109531
  init_payloads();
@@ -110751,11 +110896,11 @@ var init_notices2 = __esm({
110751
110896
  });
110752
110897
 
110753
110898
  // ../@aws-cdk/toolkit-lib/lib/api/toolkit-info.ts
110754
- var import_util36, import_chalk12, DEFAULT_TOOLKIT_STACK_NAME, ToolkitInfo, ExistingToolkitInfo, BootstrapStackNotFoundInfo;
110899
+ var import_util35, import_chalk12, DEFAULT_TOOLKIT_STACK_NAME, ToolkitInfo, ExistingToolkitInfo, BootstrapStackNotFoundInfo;
110755
110900
  var init_toolkit_info = __esm({
110756
110901
  "../@aws-cdk/toolkit-lib/lib/api/toolkit-info.ts"() {
110757
110902
  "use strict";
110758
- import_util36 = require("util");
110903
+ import_util35 = require("util");
110759
110904
  import_chalk12 = __toESM(require_source());
110760
110905
  init_bootstrap_props();
110761
110906
  init_toolkit_error();
@@ -110775,7 +110920,7 @@ var init_toolkit_info = __esm({
110775
110920
  const stack = await stabilizeStack(cfn, ioHelper, stackName);
110776
110921
  if (!stack) {
110777
110922
  await ioHelper.defaults.debug(
110778
- (0, import_util36.format)(
110923
+ (0, import_util35.format)(
110779
110924
  "The environment %s doesn't have the CDK toolkit stack (%s) installed. Use %s to setup your environment for use with the toolkit.",
110780
110925
  environment.name,
110781
110926
  stackName,
@@ -110786,7 +110931,7 @@ var init_toolkit_info = __esm({
110786
110931
  }
110787
110932
  if (stack.stackStatus.isCreationFailure) {
110788
110933
  await ioHelper.defaults.debug(
110789
- (0, import_util36.format)(
110934
+ (0, import_util35.format)(
110790
110935
  "The environment %s has a CDK toolkit stack (%s) that failed to create. Use %s to try provisioning it again.",
110791
110936
  environment.name,
110792
110937
  stackName,
@@ -284523,7 +284668,10 @@ function makeSdkLoggerSafeByBindingThis(logger2) {
284523
284668
  };
284524
284669
  }
284525
284670
  function cappedExponentialBackoff(baseMs, capMs) {
284526
- return (attempt) => Math.min(baseMs * 2 ** attempt, capMs);
284671
+ return (attempt) => {
284672
+ const delay = Math.min(baseMs * 2 ** attempt, capMs);
284673
+ return Math.floor(delay / 2 + Math.random() * (delay / 2));
284674
+ };
284527
284675
  }
284528
284676
  var import_client_appsync, import_client_bedrock_agentcore_control, import_client_cloudcontrol, import_client_cloudformation6, import_client_cloudtrail, import_client_cloudwatch_logs, import_client_codebuild, import_client_ec2, import_client_ecr2, import_client_ecs, import_client_elastic_load_balancing_v2, import_client_iam, import_client_kms, import_client_lambda, import_client_route_53, import_client_s33, import_client_secrets_manager2, import_client_sfn, import_client_ssm, import_client_sts2, import_lib_storage2, import_middleware_endpoint2, import_util_retry, SDK, CURRENT_ACCOUNT_KEY;
284529
284677
  var init_sdk2 = __esm({
@@ -285552,7 +285700,7 @@ async function v3ProviderFromPlugin(producer) {
285552
285700
  } else if (isV2Credentials(initial)) {
285553
285701
  return v3ProviderFromV2Credentials(initial);
285554
285702
  } else {
285555
- throw new AuthenticationError("InvalidPluginCredentials", `Plugin returned a value that doesn't resemble AWS credentials: ${(0, import_util46.inspect)(initial)}`);
285703
+ throw new AuthenticationError("InvalidPluginCredentials", `Plugin returned a value that doesn't resemble AWS credentials: ${(0, import_util45.inspect)(initial)}`);
285556
285704
  }
285557
285705
  }
285558
285706
  function v3ProviderFromV2Credentials(x) {
@@ -285571,7 +285719,7 @@ function refreshFromPluginProvider(current, producer) {
285571
285719
  if (credentialsAboutToExpire(current)) {
285572
285720
  const newCreds = await producer();
285573
285721
  if (!isV3Credentials(newCreds)) {
285574
- throw new AuthenticationError("PluginCredentialTypeMismatch", `Plugin initially returned static V3 credentials but now returned something else: ${(0, import_util46.inspect)(newCreds)}`);
285722
+ throw new AuthenticationError("PluginCredentialTypeMismatch", `Plugin initially returned static V3 credentials but now returned something else: ${(0, import_util45.inspect)(newCreds)}`);
285575
285723
  }
285576
285724
  current = newCreds;
285577
285725
  }
@@ -285587,11 +285735,11 @@ function isV2Credentials(x) {
285587
285735
  function isV3Credentials(x) {
285588
285736
  return !!(x && typeof x === "object" && x.accessKeyId && !isV2Credentials(x));
285589
285737
  }
285590
- var import_util46, CredentialPlugins;
285738
+ var import_util45, CredentialPlugins;
285591
285739
  var init_credential_plugins = __esm({
285592
285740
  "../@aws-cdk/toolkit-lib/lib/api/aws-auth/credential-plugins.ts"() {
285593
285741
  "use strict";
285594
- import_util46 = require("util");
285742
+ import_util45 = require("util");
285595
285743
  init_provider_caching();
285596
285744
  init_toolkit_error();
285597
285745
  init_util4();
@@ -285990,7 +286138,7 @@ function formatSdkLoggerContent(content) {
285990
286138
  return apiFmt;
285991
286139
  }
285992
286140
  }
285993
- return content.map((x) => typeof x === "string" ? x : (0, import_util49.inspect)(x)).join("");
286141
+ return content.map((x) => typeof x === "string" ? x : (0, import_util48.inspect)(x)).join("");
285994
286142
  }
285995
286143
  function formatApiCall(content) {
285996
286144
  if (!isSdkApiCallSuccess(content) && !isSdkApiCallError(content)) {
@@ -286016,11 +286164,11 @@ function isSdkApiCallSuccess(x) {
286016
286164
  function isSdkApiCallError(x) {
286017
286165
  return x && typeof x === "object" && x.commandName && x.error;
286018
286166
  }
286019
- var import_util49, IoHostSdkLogger;
286167
+ var import_util48, IoHostSdkLogger;
286020
286168
  var init_sdk_logger = __esm({
286021
286169
  "../@aws-cdk/toolkit-lib/lib/api/aws-auth/sdk-logger.ts"() {
286022
286170
  "use strict";
286023
- import_util49 = require("util");
286171
+ import_util48 = require("util");
286024
286172
  init_util4();
286025
286173
  init_private();
286026
286174
  IoHostSdkLogger = class {
@@ -286032,7 +286180,7 @@ var init_sdk_logger = __esm({
286032
286180
  this.ioHelper = ioHelper;
286033
286181
  }
286034
286182
  notify(level, ...content) {
286035
- void this.ioHelper.notify(IO.CDK_SDK_I0100.msg((0, import_util49.format)("[SDK %s] %s", level, formatSdkLoggerContent(content)), {
286183
+ void this.ioHelper.notify(IO.CDK_SDK_I0100.msg((0, import_util48.format)("[SDK %s] %s", level, formatSdkLoggerContent(content)), {
286036
286184
  sdkLevel: level,
286037
286185
  content
286038
286186
  }));
@@ -290793,6 +290941,12 @@ function quoteShellPart(part) {
290793
290941
  return part;
290794
290942
  }
290795
290943
  if (isWindows2) {
290944
+ if (/%[^%]*%/.test(part)) {
290945
+ throw new ToolkitError(
290946
+ "UnsafeWindowsPath",
290947
+ `Cannot safely run a path containing a '%...%' substring through the Windows shell: '${part}'. Rename the file or directory to remove the percent signs.`
290948
+ );
290949
+ }
290796
290950
  return `"${part}"`;
290797
290951
  }
290798
290952
  return `"${part.replace(/([\\"$`])/g, "\\$1")}"`;
@@ -290804,6 +290958,7 @@ var init_environment3 = __esm({
290804
290958
  path29 = __toESM(require("path"));
290805
290959
  cxapi4 = __toESM(require_lib11());
290806
290960
  fs28 = __toESM(require_lib4());
290961
+ init_toolkit_error();
290807
290962
  __name(prepareDefaultEnvironment, "prepareDefaultEnvironment");
290808
290963
  __name(contextFromSettings, "contextFromSettings");
290809
290964
  __name(synthParametersFromSettings, "synthParametersFromSettings");
@@ -291109,12 +291264,12 @@ var init_readable_assembly = __esm({
291109
291264
  });
291110
291265
 
291111
291266
  // ../@aws-cdk/toolkit-lib/lib/api/cloud-assembly/source-builder.ts
291112
- var path31, import_util54, cxapi6, fs31, CloudAssemblySourceBuilder;
291267
+ var path31, import_util53, cxapi6, fs31, CloudAssemblySourceBuilder;
291113
291268
  var init_source_builder = __esm({
291114
291269
  "../@aws-cdk/toolkit-lib/lib/api/cloud-assembly/source-builder.ts"() {
291115
291270
  "use strict";
291116
291271
  path31 = __toESM(require("path"));
291117
- import_util54 = require("util");
291272
+ import_util53 = require("util");
291118
291273
  cxapi6 = __toESM(require_lib3());
291119
291274
  fs31 = __toESM(require_lib4());
291120
291275
  init_context_store();
@@ -291180,7 +291335,7 @@ var init_source_builder = __esm({
291180
291335
  ...await contextStore.read(),
291181
291336
  ...synthParams.context
291182
291337
  };
291183
- await services.ioHelper.defaults.debug((0, import_util54.format)("context:", fullContext));
291338
+ await services.ioHelper.defaults.debug((0, import_util53.format)("context:", fullContext));
291184
291339
  const env3 = noUndefined({
291185
291340
  // Versioning, outdir, default account and region
291186
291341
  ...await execution.defaultEnvVars(),
@@ -291319,7 +291474,7 @@ var init_source_builder = __esm({
291319
291474
  ...await contextStore.read(),
291320
291475
  ...synthParams.context
291321
291476
  };
291322
- await services.ioHelper.defaults.debug((0, import_util54.format)("context:", fullContext));
291477
+ await services.ioHelper.defaults.debug((0, import_util53.format)("context:", fullContext));
291323
291478
  const env3 = noUndefined({
291324
291479
  // Need to start with full env of `writeContextToEnv` will not be able to do the size
291325
291480
  // calculation correctly.
@@ -291520,6 +291675,21 @@ var init_stack_collection = __esm({
291520
291675
  });
291521
291676
 
291522
291677
  // ../@aws-cdk/toolkit-lib/lib/api/cloud-assembly/private/stack-assembly.ts
291678
+ function matcherFor(patterns) {
291679
+ const positives = [];
291680
+ const negatives = [];
291681
+ for (const pattern of patterns) {
291682
+ const parsed = (0, import_picomatch.default)(pattern, void 0, true);
291683
+ (parsed.state.negated ? negatives : positives).push(parsed);
291684
+ }
291685
+ if (positives.length === 0 && negatives.length === 0) {
291686
+ return () => false;
291687
+ }
291688
+ return (hierarchicalId) => {
291689
+ const included = positives.length === 0 || positives.some((matches) => matches(hierarchicalId));
291690
+ return included && negatives.every((matches) => matches(hierarchicalId));
291691
+ };
291692
+ }
291523
291693
  function indexByHierarchicalId(stacks) {
291524
291694
  const result2 = /* @__PURE__ */ new Map();
291525
291695
  for (const stack of stacks) {
@@ -291584,7 +291754,6 @@ var init_stack_assembly = __esm({
291584
291754
  import_picomatch = __toESM(require_picomatch4());
291585
291755
  import_semver2 = __toESM(require_semver4());
291586
291756
  init_toolkit_error();
291587
- init_util4();
291588
291757
  init_private();
291589
291758
  init_stack_collection();
291590
291759
  init_stack_selector();
@@ -291708,7 +291877,7 @@ var init_stack_assembly = __esm({
291708
291877
  }
291709
291878
  return {
291710
291879
  stacks: matched,
291711
- suggestions: options.suggestPatternMatches ? this.suggestionsForPatterns(patterns, matched) : void 0
291880
+ suggestions: options.suggestPatternMatches ? this.suggestionsForPatterns(patterns) : void 0
291712
291881
  };
291713
291882
  }
291714
291883
  }
@@ -291718,13 +291887,16 @@ var init_stack_assembly = __esm({
291718
291887
  * at least one stack are omitted; the array is empty when there is no close
291719
291888
  * match. Pure computation, never throws, emits no output.
291720
291889
  */
291721
- suggestionsForPatterns(patterns, matched) {
291890
+ suggestionsForPatterns(patterns) {
291722
291891
  const suggestions = {};
291723
291892
  for (const pattern of patterns) {
291724
- if (matched.stackArtifacts.some((stack) => (0, import_picomatch.isMatch)(stack.hierarchicalId, pattern))) {
291893
+ const exact = (0, import_picomatch.default)(pattern, void 0, true);
291894
+ const loose = (0, import_picomatch.default)(pattern.toLowerCase());
291895
+ const refersTo = exact.state.negated ? (matches, id) => !matches(id) : (matches, id) => matches(id);
291896
+ if (this.allStacks.some((stack) => refersTo(exact, stack.hierarchicalId))) {
291725
291897
  continue;
291726
291898
  }
291727
- suggestions[pattern] = this.allStacks.filter((stack) => (0, import_picomatch.isMatch)(stack.hierarchicalId.toLowerCase(), pattern.toLowerCase())).map((stack) => stack.hierarchicalId);
291899
+ suggestions[pattern] = this.allStacks.filter((stack) => refersTo(loose, stack.hierarchicalId.toLowerCase())).map((stack) => stack.hierarchicalId);
291728
291900
  }
291729
291901
  return suggestions;
291730
291902
  }
@@ -291738,8 +291910,8 @@ var init_stack_assembly = __esm({
291738
291910
  return new StackCollection(this, selected);
291739
291911
  }
291740
291912
  async selectMatchingStacks(stacks, patterns, extend = "none" /* NONE */) {
291741
- const matchingPattern = /* @__PURE__ */ __name((pattern) => (stack) => (0, import_picomatch.isMatch)(stack.hierarchicalId, pattern), "matchingPattern");
291742
- const matchedStacks = flatten2(patterns.map((pattern) => stacks.filter(matchingPattern(pattern))));
291913
+ const selects = matcherFor(patterns);
291914
+ const matchedStacks = stacks.filter((stack) => selects(stack.hierarchicalId));
291743
291915
  return this.extendStacks(matchedStacks, stacks, extend);
291744
291916
  }
291745
291917
  async extendStacks(matched, all, extend = "none" /* NONE */) {
@@ -291760,6 +291932,7 @@ var init_stack_assembly = __esm({
291760
291932
  return new StackCollection(this, selectedList);
291761
291933
  }
291762
291934
  };
291935
+ __name(matcherFor, "matcherFor");
291763
291936
  __name(indexByHierarchicalId, "indexByHierarchicalId");
291764
291937
  __name(includeDownstreamStacks, "includeDownstreamStacks");
291765
291938
  __name(includeUpstreamStacks, "includeUpstreamStacks");
@@ -292628,11 +292801,11 @@ function removeNonImportResources(stack) {
292628
292801
  delete template.Outputs;
292629
292802
  return template;
292630
292803
  }
292631
- var import_util59, cfnDiff, import_chalk17, fs32, ResourceImporter;
292804
+ var import_util57, cfnDiff, import_chalk17, fs32, ResourceImporter;
292632
292805
  var init_importer = __esm({
292633
292806
  "../@aws-cdk/toolkit-lib/lib/api/resource-import/importer.ts"() {
292634
292807
  "use strict";
292635
- import_util59 = require("util");
292808
+ import_util57 = require("util");
292636
292809
  cfnDiff = __toESM(require_lib9());
292637
292810
  import_chalk17 = __toESM(require_source());
292638
292811
  fs32 = __toESM(require_lib4());
@@ -292696,12 +292869,12 @@ var init_importer = __esm({
292696
292869
  const descr = this.describeResource(resource.logicalId);
292697
292870
  const idProps = remaining[resource.logicalId];
292698
292871
  if (idProps) {
292699
- await this.ioHelper.defaults.info((0, import_util59.format)("%s: importing using %s", import_chalk17.default.blue(descr), import_chalk17.default.blue(fmtdict(idProps))));
292872
+ await this.ioHelper.defaults.info((0, import_util57.format)("%s: importing using %s", import_chalk17.default.blue(descr), import_chalk17.default.blue(fmtdict(idProps))));
292700
292873
  ret.importResources.push(resource);
292701
292874
  ret.resourceMap[resource.logicalId] = idProps;
292702
292875
  delete remaining[resource.logicalId];
292703
292876
  } else {
292704
- await this.ioHelper.defaults.info((0, import_util59.format)("%s: skipping", import_chalk17.default.blue(descr)));
292877
+ await this.ioHelper.defaults.info((0, import_util57.format)("%s: skipping", import_chalk17.default.blue(descr)));
292705
292878
  }
292706
292879
  }
292707
292880
  const unknown = Object.keys(remaining);
@@ -292745,9 +292918,9 @@ var init_importer = __esm({
292745
292918
  });
292746
292919
  assertIsSuccessfulDeployStackResult(result2);
292747
292920
  const message2 = result2.noOp ? "\u2705 %s (no changes)" : "\u2705 %s";
292748
- await this.ioHelper.defaults.info("\n" + import_chalk17.default.green((0, import_util59.format)(message2, this.stack.displayName)));
292921
+ await this.ioHelper.defaults.info("\n" + import_chalk17.default.green((0, import_util57.format)(message2, this.stack.displayName)));
292749
292922
  } catch (e6) {
292750
- await this.ioHelper.notify(IO.CDK_TOOLKIT_E3900.msg((0, import_util59.format)("\n \u274C %s failed: %s", import_chalk17.default.bold(this.stack.displayName), e6), { error: e6 }));
292923
+ await this.ioHelper.notify(IO.CDK_TOOLKIT_E3900.msg((0, import_util57.format)("\n \u274C %s failed: %s", import_chalk17.default.bold(this.stack.displayName), e6), { error: e6 }));
292751
292924
  throw e6;
292752
292925
  }
292753
292926
  }
@@ -292877,7 +293050,7 @@ var init_importer = __esm({
292877
293050
  for (const idProp of idProps) {
292878
293051
  const defaultValue2 = resourceProps[idProp] ?? "";
292879
293052
  const response = await this.ioHelper.requestResponse(IO.CDK_TOOLKIT_I3110.req(
292880
- (0, import_util59.format)(promptPattern, import_chalk17.default.blue(idProp)),
293053
+ (0, import_util57.format)(promptPattern, import_chalk17.default.blue(idProp)),
292881
293054
  {
292882
293055
  resource: {
292883
293056
  name: resourceName,
@@ -298909,7 +299082,7 @@ function countAssemblyResults(span, assembly) {
298909
299082
  span.incCounter("assemblies", asmCount(assembly));
298910
299083
  span.incCounter("errorAnns", sum3(stacksRecursively.map((s2) => s2.messages.filter((m4) => m4.level === import_cloud_assembly_api14.SynthesisMessageLevel.ERROR).length)));
298911
299084
  span.incCounter("warnings", sum3(stacksRecursively.map((s2) => s2.messages.filter((m4) => m4.level === import_cloud_assembly_api14.SynthesisMessageLevel.WARNING).length)));
298912
- const annotationErrorCodes = stacksRecursively.flatMap((s2) => Object.values(s2.metadata).flatMap((ms) => ms.filter((m4) => m4.type === ANNOTATION_ERROR_CODE_TYPE)));
299085
+ const annotationErrorCodes = stacksRecursively.flatMap((s2) => Object.values(s2.metadata ?? {}).flatMap((ms) => ms.filter((m4) => m4.type === ANNOTATION_ERROR_CODE_TYPE)));
298913
299086
  for (const annotationErrorCode of annotationErrorCodes) {
298914
299087
  span.incCounter(`errorAnn:${annotationErrorCode.data}`);
298915
299088
  }
@@ -300035,33 +300208,7 @@ var init_toolkit = __esm({
300035
300208
  try {
300036
300209
  const ioHelper = asIoHelper(this.ioHost, "synth");
300037
300210
  const assembly = __using(_stack, new AsyncDisposableBox(await synthAndMeasure(ioHelper, cx, stacksOpt(options))), true);
300038
- const stacks = await assembly.value.selectStacks(stacksOpt(options));
300039
- const autoValidateStacks = options.validateStacks ? [assembly.value.selectStacksForValidation()] : [];
300040
- await throwIfValidationFailures(assembly.value, stacks.concat(...autoValidateStacks), this.assemblyFailureAt, ioHelper);
300041
- const message2 = `Successfully synthesized to ${import_chalk29.default.blue(path35.resolve(stacks.assembly.directory))}`;
300042
- const assemblyData = {
300043
- assemblyDirectory: stacks.assembly.directory,
300044
- stacksCount: stacks.stackCount,
300045
- stackIds: stacks.hierarchicalIds
300046
- };
300047
- if (stacks.stackCount === 1) {
300048
- const firstStack = stacks.firstStack;
300049
- const template = firstStack.template;
300050
- const obscuredTemplate = obscureTemplate(template);
300051
- await ioHelper.notify(IO.CDK_TOOLKIT_I1901.msg(message2, {
300052
- ...assemblyData,
300053
- stack: {
300054
- stackName: firstStack.stackName,
300055
- hierarchicalId: firstStack.hierarchicalId,
300056
- template,
300057
- stringifiedJson: serializeStructure(obscuredTemplate, true),
300058
- stringifiedYaml: serializeStructure(obscuredTemplate, false)
300059
- }
300060
- }));
300061
- } else {
300062
- await ioHelper.notify(IO.CDK_TOOLKIT_I1902.msg(import_chalk29.default.green(message2), assemblyData));
300063
- await ioHelper.defaults.info(`Supply a stack id (${stacks.stackArtifacts.map((s2) => import_chalk29.default.green(s2.hierarchicalId)).join(", ")}) to display its template.`);
300064
- }
300211
+ await this._synth(assembly.value, options);
300065
300212
  return new CachedCloudAssembly(assembly.take());
300066
300213
  } catch (_) {
300067
300214
  var _error = _, _hasError = true;
@@ -300070,6 +300217,40 @@ var init_toolkit = __esm({
300070
300217
  _promise && await _promise;
300071
300218
  }
300072
300219
  }
300220
+ /**
300221
+ * Helper to allow synth being called with an already-produced assembly,
300222
+ * e.g. as part of the watch action which reuses the startup assembly.
300223
+ */
300224
+ async _synth(assembly, options = {}) {
300225
+ const ioHelper = asIoHelper(this.ioHost, "synth");
300226
+ const stacks = await assembly.selectStacks(stacksOpt(options));
300227
+ const autoValidateStacks = options.validateStacks ? [assembly.selectStacksForValidation()] : [];
300228
+ await throwIfValidationFailures(assembly, stacks.concat(...autoValidateStacks), this.assemblyFailureAt, ioHelper);
300229
+ const message2 = `Successfully synthesized to ${import_chalk29.default.blue(path35.resolve(stacks.assembly.directory))}`;
300230
+ const assemblyData = {
300231
+ assemblyDirectory: stacks.assembly.directory,
300232
+ stacksCount: stacks.stackCount,
300233
+ stackIds: stacks.hierarchicalIds
300234
+ };
300235
+ if (stacks.stackCount === 1) {
300236
+ const firstStack = stacks.firstStack;
300237
+ const template = firstStack.template;
300238
+ const obscuredTemplate = obscureTemplate(template);
300239
+ await ioHelper.notify(IO.CDK_TOOLKIT_I1901.msg(message2, {
300240
+ ...assemblyData,
300241
+ stack: {
300242
+ stackName: firstStack.stackName,
300243
+ hierarchicalId: firstStack.hierarchicalId,
300244
+ template,
300245
+ stringifiedJson: serializeStructure(obscuredTemplate, true),
300246
+ stringifiedYaml: serializeStructure(obscuredTemplate, false)
300247
+ }
300248
+ }));
300249
+ } else {
300250
+ await ioHelper.notify(IO.CDK_TOOLKIT_I1902.msg(import_chalk29.default.green(message2), assemblyData));
300251
+ await ioHelper.defaults.info(`Supply a stack id (${stacks.stackArtifacts.map((s2) => import_chalk29.default.green(s2.hierarchicalId)).join(", ")}) to display its template.`);
300252
+ }
300253
+ }
300073
300254
  /**
300074
300255
  * Diff Action
300075
300256
  */
@@ -300766,6 +300947,40 @@ ${deployResult.stackArn}`));
300766
300947
  onDispose: /* @__PURE__ */ __name(async () => cloudWatchLogMonitor?.deactivate(), "onDispose")
300767
300948
  });
300768
300949
  }
300950
+ /**
300951
+ * Continuously observe project files and re-synthesize the selected stacks
300952
+ * automatically when changes are detected.
300953
+ *
300954
+ * Never deploys: each iteration re-synthesizes the app to the cloud assembly
300955
+ * output directory and runs the same checks as the `synth` action.
300956
+ *
300957
+ * This function returns immediately, starting a watcher in the background.
300958
+ */
300959
+ async watchSynth(cx, options = {}) {
300960
+ const ioHelper = asIoHelper(this.ioHost, "synth");
300961
+ return this._watch(cx, options, {
300962
+ command: "cdk synth",
300963
+ activity: "synthesis",
300964
+ // `_watch` runs this inside `invokeSafe`, which reports (and swallows)
300965
+ // failures so the loop survives synth errors while the user is mid-edit.
300966
+ invoke: /* @__PURE__ */ __name(async (initialAssembly) => {
300967
+ var _stack = [];
300968
+ try {
300969
+ if (initialAssembly) {
300970
+ await this._synth(initialAssembly, options);
300971
+ return;
300972
+ }
300973
+ const assembly = __using(_stack, await synthAndMeasure(ioHelper, cx, stacksOpt(options)), true);
300974
+ await this._synth(assembly, options);
300975
+ } catch (_) {
300976
+ var _error = _, _hasError = true;
300977
+ } finally {
300978
+ var _promise = __callDispose(_stack, _error, _hasError);
300979
+ _promise && await _promise;
300980
+ }
300981
+ }, "invoke")
300982
+ });
300983
+ }
300769
300984
  /**
300770
300985
  * Continuously observe project files and validate the selected stacks
300771
300986
  * automatically when changes are detected.
@@ -302743,6 +302958,10 @@ var require_cli_type_registry = __commonJS({
302743
302958
  alias: "q",
302744
302959
  desc: "Do not output CloudFormation Template to stdout",
302745
302960
  default: false
302961
+ },
302962
+ watch: {
302963
+ type: "boolean",
302964
+ desc: "Continuously observe the project files, and synthesize the given stack(s) automatically when changes are detected. Never deploys, and never prints templates to stdout (--quiet and --json have no effect)"
302746
302965
  }
302747
302966
  }
302748
302967
  },
@@ -309404,7 +309623,7 @@ async function execProgram(aws, ioHelper, config2) {
309404
309623
  ...config2.context.all,
309405
309624
  ...params.context
309406
309625
  };
309407
- await debugFn((0, import_util77.format)("context:", context));
309626
+ await debugFn((0, import_util75.format)("context:", context));
309408
309627
  if (params.env.CDK_DEBUG === "true") {
309409
309628
  await ioHelper.defaults.info("\u{1F50D} Synthesizing with debug information. This may take a bit longer.");
309410
309629
  }
@@ -309454,7 +309673,7 @@ async function execProgram(aws, ioHelper, config2) {
309454
309673
  const perfCountersFile = path44.join(outdir, "performance-counters.json");
309455
309674
  await fs47.promises.rm(perfCountersFile, { force: true });
309456
309675
  env3.CDK_PERF_COUNTERS_FILE = perfCountersFile;
309457
- await debugFn((0, import_util77.format)("env:", env3));
309676
+ await debugFn((0, import_util75.format)("env:", env3));
309458
309677
  const cleanupTemp = writeContextToEnv(env3, context, "add-process-env-later");
309459
309678
  try {
309460
309679
  await exec2(commandLine);
@@ -309507,12 +309726,12 @@ function createAssembly(appDir) {
309507
309726
  function noUndefined2(xs) {
309508
309727
  return Object.fromEntries(Object.entries(xs).filter(([_, v]) => v !== void 0));
309509
309728
  }
309510
- var path44, import_util77, import_cloud_assembly_api16, cxschema11, cxapi12, import_toolkit_lib15, fs47;
309729
+ var path44, import_util75, import_cloud_assembly_api16, cxschema11, cxapi12, import_toolkit_lib15, fs47;
309511
309730
  var init_exec2 = __esm({
309512
309731
  "lib/cxapp/exec.ts"() {
309513
309732
  "use strict";
309514
309733
  path44 = __toESM(require("path"));
309515
- import_util77 = require("util");
309734
+ import_util75 = require("util");
309516
309735
  import_cloud_assembly_api16 = __toESM(require_lib3());
309517
309736
  cxschema11 = __toESM(require_lib2());
309518
309737
  cxapi12 = __toESM(require_lib11());
@@ -311408,6 +311627,38 @@ Do you wish to deploy these changes?`;
311408
311627
  await displayFlagsMessage(this.ioHost.asIoHelper(), this.toolkit, this.props.cloudExecutable);
311409
311628
  return void 0;
311410
311629
  }
311630
+ /**
311631
+ * Continuously synthesize the project, re-synthesizing on every file change.
311632
+ * Never deploys, and never prints templates to stdout.
311633
+ *
311634
+ * The files to observe are configured with the "watch" key of `cdk.json`,
311635
+ * exactly like `cdk deploy --watch`.
311636
+ */
311637
+ async synthWatch(options) {
311638
+ const rootDir = path46.dirname(path46.resolve(PROJECT_CONFIG));
311639
+ const watchSettings = this.props.configuration.settings.get(["watch"]);
311640
+ if (!watchSettings) {
311641
+ throw new import_toolkit_lib17.ToolkitError(
311642
+ "WatchConfigMissing",
311643
+ `Cannot use '--watch' without specifying at least one directory to monitor. Make sure to add a "watch" key to your cdk.json`
311644
+ );
311645
+ }
311646
+ const include = this.patternsArrayForWatch(watchSettings.include, {
311647
+ defaultPattern: "**",
311648
+ returnDefaultIfEmpty: true
311649
+ });
311650
+ const exclude = this.patternsArrayForWatch(watchSettings.exclude, {
311651
+ defaultPattern: "",
311652
+ returnDefaultIfEmpty: false
311653
+ });
311654
+ const watcher = await this.toolkit.watchSynth(this.props.cloudExecutable.uncachedSource(), {
311655
+ ...options,
311656
+ watchDir: rootDir,
311657
+ include,
311658
+ exclude
311659
+ });
311660
+ return watcher.waitForEnd();
311661
+ }
311411
311662
  /**
311412
311663
  * Bootstrap the CDK Toolkit stack in the accounts used by the specified stack(s).
311413
311664
  *
@@ -317213,6 +317464,10 @@ function parseCommandLineArguments(args) {
317213
317464
  type: "boolean",
317214
317465
  alias: "q",
317215
317466
  desc: "Do not output CloudFormation Template to stdout"
317467
+ }).option("watch", {
317468
+ default: void 0,
317469
+ type: "boolean",
317470
+ desc: "Continuously observe the project files, and synthesize the given stack(s) automatically when changes are detected. Never deploys, and never prints templates to stdout (--quiet and --json have no effect)"
317216
317471
  })
317217
317472
  ).command(
317218
317473
  "bootstrap [ENVIRONMENTS..]",
@@ -368786,6 +369041,12 @@ async function exec(args, synthesizer) {
368786
369041
  case "synthesize":
368787
369042
  case "synth":
368788
369043
  ioHost.currentAction = "synth";
369044
+ if (args2.watch) {
369045
+ return cli2.synthWatch({
369046
+ stacks: specificStacksOrAllRecursively(args2.STACKS),
369047
+ validateStacks: args2.validation
369048
+ });
369049
+ }
368789
369050
  const quiet = configuration.settings.get(["quiet"]) ?? args2.quiet;
368790
369051
  return cli2.synth({
368791
369052
  stackNames: args2.STACKS,