@go-to-k/cdkd 0.289.7 → 0.289.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as isVersionOnlyInvocation, t as getCdkdVersion } from "./version-DJGTB4Rm.js";
2
+ import { n as isVersionOnlyInvocation, t as getCdkdVersion } from "./version-DIRhHTEG.js";
3
3
 
4
4
  //#region src/cli/pipe-close-handler.ts
5
5
  /**
@@ -74,7 +74,7 @@ async function main() {
74
74
  console.log(getCdkdVersion());
75
75
  return;
76
76
  }
77
- const { buildProgram } = await import("./program-Ca0PiFL-.js");
77
+ const { buildProgram } = await import("./program-gLF8ioT_.js");
78
78
  const program = buildProgram();
79
79
  const args = reorderArgs(process.argv);
80
80
  await program.parseAsync(args);
@@ -1,6 +1,6 @@
1
1
  import { b as displaySafe, d as applyDefaultNameForFallback, f as explicitNamePropertyFor, g as looksLikeCdkdGeneratedName, h as getCurrentStackName, m as generateResourceNameWithFallback, n as getLogger, p as generateResourceName, r as isStdoutReservedForPayload, s as getLiveRenderer, v as withStackName, y as UNRENDERABLE } from "./logger-DTEUzYP_.js";
2
2
  import { t as awsClientDefaults } from "./aws-client-defaults-D-iYiIJ6.js";
3
- import { t as getCdkdVersion } from "./version-DJGTB4Rm.js";
3
+ import { t as getCdkdVersion } from "./version-DIRhHTEG.js";
4
4
  import { AsyncLocalStorage } from "node:async_hooks";
5
5
  import { createHash, randomUUID } from "node:crypto";
6
6
  import { CreateBucketCommand, DeleteObjectCommand, DeleteObjectsCommand, GetBucketLocationCommand, GetBucketReplicationCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchKey, PutBucketEncryptionCommand, PutBucketPolicyCommand, PutObjectCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
@@ -1082,8 +1082,8 @@ var ResourceTimeoutError = class ResourceTimeoutError extends CdkdError {
1082
1082
  operation;
1083
1083
  timeoutMs;
1084
1084
  constructor(logicalId, resourceType, region, elapsedMs, operation, timeoutMs) {
1085
- const elapsedLabel = formatDuration(elapsedMs);
1086
- const timeoutLabel = formatDuration(timeoutMs);
1085
+ const elapsedLabel = formatDuration$1(elapsedMs);
1086
+ const timeoutLabel = formatDuration$1(timeoutMs);
1087
1087
  super(`Resource ${logicalId} (${resourceType}) in ${region} timed out after ${timeoutLabel} during ${operation} (elapsed ${elapsedLabel}).\nThis may indicate a stuck Cloud Control polling loop, hung Custom Resource, or
1088
1088
  slow ENI provisioning. Re-run with --resource-timeout ${resourceType}=<DURATION>\nto bump the budget for this resource type only, or --verbose to see the
1089
1089
  underlying provider activity.`, "RESOURCE_TIMEOUT");
@@ -1102,7 +1102,7 @@ underlying provider activity.`, "RESOURCE_TIMEOUT");
1102
1102
  * (`30m`, `1h30m`, `45s`). Used by {@link ResourceTimeoutError} so the
1103
1103
  * error message stays compact.
1104
1104
  */
1105
- function formatDuration(ms) {
1105
+ function formatDuration$1(ms) {
1106
1106
  if (ms < 6e4) return `${Math.round(ms / 1e3)}s`;
1107
1107
  const totalMinutes = Math.round(ms / 6e4);
1108
1108
  if (totalMinutes < 60) return `${totalMinutes}m`;
@@ -9239,13 +9239,39 @@ const CUSTOM_RESOURCE_RESPONSE_PREFIX = "custom-resource-responses";
9239
9239
  * `for nested-stack child`), so a user grepping CI logs for one of them found
9240
9240
  * two of three. `subject` now varies only the noun.
9241
9241
  */
9242
- /** Render `expiresIn` without implying more precision than a clock skew allows. */
9243
- function formatRemaining(ms) {
9244
- if (!Number.isFinite(ms)) return "at an unknown time";
9245
- if (ms <= 0) return "already expired";
9246
- const minutes = Math.round(ms / 6e4);
9247
- if (minutes < 1) return "in under a minute";
9248
- return `in ~${minutes}m`;
9242
+ /**
9243
+ * The ONE rendering of a lock's deadline: `expires in 1m23s` / `expired 45s
9244
+ * ago` for a finite `expiresAt`, `expires at an unknown time` otherwise
9245
+ * (issue #3085). Consumed by this module's contention refusal, by
9246
+ * `LockManager`'s three sites (the expired-lock takeover warning, the acquire
9247
+ * retry line, the final `LockError`) and by `cdkd state show`'s lock row, so
9248
+ * a record renders the same everywhere it is shown.
9249
+ *
9250
+ * Takes the RAW `expiresAt`, never a difference: the field is an unchecked
9251
+ * cast, and `Number.isFinite` on the raw value is the test `isLockExpired`
9252
+ * makes, so what this SAYS agrees with what the expiry check DOES. Subtracting
9253
+ * first (the previous `formatRemaining(info.expiresAt - Date.now())`) coerced
9254
+ * a numeric string to a real deadline here while the check called it expired
9255
+ * — the one input that still split the renderers after issue #3083. `{}`,
9256
+ * `"soon"`, an absent field, and the `NaN` that `getLockRecord` substitutes
9257
+ * for a coercion that throws (go-to-k/cdkd#2947) all land on the unknown arm.
9258
+ *
9259
+ * Seconds precision, deliberately: this module used to round to `in ~12m`
9260
+ * "without implying more precision than a clock skew allows", but the
9261
+ * `LockError` refusal that advises the same force-unlock decision already
9262
+ * printed `expires in 4m12s`, so the coarser form was a second spelling of the
9263
+ * same fact rather than a guard against skew.
9264
+ */
9265
+ function formatLockExpiry(expiresAt) {
9266
+ if (!Number.isFinite(expiresAt)) return "expires at an unknown time";
9267
+ const remainingMs = expiresAt - Date.now();
9268
+ return remainingMs > 0 ? `expires in ${formatDuration(remainingMs)}` : `expired ${formatDuration(-remainingMs)} ago`;
9269
+ }
9270
+ /** `1m23s` / `45s` from a non-negative millisecond count. */
9271
+ function formatDuration(ms) {
9272
+ const seconds = Math.floor(ms / 1e3);
9273
+ if (seconds < 60) return `${seconds}s`;
9274
+ return `${Math.floor(seconds / 60)}m${seconds % 60}s`;
9249
9275
  }
9250
9276
  /**
9251
9277
  * Quote a value for a pasteable shell command.
@@ -9316,10 +9342,10 @@ async function buildLockContentionMessage(args) {
9316
9342
  const info = await lockManager.getLockInfo(stackName, region);
9317
9343
  if (info) {
9318
9344
  const operation = info.operation ? `, operation: ${displaySafe(info.operation)}` : "";
9319
- const expires = formatRemaining(info.expiresAt - Date.now());
9345
+ const expires = formatLockExpiry(info.expiresAt);
9320
9346
  const owner = displaySafe(info.owner);
9321
9347
  const holder = owner ? `held by ${owner}${operation}` : `held by an unnamed holder`;
9322
- held = `${heldClause ? `${heldClause} — ` : ""}${holder}, expires ${expires}`;
9348
+ held = `${heldClause ? `${heldClause} — ` : ""}${holder}, ${expires}`;
9323
9349
  if (owner) sawHolder = true;
9324
9350
  }
9325
9351
  } catch {}
@@ -10500,25 +10526,6 @@ var LockManager = class {
10500
10526
  return `${Math.floor(seconds / 60)}m${seconds % 60}s`;
10501
10527
  }
10502
10528
  /**
10503
- * `expires in 1m23s` / `expired 45s ago` for a finite deadline, `expires at
10504
- * an unknown time` otherwise — the ONE spelling for a lock's expiry in this
10505
- * module's messages, so the three sites that render one (the expired-lock
10506
- * takeover warning, the retry line, the final refusal) cannot disagree.
10507
- *
10508
- * The non-finite arm is what stops `expired NaNmNaNs ago` (issue #3083):
10509
- * `expiresAt` is an unchecked cast, and `getLockRecord` deliberately hands
10510
- * a coercion that THROWS through as `NaN` (go-to-k/cdkd#2947) rather than
10511
- * inventing a deadline. The wording matches `formatRemaining` in
10512
- * `lock-contention-message.ts`, which answered the same input this way
10513
- * first. `isLockExpired` decides what such a value MEANS (expired); this
10514
- * only decides what it SAYS.
10515
- */
10516
- formatExpiry(expiresAt) {
10517
- if (!Number.isFinite(expiresAt)) return "expires at an unknown time";
10518
- const remainingMs = expiresAt - Date.now();
10519
- return remainingMs > 0 ? `expires in ${this.formatDuration(remainingMs)}` : `expired ${this.formatDuration(-remainingMs)} ago`;
10520
- }
10521
- /**
10522
10529
  * Try to acquire a lock for a stack
10523
10530
  *
10524
10531
  * Uses If-None-Match: "*" to ensure atomic lock acquisition.
@@ -10573,7 +10580,7 @@ var LockManager = class {
10573
10580
  } else throw deleteError;
10574
10581
  }
10575
10582
  const why = Number.isFinite(existing.info.expiresAt) ? "A live cdkd process renews its lock well inside the TTL, so this normally means the previous owner crashed or was suspended" : `Its expiresAt is not a finite number, which cdkd treats as already expired`;
10576
- this.logger.warn(`Took over an EXPIRED lock for stack: ${stackName} (${region}, owner: ${existing.info.owner}, ${this.formatExpiry(existing.info.expiresAt)}). ${why} -- if it is in fact still running, both processes are now writing to the same stack.`);
10583
+ this.logger.warn(`Took over an EXPIRED lock for stack: ${stackName} (${region}, owner: ${existing.info.owner}, ${formatLockExpiry(existing.info.expiresAt)}). ${why} -- if it is in fact still running, both processes are now writing to the same stack.`);
10577
10584
  try {
10578
10585
  const retryEtag = await this.putLockObject(key, lockInfo);
10579
10586
  this.logger.debug(`Lock acquired for stack: ${stackName} (${region}) after expired lock cleanup, owner: ${lockOwner}`);
@@ -11170,14 +11177,14 @@ var LockManager = class {
11170
11177
  const lockInfo = await this.getLockInfo(stackName, region);
11171
11178
  if (lockInfo) {
11172
11179
  if (attempt < maxRetries) {
11173
- this.logger.info(`Stack '${safeSegment(stackName)}' (${safeSegment(region)}) is locked by ${lockInfo.owner}${lockInfo.operation ? ` (operation: ${lockInfo.operation})` : ""}. Lock ${this.formatExpiry(lockInfo.expiresAt)}. Retrying in ${this.formatDuration(retryDelay)}... (attempt ${attempt + 1}/${maxRetries})`);
11180
+ this.logger.info(`Stack '${safeSegment(stackName)}' (${safeSegment(region)}) is locked by ${lockInfo.owner}${lockInfo.operation ? ` (operation: ${lockInfo.operation})` : ""}. Lock ${formatLockExpiry(lockInfo.expiresAt)}. Retrying in ${this.formatDuration(retryDelay)}... (attempt ${attempt + 1}/${maxRetries})`);
11174
11181
  await new Promise((resolve) => setTimeout(resolve, retryDelay));
11175
11182
  continue;
11176
11183
  }
11177
11184
  }
11178
11185
  }
11179
11186
  const lockInfo = await this.getLockInfo(stackName, region);
11180
- const expiry = lockInfo ? this.formatExpiry(lockInfo.expiresAt) : void 0;
11187
+ const expiry = lockInfo ? formatLockExpiry(lockInfo.expiresAt) : void 0;
11181
11188
  const forceUnlockCommand = buildForceUnlockCommand(stackName, region);
11182
11189
  const recovery = forceUnlockCommand ? `If you are certain no other process is active, run: ${forceUnlockCommand}` : `If you are certain no other process is active, ${UNREPRODUCIBLE_LOCK_CLAUSE.charAt(0).toLowerCase()}${UNREPRODUCIBLE_LOCK_CLAUSE.slice(1)}`;
11183
11190
  const safeStack = safeSegment(stackName);
@@ -11394,7 +11401,10 @@ const sameGenerationBags = /* @__PURE__ */ new WeakSet();
11394
11401
  * stored. On the no-change path the newly redacted bag is installed when
11395
11402
  * the outputs CHANGED, and the previous `persistedOutputs` is kept
11396
11403
  * otherwise; that previous bag is unmarked, which is the answer that arm
11397
- * wants.
11404
+ * wants. When an output FAILED there, what is installed is either a fresh
11405
+ * merge of this pass's values with the previous bag's carried ones (issue
11406
+ * #2771), mixed provenance and never marked, or — when that merge refuses —
11407
+ * the previous bag kept whole, unmarked as above.
11398
11408
  * - the update arm's no-change re-check — a marked `{ ...resolvedProps }`
11399
11409
  * compared against the stored record so a stored token reads as a no-op.
11400
11410
  * NOT installed; the object the provider is handed is the unmarked original.
@@ -12179,18 +12189,28 @@ const UNFRAMED_SPELLING = Symbol("cdkd.nested-parameter.unframed-spelling");
12179
12189
  * and the same generation the bag was resolved from one statement earlier. That
12180
12190
  * is the identical pairing `redactRollbackRecord` already makes for the record
12181
12191
  * it positions, so the two replay walks now agree about what their source is.
12192
+ * Since issue #3090 the `trustAnyExpression` half of that claim no longer
12193
+ * changes what THIS recorder writes for a reference the pass resolved:
12194
+ * refusal 5 asks the pair table under both rule sets, and a resolved unpinned
12195
+ * `ssm` reference has a pair (only its pin is withheld), so either ruleset
12196
+ * positions it through the span arm's empty frame. What the constants still
12197
+ * decide here is `sourceIsSameGeneration`, which a token-shaped plaintext
12198
+ * reaches (fenced by the replay call sites' own file).
12182
12199
  *
12183
12200
  * "No public expressions" carries the carve-out {@link PathSourceRules} states
12184
12201
  * and this note must not restate without it: `cdkd import` warns and persists
12185
12202
  * the RAW template intrinsic, so a public `ssm:` token CAN sit in a record. The
12186
- * replay then CERTIFIES one the deploy default would refuse, at a cost bounded
12187
- * to the issue #1901 class — a spurious UPDATE over a value state should hold
12188
- * resolved, never a disclosure, since an expression is what gets persisted
12189
- * either way. See the replay call sites for why gating on
12190
- * {@link isKnownSecretExpression} is the wrong way to close it.
12191
- *
12192
- * FOUR REFUSALS, each degrading to today's behaviour (the child leaf falls to
12193
- * the plaintext-keyed value scan):
12203
+ * replay's POSITION pass then certifies one the deploy default would refuse;
12204
+ * since issue #3090 refusal 5 refuses to RECORD it under either ruleset (a
12205
+ * token resolved as public is never paired), so the child's leaf falls to the
12206
+ * value scan. Before that the cost was bounded to the issue #1901 class — a
12207
+ * spurious UPDATE over a value state should hold resolved, never a
12208
+ * disclosure, since an expression is what gets persisted either way. See the
12209
+ * replay call sites for why gating on {@link isKnownSecretExpression} is the
12210
+ * wrong way to close it.
12211
+ *
12212
+ * FIVE REFUSALS, each degrading to today's behaviour (the child leaf falls to
12213
+ * the plaintext-keyed value scan); the fifth is stated at its line:
12194
12214
  *
12195
12215
  * 1. REFUSAL — the resolved parameter value is not a WHOLE recorded plaintext.
12196
12216
  * A parameter the parent built with an `Fn::Sub` merely EMBEDS the secret,
@@ -12336,9 +12356,11 @@ const UNFRAMED_SPELLING = Symbol("cdkd.nested-parameter.unframed-spelling");
12336
12356
  * the value, which the entry provides -- or the child's OWN resolution of
12337
12357
  * the same plaintext, in which case the association answers with the leaf's
12338
12358
  * own frame, the right reference for it. So a FRAMED association whose value
12339
- * (iii) refused is inert or correct, never wrong -- a claim about this
12340
- * route's pair gate, not about the whole-token walk above, whose refusal 4
12341
- * cannot see a public token (issue #3090). The association's expression is
12359
+ * (iii) refused is inert or correct, never wrong -- a claim the whole-token
12360
+ * walk's STRING-source half now earns the same way, through refusal 5 (issue
12361
+ * #3090); its intrinsic-source half rests on the reader's condition 3, less
12362
+ * the skeleton arm's own unpinned-`ssm` residual (stated on that arm).
12363
+ * The association's expression is
12342
12364
  * the FRAME, not a token -- the one writer into that table that stores a
12343
12365
  * non-token, said so on {@link storeAssociation}; its readers return it to be
12344
12366
  * persisted, which is exactly what the entry would have written.
@@ -12397,6 +12419,7 @@ function recordNestedStackParameterExpressions(secrets, resourceType, resolvedPr
12397
12419
  if (expression === resolvedValue) continue;
12398
12420
  const seenResolvingTo = plaintextIndexOf(secrets).get(expression);
12399
12421
  if (seenResolvingTo !== void 0 && seenResolvingTo !== resolvedValue) continue;
12422
+ if (typeof sourceLeaf === "string" && resolvedPlaintextOf(secrets, expression) !== resolvedValue) continue;
12400
12423
  if (table === void 0) {
12401
12424
  table = /* @__PURE__ */ new Map();
12402
12425
  nestedStackParameterExpressions.set(secrets, table);
@@ -28407,7 +28430,7 @@ var CloudControlProvider = class {
28407
28430
  const indeterminateGuard = await this.confirmDeleteTargetIdentity(logicalId, resourceType, physicalId, context);
28408
28431
  if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
28409
28432
  this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
28410
- const { ASGProvider } = await import("./asg-provider-D6Zyjgrr.js").then((n) => n.n);
28433
+ const { ASGProvider } = await import("./asg-provider-BNOp-qgj.js").then((n) => n.n);
28411
28434
  const asgProvider = new ASGProvider();
28412
28435
  return withIndeterminateGuard(await asgProvider.delete(logicalId, physicalId, resourceType, _properties, context), indeterminateGuard);
28413
28436
  }
@@ -35065,10 +35088,10 @@ async function createReplicationGroupFinalSnapshot(client, replicationGroupId, l
35065
35088
  *
35066
35089
  * The deploy side (`DeployEngine.handleOutputResolutionFailure`, default arm)
35067
35090
  * warns, stores `undefined` for the key and moves on, so a re-resolved
35068
- * `state.outputs` lacks it (the no-change path keeps the previous bag whole
35069
- * when any output fails, so a key that resolved on an EARLIER deploy can keep
35070
- * its value beside a record — the reader checks absence first and ignores the
35071
- * record then). The diff side resolves outputs with `skipDynamicReferences`, so a
35091
+ * `state.outputs` lacks it (the no-change path keeps a failed key's STORED
35092
+ * value, go-to-k/cdkd#2771, so a key that resolved on an EARLIER deploy can
35093
+ * keep its value beside a record — the reader checks absence first and ignores
35094
+ * the record then). The diff side resolves outputs with `skipDynamicReferences`, so a
35072
35095
  * failure that happens INSIDE a secret lookup — a JSON key the secret does not
35073
35096
  * hold, a reference assembled from another secret's value — does not reproduce
35074
35097
  * there: the value assembles into its token, the key is absent from state, and
@@ -35149,10 +35172,10 @@ async function createReplicationGroupFinalSnapshot(client, replicationGroupId, l
35149
35172
  * the writing binary's version is knowable and merely unstored: keeping it
35150
35173
  * beside the digest and un-binding on mismatch would close that one. All four
35151
35174
  * end the same way: the record keeps binding until the next deploy re-resolves
35152
- * the output, and that deploy publishes the key — unless a SIBLING output is
35153
- * still unresolved on a run with no resource change, where the engine keeps
35154
- * the previous outputs bag wholesale and the key stays unpublished for a
35155
- * further run (go-to-k/cdkd#2771, pre-existing and not introduced here).
35175
+ * the output, and that deploy publishes the key, a still-unresolved SIBLING
35176
+ * included, since the no-change path persists what resolved rather than
35177
+ * keeping the previous bag whole (go-to-k/cdkd#2771; the two shapes it still
35178
+ * keeps whole are in `src/deployment/no-change-outputs-merge.ts`).
35156
35179
  * Documented as the accepted limitation in `docs/cli-diff.md`; it is narrower
35157
35180
  * than the pre-#2740 behaviour, where the diff was wrong on EVERY run.
35158
35181
  *
@@ -35437,8 +35460,9 @@ function bindingSkippedOutputs(pristineTemplate, record, changedLogicalIds) {
35437
35460
  /**
35438
35461
  * Whether two records — either possibly absent — describe the same skipped
35439
35462
  * set with the same digests. The no-change deploy path persists on a
35440
- * difference here: it is the ONLY save trigger for this field on that path,
35441
- * because a skipped output switches the outputs-changed trigger off.
35463
+ * difference here: it is what saves this field when the outputs bag that save
35464
+ * would write is unchanged, which is the usual shape — a skipped output that
35465
+ * never had a stored value leaves the bag equal.
35442
35466
  */
35443
35467
  function skippedOutputsEqual(a, b) {
35444
35468
  const aKeys = a === null || a === void 0 ? [] : Object.keys(a);
@@ -35447,6 +35471,95 @@ function skippedOutputsEqual(a, b) {
35447
35471
  return aKeys.every((k) => Object.prototype.hasOwnProperty.call(b, k) && a?.[k] === b?.[k]);
35448
35472
  }
35449
35473
 
35474
+ //#endregion
35475
+ //#region src/deployment/no-change-outputs-merge.ts
35476
+ /**
35477
+ * True when `value` is a string carrying a SECRET-BEARING CloudFormation
35478
+ * dynamic reference: `{{resolve:secretsmanager:` or `{{resolve:ssm-secure:`,
35479
+ * the two spellings that are secret regardless of what they point at.
35480
+ *
35481
+ * A plain `{{resolve:ssm:...}}` is deliberately excluded. Per issue #1901 it is
35482
+ * classified by the parameter's TYPE, and a `String` / `StringList` parameter is
35483
+ * PUBLIC and legitimately persisted RESOLVED. Treating it as a signal would fire
35484
+ * on a perfectly ordinary record, and since `cdkd diff`'s legacy verdict is
35485
+ * record-WIDE, that would withhold every previous value in the stack and tell
35486
+ * the user to run `cdkd scrub`, which would find nothing to fix. The residual is
35487
+ * a pre-#1901 SecureString `ssm:` record, a strictly narrower gap than the false
35488
+ * positive this exclusion removes.
35489
+ */
35490
+ function isSecretBearingReferenceString(value) {
35491
+ if (typeof value !== "string") return false;
35492
+ return value.includes("{{resolve:secretsmanager:") || value.includes("{{resolve:ssm-secure:");
35493
+ }
35494
+ /**
35495
+ * True when any TOP-LEVEL value of `bag` is itself a secret-bearing expression
35496
+ * string. Leaf granularity on purpose: a container holding an expression next
35497
+ * to a plaintext leaf is exactly the partially redacted residue `cdkd scrub`
35498
+ * admits it can leave, and it must not earn the exoneration.
35499
+ */
35500
+ function bagHoldsSecretExpression(bag) {
35501
+ if (bag === void 0 || bag === null) return false;
35502
+ return Object.values(bag).some((value) => isSecretBearingReferenceString(value));
35503
+ }
35504
+ function hasOwn(bag, key) {
35505
+ return Object.prototype.hasOwnProperty.call(bag, key);
35506
+ }
35507
+ /**
35508
+ * Decide the bag the no-change path persists when `resolved` holds at least
35509
+ * one unresolved output. See the module doc for the three rules and the two
35510
+ * refusals.
35511
+ */
35512
+ function mergeNoChangeOutputs(input) {
35513
+ const { persisted, resolved, declaredOutputs, previousExportNames, resolvedExportNames } = input;
35514
+ const failedKeys = Object.keys(resolved).filter((key) => resolved[key] === void 0);
35515
+ const exportNameOf = (outputKey) => declaredOutputs !== void 0 && hasOwn(declaredOutputs, outputKey) ? declaredOutputs[outputKey]?.Export?.Name : void 0;
35516
+ for (const outputKey of failedKeys) {
35517
+ const exportName = exportNameOf(outputKey);
35518
+ if (exportName !== null && typeof exportName === "object" && hasOwn(persisted, outputKey)) return {
35519
+ kind: "kept",
35520
+ reason: "intrinsic-export-name"
35521
+ };
35522
+ }
35523
+ const outputs = Object.create(null);
35524
+ for (const [key, value] of Object.entries(resolved)) if (value !== void 0) outputs[key] = value;
35525
+ const carriedKeys = [];
35526
+ const exportNames = [...resolvedExportNames];
35527
+ const addExport = (name) => {
35528
+ exportNames.push(name);
35529
+ };
35530
+ for (const outputKey of failedKeys) {
35531
+ const exportName = exportNameOf(outputKey);
35532
+ if (hasOwn(persisted, outputKey)) {
35533
+ outputs[outputKey] = persisted[outputKey];
35534
+ carriedKeys.push(outputKey);
35535
+ if (exportName === outputKey && previousExportNames.has(outputKey)) addExport(outputKey);
35536
+ }
35537
+ if (typeof exportName !== "string") continue;
35538
+ if (previousExportNames.has(exportName) && hasOwn(persisted, exportName) && !hasOwn(resolved, exportName) && !hasOwn(outputs, exportName)) {
35539
+ outputs[exportName] = persisted[exportName];
35540
+ carriedKeys.push(exportName);
35541
+ addExport(exportName);
35542
+ }
35543
+ }
35544
+ if (carriedKeys.length > 0 && bagHoldsSecretExpression(outputs) && !bagHoldsSecretExpression(persisted)) return {
35545
+ kind: "kept",
35546
+ reason: "mixed-generation"
35547
+ };
35548
+ return {
35549
+ kind: "merged",
35550
+ outputs,
35551
+ exportNames,
35552
+ carriedKeys
35553
+ };
35554
+ }
35555
+ /** The sentence the deploy engine appends to its keep-whole warning. */
35556
+ function keptWholeReasonText(reason) {
35557
+ switch (reason) {
35558
+ case "intrinsic-export-name": return "An unresolved output declares an intrinsic Export.Name, so the export key it published before cannot be identified and carried.";
35559
+ case "mixed-generation": return "Persisting only the outputs that resolved would put a redacted secret reference beside a carried value in a bag that held none, which would make that value read as redacted.";
35560
+ }
35561
+ }
35562
+
35450
35563
  //#endregion
35451
35564
  //#region src/analyzer/implicit-delete-deps.ts
35452
35565
  /**
@@ -38934,14 +39047,32 @@ var DeployEngine = class DeployEngine {
38934
39047
  let persistedOutputs = currentState.outputs ?? {};
38935
39048
  if (!this.options.dryRun) {
38936
39049
  const resolvedOutputs = this.redactOutputs(await withSharedDrainBudget(() => this.resolveOutputs(effectiveTemplate, currentState.resources, stackName, outputsDigestSource, parameterValues, conditions)));
38937
- const resolutionFailed = Object.values(resolvedOutputs).some((v) => v === void 0);
38938
- const outputsChanged = !resolutionFailed && !outputMapsEqual(persistedOutputs, resolvedOutputs);
38939
- const currentEffectiveExports = new Set(importableOutputKeys(currentState));
38940
- const resolvedExportSet = new Set(this.resolvedExportNames);
38941
- const exportSetChanged = !resolutionFailed && (currentEffectiveExports.size !== resolvedExportSet.size || [...resolvedExportSet].some((k) => !currentEffectiveExports.has(k)));
38942
- if (resolutionFailed && !outputMapsEqual(persistedOutputs, resolvedOutputs)) this.logger.warn("Outputs changed but one or more could not be resolved; keeping the previously persisted outputs. A downstream Fn::ImportValue may fail until the next deploy.");
38943
39050
  const observedRefresh = this.observedCaptureTasks.size > 0;
38944
39051
  if (observedRefresh) await this.drainObservedCaptures(currentState.resources);
39052
+ const resolutionFailed = Object.values(resolvedOutputs).some((v) => v === void 0);
39053
+ const currentEffectiveExports = new Set(importableOutputKeys(currentState));
39054
+ let merge = resolutionFailed ? mergeNoChangeOutputs({
39055
+ persisted: persistedOutputs,
39056
+ resolved: resolvedOutputs,
39057
+ declaredOutputs: effectiveTemplate.Outputs,
39058
+ previousExportNames: currentEffectiveExports,
39059
+ resolvedExportNames: this.resolvedExportNames
39060
+ }) : void 0;
39061
+ if (merge?.kind === "merged") {
39062
+ for (const key of merge.carriedKeys) Reflect.deleteProperty(this.outputsTemplateSource, key);
39063
+ if (merge.carriedKeys.length > 0 && !bagHoldsSecretExpression(persistedOutputs) && bagHoldsSecretExpression(this.redactOutputs(merge.outputs))) merge = {
39064
+ kind: "kept",
39065
+ reason: "mixed-generation"
39066
+ };
39067
+ }
39068
+ if (merge?.kind === "kept") this.outputsSourceUsable = false;
39069
+ const outputsToPersist = merge === void 0 ? resolvedOutputs : merge.kind === "merged" ? merge.outputs : persistedOutputs;
39070
+ const exportNamesToPersist = merge === void 0 ? this.resolvedExportNames : merge.kind === "merged" ? merge.exportNames : void 0;
39071
+ const outputsChanged = !outputMapsEqual(persistedOutputs, outputsToPersist);
39072
+ const persistExportSet = new Set(exportNamesToPersist ?? []);
39073
+ const exportSetChanged = exportNamesToPersist !== void 0 && (currentEffectiveExports.size !== persistExportSet.size || [...persistExportSet].some((k) => !currentEffectiveExports.has(k)));
39074
+ if (merge?.kind === "kept" && !outputMapsEqual(persistedOutputs, resolvedOutputs)) this.logger.warn(`Outputs changed but one or more could not be resolved; keeping the previously persisted outputs. ${keptWholeReasonText(merge.reason)} A downstream Fn::ImportValue may fail until the next deploy.`);
39075
+ else if (merge?.kind === "merged" && merge.carriedKeys.length > 0) this.logger.debug(`Kept the previously persisted value of ${merge.carriedKeys.length} output key(s) that could not be resolved (no-change path, #2771)`);
38945
39076
  const skippedOutputsChanged = !skippedOutputsEqual(currentState.skippedOutputs, this.skippedOutputs);
38946
39077
  if (observedRefresh || outputsChanged || exportSetChanged || skippedOutputsChanged || orphansChanged) try {
38947
39078
  const refreshedState = {
@@ -38950,8 +39081,8 @@ var DeployEngine = class DeployEngine {
38950
39081
  stackName: currentState.stackName,
38951
39082
  resources: currentState.resources,
38952
39083
  ...orphansCarriedFrom(currentState),
38953
- outputs: outputsChanged ? resolvedOutputs : persistedOutputs,
38954
- ...resolutionFailed ? exportNamesCarriedFrom(currentState) : { exportNames: [...this.resolvedExportNames] },
39084
+ outputs: outputsChanged ? outputsToPersist : persistedOutputs,
39085
+ ...exportNamesToPersist === void 0 ? exportNamesCarriedFrom(currentState) : { exportNames: [...exportNamesToPersist] },
38955
39086
  ...this.skippedOutputs && { skippedOutputs: { ...this.skippedOutputs } },
38956
39087
  ...crossStackReadsForPartialSave(currentState, this.recordedImports, this.recordedOutputReads),
38957
39088
  lastModified: Date.now()
@@ -40853,5 +40984,5 @@ var DeployEngine = class DeployEngine {
40853
40984
  };
40854
40985
 
40855
40986
  //#endregion
40856
- export { collectInlinePolicyNamesManagedBySiblings as $, describeAwsFailure as $n, IntrinsicResolutionRefusalError as $r, describeTypeWithThrottleRetry as $t, isStatefulRecreateTargetForReplace as A, importableOutputKeys as An, MIGRATE_TMP_PREFIX as Ar, coerceCfnBoolean as At, gray as B, loadPublishableAssetManifest as Bn, clearBucketRegionCache as Br, classifyReplaySecretRegion as Bt, refusesFinalSnapshot as C, __exportAll as Ci, buildForceUnlockCommand as Cn, resolveStateBucketWithDefault as Cr, isUnboundTemplateParameter as Ct, makeSiblingClaimReader as D, CUSTOM_RESOURCE_RESPONSE_PREFIX as Dn, warnDeprecatedNoPrefixCliFlag as Dr, normalizeAwsTagsToCfn as Dt, extractDeploymentEventError as E, shellQuote as En, stateBucketExistenceConfirmed as Er, WAFv2WebACLProvider as Et, isWarmThroughputDecrease as F, AssetPublisher as Fn, PARTITION_TABLE as Fr, readConfigString as Ft, collectPublishedOutputNames as G, ensureAssetStorage as Gn, setAwsClients as Gr, s3BucketDualStackDomainName as Gt, red as H, AssetModeResolver as Hn, AwsClients as Hr, withSharedDrainBudget as Ht, toFiniteNumber as I, stringifyValue as In, canonicalizeRegion as Ir, replayWarn as It, secretBearing as J, parseBootstrapMarker as Jn, ConfigError as Jr, applyRoleArnIfSet as Jt, exportAliasCollisionScrubWarning as K, getBootstrapMarkerKey as Kn, AssetError as Kr, s3BucketRegionalDomainName as Kt, formatResourceLine as L, WorkGraph as Ln, derivePartitionAndUrlSuffix as Lr, requireConfigArray as Lt, renderStatefulReason as M, orphansAfterRollback as Mn, uploadCfnTemplate as Mr, configBooleanRefusal as Mt, WARM_THROUGHPUT_MEMBERS as N, orphansCarriedFrom as Nn, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as Nr, configIntegerRefusal as Nt, planOrphanAdoption as O, DEFAULT_STATE_PREFIX as On, CFN_TEMPLATE_BODY_LIMIT as Or, resolveExplicitPhysicalId as Ot, coerceWarmThroughput as P, shouldRetainResource as Pn, expectedOwnerParam as Pr, configStringRefusal as Pt, IAMRoleProvider as Q, buildDenyExternalAccessPolicy as Qn, DynamicReferenceRegionAmbiguousError as Qr, findSilentDropProperties as Qt, bold as R, buildAssetRedirectMap as Rn, AssemblyReader as Rr, requireConfigObject as Rt, isFinalSnapshotError as S, retryClassificationText as Si, rebuildClientForBucketRegion as Sn, resolveSkipPrefix as Sr, getAccountInfo as St, makeCanonicalizePropertiesFn as T, forceQuitRecoveryClause as Tn, resolveUseCdkBootstrapAssets as Tr, refStateLookupFromResource as Tt, yellow as U, BOOTSTRAP_MARKER_PREFIX as Un, getAwsClients as Ur, s3BucketArn as Ut, green as V, rewriteTemplateAssetReferences as Vn, resolveBucketRegion as Vr, producerRegionsFromState as Vt, collectDeclaredOutputNames as W, assertAssetBucketRegion as Wn, resetAwsClients as Wr, s3BucketDomainName as Wt, secretSafeKeyDisplay as X, validateAssetBucketName as Xn, DependencyError as Xr, INTRINSIC_KEYS as Xt, secretBearingStateKeyWarning as Y, readBootstrapMarkerBody as Yn, CrossAccountSecretRefusalError as Yr, DiffCalculator as Yt, getCurrentResourceSecrets as Z, validateContainerRepoName as Zn, DeployCancelledError as Zr, findActionableSilentDrops as Zt, ATOMIC_FINAL_SNAPSHOT_TYPES as _, isRetryableTransientError as _i, recoverMaskedOutput as _n, getDefaultStateBucketName as _r, isTerminationProtectionPropagationError as _t, DeploymentEventsStore as a, ProvisioningError as ai, STATE_SOURCED_READBACK_RULES as an, formatDockerLoginError as ar, maskerOrIdentity as at, ccRoutedFinalSnapshotError as b, markNonRetryable as bi, LockManager as bn, resolveAutoAssetStorage as br, cfnRefValueFromPhysicalId as bt, replayFailedOperations as c, StackHasActiveImportsError as ci, createSecretMasker as cn, redactDockerArgvValues as cr, interruptWatchListenerCount as ct, updatePartialReason as d, SynthesisError as di, identityKeyFor as dn, escapeRegExp$1 as dr, CloudControlProvider as dt, LocalInvokeBuildError as ei, withRetry as en, buildDockerImage as er, clearOnUpdateRemoval as et, withResourceDeadline as f, formatError as fi, isSingleDynamicReferenceToken as fn, stripControlChars as fr, slowCcOperationTimeoutMs as ft, bindingSkippedOutputs as g, isMarkedNonRetryable as gi, recordMaskOnlyValue as gn, synthesisStatusMessage as gr, disableInstanceApiTermination as gt, computeImplicitDeleteEdges as h, withErrorHandling as hi, maskSecretsInText as hn, Synthesizer as hr, deleteSkipReason as ht, DeploymentEventsReader as i, PartialFailureError as ii, STATE_SOURCED_CROSS_GENERATION_RULES as in, dockerSpawnEnvWithSensitive as ir, maskDeep as it, isStatefulRecreateTargetSync as j, importableOutputs as jn, findLargeInlineResources as jr, coerceCfnInteger as jt, MULTI_REGION_RECREATE_BLOCKED_TYPES as k, exportNamesCarriedFrom as kn, CFN_TEMPLATE_URL_LIMIT as kr, assertRegionMatch as kt, replayRollback as l, StackTerminationProtectionError as li, dynamicReferenceTokens as ln, runDockerForeground as lr, isInterruptedWaitError as lt, IMPLICIT_DELETE_DEPENDENCIES as m, normalizeAwsError as mi, maskSecretsInError as mn, getDockerImageBySourceHash as mr, deleteIndeterminateGuards as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, LockError as ni, TemplateParser as nn, describeDockerExecFailure as nr, wouldReturnToSdkProvider as nt, planFailedOps as o, ResourceTimeoutError as oi, TEMPLATE_SOURCED_RULES as on, getDockerCmd as or, beginCommandInterruptScope as ot, maskingRetryLogger as p, isCdkdError as pi, markSameGenerationBag as pn, AssetManifestLoader as pr, UNSPECIFIED_SKIP_REASON as pt, isExportAliasCollision as q, isCrossRegionRedirect as qn, CdkdError as qr, s3BucketWebsiteUrl as qt, DeployEngine as r, NestedStackChildDirectDestroyError as ri, STATE_SOURCED_BASELINE_RULES as rn, describeDockerFailure as rr, createMaskedRetryLogger as rt, planRollback as s, ResourceUpdateNotSupportedError as si, carriesSecretMask as sn, partitionSensitiveEnv as sr, endCommandInterruptScope as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, LocalStartServiceError as ti, DagBuilder as tn, describeDockerCapturedOutput as tr, ProviderRegistry as tt, updatePartialMessage as u, StateError as ui, errorCauseChain as un, runDockerStreaming as ur, startInterruptWatch as ut, PRE_DELETE_SNAPSHOT_TYPES as v, isThrottlingError as vi, redactSecretsForState as vn, getLegacyStateBucketName as vr, IntrinsicFunctionResolver as vt, unsupportedFinalSnapshotError as w, buildLockContentionMessage as wn, resolveStateBucketWithDefaultAndSource as wr, parameterTypeMayLoseSecretIdentity as wt, createPreDeleteFinalSnapshot as x, markRedactedCause as xi, S3StateBackend as xn, resolveCaptureObservedState as xr, coerceParameterTypedValue as xt, buildFinalSnapshotIdentifier as y, isTransientServerError as yi, scrubResourceRecord as yn, resolveApp as yr, carriesDynamicReference as yt, cyan as z, createAssetRedirectResolver as zn, processStackMessages as zr, requireConfigString as zt };
40857
- //# sourceMappingURL=deploy-engine-DrTOY3f-.js.map
40987
+ export { getCurrentResourceSecrets as $, validateAssetBucketName as $n, DependencyError as $r, findActionableSilentDrops as $t, planOrphanAdoption as A, CUSTOM_RESOURCE_RESPONSE_PREFIX as An, warnDeprecatedNoPrefixCliFlag as Ar, resolveExplicitPhysicalId as At, bold as B, WorkGraph as Bn, derivePartitionAndUrlSuffix as Br, requireConfigObject as Bt, createPreDeleteFinalSnapshot as C, markNonRetryable as Ci, S3StateBackend as Cn, resolveAutoAssetStorage as Cr, coerceParameterTypedValue as Ct, makeCanonicalizePropertiesFn as D, forceQuitRecoveryClause as Dn, resolveStateBucketWithDefaultAndSource as Dr, refStateLookupFromResource as Dt, unsupportedFinalSnapshotError as E, __exportAll as Ei, buildLockContentionMessage as En, resolveStateBucketWithDefault as Er, parameterTypeMayLoseSecretIdentity as Et, WARM_THROUGHPUT_MEMBERS as F, orphansAfterRollback as Fn, uploadCfnTemplate as Fr, configIntegerRefusal as Ft, yellow as G, AssetModeResolver as Gn, AwsClients as Gr, s3BucketArn as Gt, gray as H, createAssetRedirectResolver as Hn, processStackMessages as Hr, classifyReplaySecretRegion as Ht, coerceWarmThroughput as I, orphansCarriedFrom as In, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as Ir, configStringRefusal as It, exportAliasCollisionScrubWarning as J, ensureAssetStorage as Jn, setAwsClients as Jr, s3BucketRegionalDomainName as Jt, collectDeclaredOutputNames as K, BOOTSTRAP_MARKER_PREFIX as Kn, getAwsClients as Kr, s3BucketDomainName as Kt, isWarmThroughputDecrease as L, shouldRetainResource as Ln, expectedOwnerParam as Lr, readConfigString as Lt, isStatefulRecreateTargetForReplace as M, exportNamesCarriedFrom as Mn, CFN_TEMPLATE_URL_LIMIT as Mr, coerceCfnBoolean as Mt, isStatefulRecreateTargetSync as N, importableOutputKeys as Nn, MIGRATE_TMP_PREFIX as Nr, coerceCfnInteger as Nt, extractDeploymentEventError as O, formatLockExpiry as On, resolveUseCdkBootstrapAssets as Or, WAFv2WebACLProvider as Ot, renderStatefulReason as P, importableOutputs as Pn, findLargeInlineResources as Pr, configBooleanRefusal as Pt, secretSafeKeyDisplay as Q, readBootstrapMarkerBody as Qn, CrossAccountSecretRefusalError as Qr, INTRINSIC_KEYS as Qt, toFiniteNumber as R, AssetPublisher as Rn, PARTITION_TABLE as Rr, replayWarn as Rt, ccRoutedFinalSnapshotError as S, isTransientServerError as Si, LockManager as Sn, resolveApp as Sr, cfnRefValueFromPhysicalId as St, refusesFinalSnapshot as T, retryClassificationText as Ti, buildForceUnlockCommand as Tn, resolveSkipPrefix as Tr, isUnboundTemplateParameter as Tt, green as U, loadPublishableAssetManifest as Un, clearBucketRegionCache as Ur, producerRegionsFromState as Ut, cyan as V, buildAssetRedirectMap as Vn, AssemblyReader as Vr, requireConfigString as Vt, red as W, rewriteTemplateAssetReferences as Wn, resolveBucketRegion as Wr, withSharedDrainBudget as Wt, secretBearing as X, isCrossRegionRedirect as Xn, CdkdError as Xr, applyRoleArnIfSet as Xt, isExportAliasCollision as Y, getBootstrapMarkerKey as Yn, AssetError as Yr, s3BucketWebsiteUrl as Yt, secretBearingStateKeyWarning as Z, parseBootstrapMarker as Zn, ConfigError as Zr, DiffCalculator as Zt, isSecretBearingReferenceString as _, normalizeAwsError as _i, maskSecretsInText as _n, getDockerImageBySourceHash as _r, deleteSkipReason as _t, DeploymentEventsStore as a, LockError as ai, STATE_SOURCED_BASELINE_RULES as an, describeDockerExecFailure as ar, createMaskedRetryLogger as at, PRE_DELETE_SNAPSHOT_TYPES as b, isRetryableTransientError as bi, redactSecretsForState as bn, getDefaultStateBucketName as br, IntrinsicFunctionResolver as bt, replayFailedOperations as c, ProvisioningError as ci, TEMPLATE_SOURCED_RULES as cn, formatDockerLoginError as cr, beginCommandInterruptScope as ct, updatePartialReason as d, StackHasActiveImportsError as di, dynamicReferenceTokens as dn, redactDockerArgvValues as dr, isInterruptedWaitError as dt, DeployCancelledError as ei, findSilentDropProperties as en, validateContainerRepoName as er, IAMRoleProvider as et, withResourceDeadline as f, StackTerminationProtectionError as fi, errorCauseChain as fn, runDockerForeground as fr, startInterruptWatch as ft, bagHoldsSecretExpression as g, isCdkdError as gi, maskSecretsInError as gn, AssetManifestLoader as gr, deleteIndeterminateGuards as gt, computeImplicitDeleteEdges as h, formatError as hi, markSameGenerationBag as hn, stripControlChars as hr, UNSPECIFIED_SKIP_REASON as ht, DeploymentEventsReader as i, LocalStartServiceError as ii, TemplateParser as in, describeDockerCapturedOutput as ir, wouldReturnToSdkProvider as it, MULTI_REGION_RECREATE_BLOCKED_TYPES as j, DEFAULT_STATE_PREFIX as jn, CFN_TEMPLATE_BODY_LIMIT as jr, assertRegionMatch as jt, makeSiblingClaimReader as k, shellQuote as kn, stateBucketExistenceConfirmed as kr, normalizeAwsTagsToCfn as kt, replayRollback as l, ResourceTimeoutError as li, carriesSecretMask as ln, getDockerCmd as lr, endCommandInterruptScope as lt, IMPLICIT_DELETE_DEPENDENCIES as m, SynthesisError as mi, isSingleDynamicReferenceToken as mn, escapeRegExp$1 as mr, slowCcOperationTimeoutMs as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, IntrinsicResolutionRefusalError as ni, withRetry as nn, describeAwsFailure as nr, clearOnUpdateRemoval as nt, planFailedOps as o, NestedStackChildDirectDestroyError as oi, STATE_SOURCED_CROSS_GENERATION_RULES as on, describeDockerFailure as or, maskDeep as ot, maskingRetryLogger as p, StateError as pi, identityKeyFor as pn, runDockerStreaming as pr, CloudControlProvider as pt, collectPublishedOutputNames as q, assertAssetBucketRegion as qn, resetAwsClients as qr, s3BucketDualStackDomainName as qt, DeployEngine as r, LocalInvokeBuildError as ri, DagBuilder as rn, buildDockerImage as rr, ProviderRegistry as rt, planRollback as s, PartialFailureError as si, STATE_SOURCED_READBACK_RULES as sn, dockerSpawnEnvWithSensitive as sr, maskerOrIdentity as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, DynamicReferenceRegionAmbiguousError as ti, describeTypeWithThrottleRetry as tn, buildDenyExternalAccessPolicy as tr, collectInlinePolicyNamesManagedBySiblings as tt, updatePartialMessage as u, ResourceUpdateNotSupportedError as ui, createSecretMasker as un, partitionSensitiveEnv as ur, interruptWatchListenerCount as ut, bindingSkippedOutputs as v, withErrorHandling as vi, recordMaskOnlyValue as vn, Synthesizer as vr, disableInstanceApiTermination as vt, isFinalSnapshotError as w, markRedactedCause as wi, rebuildClientForBucketRegion as wn, resolveCaptureObservedState as wr, getAccountInfo as wt, buildFinalSnapshotIdentifier as x, isThrottlingError as xi, scrubResourceRecord as xn, getLegacyStateBucketName as xr, carriesDynamicReference as xt, ATOMIC_FINAL_SNAPSHOT_TYPES as y, isMarkedNonRetryable as yi, recoverMaskedOutput as yn, synthesisStatusMessage as yr, isTerminationProtectionPropagationError as yt, formatResourceLine as z, stringifyValue as zn, canonicalizeRegion as zr, requireConfigArray as zt };
40988
+ //# sourceMappingURL=deploy-engine-BwZFYWGI.js.map