@go-to-k/cdkd 0.284.81 → 0.284.82

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.
@@ -1,5 +1,5 @@
1
1
  import { d as generateResourceName, f as generateResourceNameWithFallback, g as withStackName, m as looksLikeCdkdGeneratedName, n as getLogger, o as getLiveRenderer, p as getCurrentStackName, u as applyDefaultNameForFallback } from "./logger-C9-E73FI.js";
2
- import { t as getCdkdVersion } from "./version-D91AoEe5.js";
2
+ import { t as getCdkdVersion } from "./version-D_b3uJus.js";
3
3
  import { AsyncLocalStorage } from "node:async_hooks";
4
4
  import { randomUUID } from "node:crypto";
5
5
  import { CreateBucketCommand, DeleteObjectCommand, DeleteObjectsCommand, GetBucketLocationCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchKey, PutBucketEncryptionCommand, PutBucketPolicyCommand, PutObjectCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
@@ -4008,6 +4008,83 @@ function findLargeInlineResources(template, threshold = LARGE_INLINE_RESOURCE_TH
4008
4008
  return result;
4009
4009
  }
4010
4010
 
4011
+ //#endregion
4012
+ //#region src/utils/parameter-types.ts
4013
+ /**
4014
+ * ONE definition of "is this CloudFormation Parameter `Type` LIST-shaped?".
4015
+ *
4016
+ * cdkd used to hold TWO independent answers to this question (issue
4017
+ * [#2347](https://github.com/go-to-k/cdkd/issues/2347)):
4018
+ *
4019
+ * - `coerceParameterTypedValue` in `src/deployment/intrinsic-function-resolver.ts`
4020
+ * named exactly two list types (`List<Number>`, `CommaDelimitedList`) in a
4021
+ * `switch`, so every other `List<...>` spelling fell to `default` and a
4022
+ * `Ref` to it resolved to the raw comma-joined STRING;
4023
+ * - `stringifyParamDefault` in `src/synthesis/macro-expander.ts` tested
4024
+ * `inner.startsWith('List<') || inner === 'CommaDelimitedList'` when choosing
4025
+ * the placeholder shape for an `AWS::SSM::Parameter::Value<...>` parameter,
4026
+ * i.e. the WIDER, correct view.
4027
+ *
4028
+ * The two disagreeing is what let a `List<AWS::EC2::Subnet::Id>` child
4029
+ * parameter be handed to a nested stack as a string. They now share this
4030
+ * predicate, so a third spelling cannot appear without deleting this file.
4031
+ *
4032
+ * This lives in `src/utils/` rather than beside either consumer because it has
4033
+ * TWO, in different layers -- `src/deployment/intrinsic-function-resolver.ts`
4034
+ * and `src/synthesis/macro-expander.ts`. Hosting it in `src/deployment/` gave
4035
+ * the tree its FIRST `src/synthesis/**` -> `src/deployment/**` import, which
4036
+ * inverts the documented layer order (synthesis runs before deployment); every
4037
+ * other synthesis import goes to `../types`, `../utils` or `../cli`.
4038
+ * `src/utils/ip-protocol.ts` is the precedent, hosted here for the same reason
4039
+ * and stating it in the same place. `src/types/` was the other candidate and is
4040
+ * wrong for this: it carries type declarations plus the constants and helpers
4041
+ * that read them, not a standalone runtime predicate with no type of its own.
4042
+ *
4043
+ * ## What CloudFormation actually defines
4044
+ *
4045
+ * Measured 2026-08-28 against the AWS-published enumerations, NOT against a
4046
+ * library:
4047
+ *
4048
+ * - `parameters-section-structure.html` lists the base types as `String`,
4049
+ * `Number`, `List<Number>`, `CommaDelimitedList`, plus "AWS-specific
4050
+ * parameter types" and "Systems Manager parameter types". **A bare
4051
+ * `List<String>` is NOT in that enumeration.**
4052
+ * - `cloudformation-supplied-parameter-types.html` enumerates ten AWS-specific
4053
+ * SCALAR types and nine `List<AWS::...>` types (`List<AWS::EC2::Subnet::Id>`,
4054
+ * `List<AWS::EC2::SecurityGroup::Id>`, ...). `List<String>` appears only as
4055
+ * the INNER shape of the Systems Manager form
4056
+ * `AWS::SSM::Parameter::Value<List<String>>`.
4057
+ *
4058
+ * `List<String>` is nevertheless accepted here, because `aws-cdk-lib`'s own
4059
+ * `CfnParameter` accepts it (`isListType` in
4060
+ * `node_modules/aws-cdk-lib/core/lib/cfn-parameter.js` is a substring test) and
4061
+ * `valueAsList()` on such a parameter synthesizes a template cdkd will deploy
4062
+ * WITHOUT CloudFormation ever seeing it. Treating it as a list is the reading
4063
+ * that agrees with the app that produced it; the alternative silently hands a
4064
+ * string to something the CDK typed as a string list.
4065
+ *
4066
+ * ## Why this is `startsWith`, not `aws-cdk-lib`'s `indexOf`
4067
+ *
4068
+ * `indexOf('List<') >= 0` also matches `MyList<String>` and, load-bearing here,
4069
+ * the Systems Manager OUTER form `AWS::SSM::Parameter::Value<List<String>>`.
4070
+ * That outer form must NOT be list-shaped for the coercion: the VALUE supplied
4071
+ * for an SSM-typed parameter is a Parameter Store KEY, not the resolved list,
4072
+ * so splitting it on `,` would shred a key rather than build a list. The
4073
+ * macro-expander asks this question of the INNER shape it has already peeled
4074
+ * out of `Value<...>`, so the same predicate serves both sites unchanged.
4075
+ *
4076
+ * A closing `>` is required, so `List<`, `List<>` and `List<String` are NOT
4077
+ * list-shaped. That is the whole of the claim: this predicate is a test of the
4078
+ * SPELLING, not a validator. Measured, `List< >`, `List<a>`, `List<<>>` and
4079
+ * `List<X>>` all return `true` -- nothing here rejects a nonsense inner type,
4080
+ * and cdkd deploys without CloudFormation ever seeing the template, so no
4081
+ * service-side validation stands behind it either.
4082
+ */
4083
+ function isListParameterType(type) {
4084
+ if (type === "CommaDelimitedList") return true;
4085
+ return type.length > 6 && type.startsWith("List<") && type.endsWith(">");
4086
+ }
4087
+
4011
4088
  //#endregion
4012
4089
  //#region src/synthesis/macro-expander.ts
4013
4090
  /** 600 seconds = 10 minutes. SDK waiter's `maxWaitTime` is in seconds. */
@@ -4281,8 +4358,7 @@ function stringifyParamDefault(value, type, paramKey, logger) {
4281
4358
  const known = PARAMETER_TYPE_PLACEHOLDERS[type];
4282
4359
  if (known !== void 0) return known;
4283
4360
  if (type.startsWith("AWS::SSM::Parameter::Value<")) {
4284
- const inner = type.slice(27, -1);
4285
- if (inner.startsWith("List<") || inner === "CommaDelimitedList") return "placeholder,placeholder";
4361
+ if (isListParameterType(type.slice(27, -1))) return "placeholder,placeholder";
4286
4362
  return "placeholder";
4287
4363
  }
4288
4364
  logger.warn(`Parameter '${paramKey}' has unrecognized CFn Type '${type}'; using a generic string placeholder for the transient macro-expansion changeset. If CFn rejects the changeset with a type error, file an issue with the offending Type.`);
@@ -16559,14 +16635,26 @@ function parameterTypeMayLoseSecretIdentity(type) {
16559
16635
  * ONE definition of parameter-type coercion, at module scope so
16560
16636
  * {@link parameterTypeMayLoseSecretIdentity} probes the same code the resolver
16561
16637
  * runs rather than a copy of it.
16638
+ *
16639
+ * WHICH TYPES ARE LISTS is asked of the SHARED {@link isListParameterType}
16640
+ * rather than enumerated in the `switch` (issue #2347). The `switch` named only
16641
+ * `List<Number>` and `CommaDelimitedList`, so the nine `List<AWS::...>` types
16642
+ * CloudFormation defines -- `List<AWS::EC2::Subnet::Id>` and its siblings --
16643
+ * fell to `default` and a `Ref` to such a parameter resolved to the raw
16644
+ * comma-joined STRING, while `src/synthesis/macro-expander.ts` held the wider,
16645
+ * correct view of the very same question. Both sites now read one predicate.
16646
+ *
16647
+ * `List<Number>` keeps its own arm because it is the only list type whose
16648
+ * ELEMENTS are not strings; every other list type produces trimmed strings,
16649
+ * which is what CloudFormation says a `Ref` to one returns.
16562
16650
  */
16563
16651
  function coerceParameterTypedValue(value, type) {
16564
16652
  switch (type) {
16565
16653
  case "Number": return Number(value);
16566
16654
  case "List<Number>": return value.split(",").map((v) => Number(v.trim()));
16567
- case "CommaDelimitedList": return value.split(",").map((v) => v.trim());
16568
- default: return value;
16569
16655
  }
16656
+ if (isListParameterType(type)) return value.split(",").map((v) => v.trim());
16657
+ return value;
16570
16658
  }
16571
16659
  /**
16572
16660
  * The inherited `plaintext -> expression` pairs that `value` CARRIES.
@@ -16587,8 +16675,8 @@ function coerceParameterTypedValue(value, type) {
16587
16675
  * for the same reason the redactor excludes them: a 3-character secret
16588
16676
  * matches half the alphabet's worth of ordinary identifiers.
16589
16677
  *
16590
- * A `CommaDelimitedList` parameter arrives as an array, so the scan walks
16591
- * string elements too.
16678
+ * A LIST-TYPED parameter — any `List<...>` type or `CommaDelimitedList` arrives as an
16679
+ * array, so the scan walks string elements too.
16592
16680
  */
16593
16681
  function inheritedSecretsCarriedBy(value, inherited) {
16594
16682
  const candidates = [];
@@ -17919,7 +18007,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
17919
18007
  const [delimiter, rawValues] = joinArgs;
17920
18008
  let values = rawValues;
17921
18009
  if (!Array.isArray(values)) values = await this.resolveValue(values, context);
17922
- if (!Array.isArray(values)) throw new Error(`Fn::Join's second argument must be a list (an array literal or a list-returning intrinsic such as Fn::Cidr / Fn::GetAZs / Fn::Split / a Ref to a CommaDelimitedList parameter), but resolved to ${typeof values}`);
18010
+ if (!Array.isArray(values)) throw new Error(`Fn::Join's second argument must be a list (an array literal or a list-returning intrinsic such as Fn::Cidr / Fn::GetAZs / Fn::Split / a Ref to a list-typed parameter — any List<...> type or CommaDelimitedList), but resolved to ${typeof values}`);
17923
18011
  let result = (await Promise.all(values.map(async (v) => {
17924
18012
  const resolved = await this.resolveValue(v, context);
17925
18013
  return String(resolved);
@@ -18176,9 +18264,10 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
18176
18264
  *
18177
18265
  * - a list-valued `Fn::GetAtt` renders as `Fn::GetAtt [Zone, NameServers]`,
18178
18266
  * naming both the resource and the attribute;
18179
- * - a `Ref` to a `CommaDelimitedList` / `List<Number>` parameter the
18180
- * SECOND genuinely reachable array source, via `coerceParameterValue` —
18181
- * renders as `Ref MyListParam`, naming the parameter.
18267
+ * - a `Ref` to a LIST-TYPED parameter — any `List<...>` type or `CommaDelimitedList`, per the
18268
+ * shared `isListParameterType` — the SECOND genuinely reachable array
18269
+ * source, via `coerceParameterValue` — renders as `Ref MyListParam`,
18270
+ * naming the parameter.
18182
18271
  *
18183
18272
  * Anything else degrades to its bare intrinsic key, or to `undefined` for a
18184
18273
  * literal (which the message then simply omits).
@@ -18283,7 +18372,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
18283
18372
  const source = this.describeSplitValueSource(value);
18284
18373
  const sourceClause = source ? ` (from ${source.label})` : "";
18285
18374
  if (Array.isArray(resolvedValue)) {
18286
- const remedy = source?.kind === "ref" ? `A CommaDelimitedList / List<Number> parameter is already a list.` : source?.kind === "getatt" ? "A list-valued Fn::GetAtt (for example AWS::Route53::HostedZone.NameServers or AWS::EC2::VPC.Ipv6CidrBlocks) already returns a list. If you wrote the Fn::Split as a workaround for cdkd resolving that attribute to a comma-delimited string, that bug is fixed (PR #1868) and the workaround is no longer needed." : "Several intrinsics already return a list — among them a list-valued Fn::GetAtt, a Ref to a CommaDelimitedList / List<Number> parameter, Fn::GetAZs, Fn::Cidr, and Fn::Split itself.";
18375
+ const remedy = source?.kind === "ref" ? "A list-typed parameter — any List<...> type (List<AWS::EC2::Subnet::Id>, List<Number>, …) or CommaDelimitedList — is already a list." : source?.kind === "getatt" ? "A list-valued Fn::GetAtt (for example AWS::Route53::HostedZone.NameServers or AWS::EC2::VPC.Ipv6CidrBlocks) already returns a list. If you wrote the Fn::Split as a workaround for cdkd resolving that attribute to a comma-delimited string, that bug is fixed (PR #1868) and the workaround is no longer needed." : "Several intrinsics already return a list — among them a list-valued Fn::GetAtt, a Ref to a list-typed parameter (any List<...> type or CommaDelimitedList), Fn::GetAZs, Fn::Cidr, and Fn::Split itself.";
18287
18376
  throw markNonRetryable(new IntrinsicResolutionRefusalError(`Fn::Split: the value to split${sourceClause} is ALREADY a list (an array of ${resolvedValue.length} item${resolvedValue.length === 1 ? "" : "s"}), not a string. CloudFormation rejects Fn::Split over a list too, so this template is not valid CloudFormation either. Remove the Fn::Split and use the value directly. ${remedy}`));
18288
18377
  }
18289
18378
  throw markNonRetryable(new IntrinsicResolutionRefusalError(`Fn::Split: the value to split${sourceClause} must be a string, got ${resolvedValue === null ? "null" : typeof resolvedValue}. Fn::Split accepts only a string; check the value or the intrinsic that produced it.`));
@@ -20387,7 +20476,7 @@ var CloudControlProvider = class {
20387
20476
  await this.confirmDeleteTargetIdentity(logicalId, resourceType, physicalId, context);
20388
20477
  if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
20389
20478
  this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
20390
- const { ASGProvider } = await import("./asg-provider-DW0VKnyp.js").then((n) => n.n);
20479
+ const { ASGProvider } = await import("./asg-provider-BoJz-x3Q.js").then((n) => n.n);
20391
20480
  return await new ASGProvider().delete(logicalId, physicalId, resourceType, _properties, context);
20392
20481
  }
20393
20482
  const isProtectedEc2Instance = context?.removeProtection === true && resourceType === "AWS::EC2::Instance";
@@ -32302,4 +32391,4 @@ var DeployEngine = class {
32302
32391
 
32303
32392
  //#endregion
32304
32393
  export { maskerOrIdentity as $, CFN_TEMPLATE_BODY_LIMIT as $n, maskSecretsInText as $t, renderStatefulReason as A, describeAwsFailure as An, ProvisioningError as Ar, requireConfigString as At, exportAliasCollisionScrubWarning as B, Synthesizer as Bn, withErrorHandling as Br, INTRINSIC_KEYS as Bt, isFinalSnapshotError as C, getBootstrapMarkerKey as Cn, LocalInvokeBuildError as Cr, coerceCfnBoolean as Ct, extractDeploymentEventError as D, validateAssetBucketName as Dn, MissingCdkCliError as Dr, replayWarn as Dt, makeCanonicalizePropertiesFn as E, readBootstrapMarkerBody as En, LockError as Er, readConfigString as Et, green as F, partitionSensitiveEnv as Fn, StateError as Fr, s3BucketDualStackDomainName as Ft, IAMRoleProvider as G, resolveAutoAssetStorage as Gn, markRedactedCause as Gr, STATE_SOURCED_CROSS_GENERATION_RULES as Gt, secretBearingStateKeyWarning as H, getDefaultStateBucketName as Hn, isRetryableTransientError as Hr, withRetry as Ht, red as I, runDockerForeground as In, SynthesisError as Ir, s3BucketRegionalDomainName as It, ProviderRegistry as J, resolveStateBucketWithDefault as Jn, createSecretMasker as Jt, collectInlinePolicyNamesManagedBySiblings as K, resolveCaptureObservedState as Kn, retryClassificationText as Kr, STATE_SOURCED_READBACK_RULES as Kt, yellow as L, runDockerStreaming as Ln, formatError as Lr, s3BucketWebsiteUrl as Lt, bold as M, dockerSpawnEnvWithSensitive as Mn, ResourceUpdateNotSupportedError as Mr, producerRegionsFromState as Mt, cyan as N, formatDockerLoginError as Nn, StackHasActiveImportsError as Nr, s3BucketArn as Nt, MULTI_REGION_RECREATE_BLOCKED_TYPES as O, validateContainerRepoName as On, NestedStackChildDirectDestroyError as Or, requireConfigArray as Ot, gray as P, getDockerCmd as Pn, StackTerminationProtectionError as Pr, s3BucketDomainName as Pt, maskDeep as Q, warnDeprecatedNoPrefixCliFlag as Qn, maskSecretsInError as Qt, collectDeclaredOutputNames as R, AssetManifestLoader as Rn, isCdkdError as Rr, applyRoleArnIfSet as Rt, createPreDeleteFinalSnapshot as S, ensureAssetStorage as Sn, DynamicReferenceRegionAmbiguousError as Sr, assertRegionMatch as St, unsupportedFinalSnapshotError as T, parseBootstrapMarker as Tn, LocalStartServiceError as Tr, configStringRefusal as Tt, stateKeySecretExposure as U, getLegacyStateBucketName as Un, isThrottlingError as Ur, DagBuilder as Ut, isExportAliasCollision as V, synthesisStatusMessage as Vn, isMarkedNonRetryable as Vr, describeTypeWithThrottleRetry as Vt, getCurrentResourceSecrets as W, resolveApp as Wn, markNonRetryable as Wr, TemplateParser as Wt, findSilentDropProperties as X, resolveUseCdkBootstrapAssets as Xn, errorCauseChain as Xt, findActionableSilentDrops as Y, resolveStateBucketWithDefaultAndSource as Yn, dynamicReferenceTokens as Yt, createMaskedRetryLogger as Z, stateBucketExistenceConfirmed as Zn, isSingleDynamicReferenceToken as Zt, computeImplicitDeleteEdges as _, escapeRegExp$1 as _n, CdkdError as _r, parameterTypeMayLoseSecretIdentity as _t, DeploymentEventsStore as a, rebuildClientForBucketRegion as an, PARTITION_TABLE as ar, isInterruptedWaitError as at, buildFinalSnapshotIdentifier as b, BOOTSTRAP_MARKER_PREFIX as bn, DependencyError as br, normalizeAwsTagsToCfn as bt, replayFailedOperations as c, importableOutputs as cn, AssemblyReader as cr, slowCcOperationTimeoutMs as ct, updatePartialReason as d, stringifyValue as dn, resolveBucketRegion as dr, IntrinsicFunctionResolver as dt, redactSecretsForState as en, CFN_TEMPLATE_URL_LIMIT as er, CUSTOM_RESOURCE_RESPONSE_PREFIX as et, UNSPECIFIED_SKIP_REASON as f, WorkGraph as fn, AwsClients as fr, carriesDynamicReference as ft, IMPLICIT_DELETE_DEPENDENCIES as g, rewriteTemplateAssetReferences as gn, AssetError as gr, isUnboundTemplateParameter as gt, maskingRetryLogger as h, loadPublishableAssetManifest as hn, setAwsClients as hr, getAccountInfo as ht, DeploymentEventsReader as i, S3StateBackend as in, expectedOwnerParam as ir, interruptWatchListenerCount as it, formatResourceLine as j, buildDockerImage as jn, ResourceTimeoutError as jr, classifyReplaySecretRegion as jt, isStatefulRecreateTargetSync as k, buildDenyExternalAccessPolicy as kn, PartialFailureError as kr, requireConfigObject as kt, replayRollback as l, shouldRetainResource as ln, processStackMessages as lr, disableInstanceApiTermination as lt, withResourceDeadline as m, createAssetRedirectResolver as mn, resetAwsClients as mr, coerceParameterTypedValue as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, LockManager as nn, findLargeInlineResources as nr, beginCommandInterruptScope as nt, planFailedOps as o, exportNamesCarriedFrom as on, canonicalizeRegion as or, startInterruptWatch as ot, deleteSkipReason as p, buildAssetRedirectMap as pn, getAwsClients as pr, cfnRefValueFromPhysicalId as pt, clearOnUpdateRemoval as q, resolveSkipPrefix as qn, __exportAll as qr, TEMPLATE_SOURCED_RULES as qt, DeployEngine as r, displaySafe as rn, uploadCfnTemplate as rr, endCommandInterruptScope as rt, planRollback as s, importableOutputKeys as sn, derivePartitionAndUrlSuffix as sr, CloudControlProvider as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, scrubResourceRecord as tn, MIGRATE_TMP_PREFIX as tr, DEFAULT_STATE_PREFIX as tt, updatePartialMessage as u, AssetPublisher as un, clearBucketRegionCache as ur, isTerminationProtectionPropagationError as ut, ATOMIC_FINAL_SNAPSHOT_TYPES as v, stripControlChars as vn, ConfigError as vr, refStateLookupFromResource as vt, refusesFinalSnapshot as w, isCrossRegionRedirect as wn, LocalMigrateError as wr, configBooleanRefusal as wt, ccRoutedFinalSnapshotError as x, assertAssetBucketRegion as xn, DeployCancelledError as xr, resolveExplicitPhysicalId as xt, PRE_DELETE_SNAPSHOT_TYPES as y, AssetModeResolver as yn, CrossAccountSecretRefusalError as yr, WAFv2WebACLProvider as yt, collectPublishedOutputNames as z, getDockerImageBySourceHash as zn, normalizeAwsError as zr, DiffCalculator as zt };
32305
- //# sourceMappingURL=deploy-engine-DAY3Q6s4.js.map
32394
+ //# sourceMappingURL=deploy-engine-Dh4Jid_H.js.map