@go-to-k/cdkd 0.18.0 → 0.19.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.
Binary file
package/dist/index.js CHANGED
@@ -432,10 +432,122 @@ var init_aws_clients = __esm({
432
432
  }
433
433
  });
434
434
 
435
+ // src/provisioning/resource-name.ts
436
+ import { AsyncLocalStorage } from "node:async_hooks";
437
+ import { createHash } from "node:crypto";
438
+ var stackNameStore = new AsyncLocalStorage();
439
+ function withStackName(stackName, fn) {
440
+ return stackNameStore.run(stackName, fn);
441
+ }
442
+ function getCurrentStackName() {
443
+ return stackNameStore.getStore();
444
+ }
445
+ function generateResourceName(name, options) {
446
+ const { maxLength, lowercase = false, allowedPattern = /[^a-zA-Z0-9-]/g } = options;
447
+ const currentStackName = stackNameStore.getStore();
448
+ const fullName = currentStackName ? `${currentStackName}-${name}` : name;
449
+ let sanitized = lowercase ? fullName.toLowerCase() : fullName;
450
+ sanitized = sanitized.replace(allowedPattern, "-");
451
+ sanitized = sanitized.replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "");
452
+ if (sanitized.length <= maxLength) {
453
+ return sanitized;
454
+ }
455
+ const hash = createHash("sha256").update(fullName).digest("hex").substring(0, 8);
456
+ const maxPrefixLength = maxLength - hash.length - 1;
457
+ const prefix = sanitized.substring(0, maxPrefixLength).replace(/-+$/, "");
458
+ return `${prefix}-${hash}`;
459
+ }
460
+ var FALLBACK_NAME_RULES = {
461
+ "AWS::S3::Bucket": { nameProperty: "BucketName", options: { maxLength: 63, lowercase: true } },
462
+ "AWS::SQS::Queue": { nameProperty: "QueueName", options: { maxLength: 80 } },
463
+ "AWS::SNS::Topic": { nameProperty: "TopicName", options: { maxLength: 256 } },
464
+ "AWS::Lambda::Function": { nameProperty: "FunctionName", options: { maxLength: 64 } },
465
+ "AWS::Lambda::LayerVersion": { nameProperty: "LayerName", options: { maxLength: 64 } },
466
+ "AWS::IAM::Role": { nameProperty: "RoleName", options: { maxLength: 64 } },
467
+ "AWS::IAM::Policy": { nameProperty: "PolicyName", options: { maxLength: 64 } },
468
+ "AWS::IAM::User": { nameProperty: "UserName", options: { maxLength: 64 } },
469
+ "AWS::IAM::Group": { nameProperty: "GroupName", options: { maxLength: 128 } },
470
+ "AWS::IAM::InstanceProfile": {
471
+ nameProperty: "InstanceProfileName",
472
+ options: { maxLength: 128 }
473
+ },
474
+ "AWS::DynamoDB::Table": { nameProperty: "TableName", options: { maxLength: 255 } },
475
+ "AWS::ECR::Repository": {
476
+ nameProperty: "RepositoryName",
477
+ options: { maxLength: 256, lowercase: true }
478
+ },
479
+ "AWS::ECS::Cluster": { nameProperty: "ClusterName", options: { maxLength: 255 } },
480
+ "AWS::ECS::Service": { nameProperty: "ServiceName", options: { maxLength: 255 } },
481
+ "AWS::Logs::LogGroup": { nameProperty: "LogGroupName", options: { maxLength: 512 } },
482
+ "AWS::CloudWatch::Alarm": { nameProperty: "AlarmName", options: { maxLength: 256 } },
483
+ "AWS::Events::Rule": { nameProperty: "Name", options: { maxLength: 64 } },
484
+ "AWS::Events::EventBus": { nameProperty: "Name", options: { maxLength: 256 } },
485
+ "AWS::Kinesis::Stream": { nameProperty: "Name", options: { maxLength: 128 } },
486
+ "AWS::StepFunctions::StateMachine": {
487
+ nameProperty: "StateMachineName",
488
+ options: { maxLength: 80 }
489
+ },
490
+ "AWS::SecretsManager::Secret": {
491
+ nameProperty: "Name",
492
+ options: { maxLength: 512, allowedPattern: /[^a-zA-Z0-9-/_]/g }
493
+ },
494
+ "AWS::SSM::Parameter": { nameProperty: "Name", options: { maxLength: 2048 } },
495
+ "AWS::Cognito::UserPool": { nameProperty: "UserPoolName", options: { maxLength: 128 } },
496
+ "AWS::ElastiCache::SubnetGroup": {
497
+ nameProperty: "CacheSubnetGroupName",
498
+ options: { maxLength: 255, lowercase: true }
499
+ },
500
+ "AWS::ElastiCache::CacheCluster": {
501
+ nameProperty: "ClusterName",
502
+ options: { maxLength: 40, lowercase: true }
503
+ },
504
+ "AWS::RDS::DBSubnetGroup": {
505
+ nameProperty: "DBSubnetGroupName",
506
+ options: { maxLength: 255, lowercase: true }
507
+ },
508
+ "AWS::RDS::DBCluster": {
509
+ nameProperty: "DBClusterIdentifier",
510
+ options: { maxLength: 63, lowercase: true }
511
+ },
512
+ "AWS::RDS::DBInstance": {
513
+ nameProperty: "DBInstanceIdentifier",
514
+ options: { maxLength: 63, lowercase: true }
515
+ },
516
+ "AWS::ElasticLoadBalancingV2::LoadBalancer": {
517
+ nameProperty: "Name",
518
+ options: { maxLength: 32 }
519
+ },
520
+ "AWS::ElasticLoadBalancingV2::TargetGroup": {
521
+ nameProperty: "Name",
522
+ options: { maxLength: 32 }
523
+ },
524
+ "AWS::WAFv2::WebACL": { nameProperty: "Name", options: { maxLength: 128 } },
525
+ "AWS::CodeBuild::Project": { nameProperty: "Name", options: { maxLength: 255 } },
526
+ "AWS::S3Express::DirectoryBucket": {
527
+ nameProperty: "BucketName",
528
+ options: { maxLength: 63, lowercase: true }
529
+ }
530
+ };
531
+ function applyDefaultNameForFallback(logicalId, resourceType, properties) {
532
+ const rule = FALLBACK_NAME_RULES[resourceType];
533
+ if (!rule)
534
+ return properties;
535
+ if (properties[rule.nameProperty])
536
+ return properties;
537
+ const generatedName = generateResourceName(logicalId, rule.options);
538
+ return {
539
+ ...properties,
540
+ [rule.nameProperty]: generatedName
541
+ };
542
+ }
543
+
435
544
  // src/utils/live-renderer.ts
436
545
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
437
546
  var FRAME_INTERVAL_MS = 80;
438
547
  var ESC = "\x1B[";
548
+ function scopedKey(id, stackName) {
549
+ return stackName ? `${stackName}:${id}` : id;
550
+ }
439
551
  var LiveRenderer = class {
440
552
  constructor(stream = process.stdout) {
441
553
  this.stream = stream;
@@ -489,12 +601,14 @@ var LiveRenderer = class {
489
601
  this.active = false;
490
602
  }
491
603
  addTask(id, label) {
492
- this.tasks.set(id, { label, startedAt: Date.now() });
604
+ const stackName = getCurrentStackName();
605
+ this.tasks.set(scopedKey(id, stackName), { label, startedAt: Date.now(), stackName });
493
606
  if (this.active)
494
607
  this.draw();
495
608
  }
496
609
  removeTask(id) {
497
- if (!this.tasks.delete(id))
610
+ const stackName = getCurrentStackName();
611
+ if (!this.tasks.delete(scopedKey(id, stackName)))
498
612
  return;
499
613
  if (this.active)
500
614
  this.draw();
@@ -530,11 +644,16 @@ var LiveRenderer = class {
530
644
  return;
531
645
  const frame = SPINNER_FRAMES[this.spinnerIndex % SPINNER_FRAMES.length];
532
646
  this.spinnerIndex++;
647
+ const distinctStacks = /* @__PURE__ */ new Set();
648
+ for (const task of this.tasks.values())
649
+ distinctStacks.add(task.stackName);
650
+ const showStackPrefix = distinctStacks.size > 1;
533
651
  const cols = this.stream.columns ?? 80;
534
652
  const lines = [];
535
653
  for (const task of this.tasks.values()) {
536
654
  const elapsed = ((Date.now() - task.startedAt) / 1e3).toFixed(1);
537
- const raw = ` ${frame} ${task.label} (${elapsed}s)`;
655
+ const prefix = showStackPrefix && task.stackName ? `[${task.stackName}] ` : "";
656
+ const raw = ` ${frame} ${prefix}${task.label} (${elapsed}s)`;
538
657
  lines.push(this.truncate(raw, cols));
539
658
  }
540
659
  this.stream.write(lines.join("\n") + "\n");
@@ -567,6 +686,13 @@ function getLiveRenderer() {
567
686
  return globalRenderer;
568
687
  }
569
688
 
689
+ // src/utils/stack-context.ts
690
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
691
+ var outputBufferStore = new AsyncLocalStorage2();
692
+ function getCurrentStackOutputBuffer() {
693
+ return outputBufferStore.getStore();
694
+ }
695
+
570
696
  // src/utils/logger.ts
571
697
  var colors = {
572
698
  reset: "\x1B[0m",
@@ -621,28 +747,48 @@ var ConsoleLogger = class {
621
747
  }
622
748
  return `${message}${formattedArgs}`;
623
749
  }
750
+ /**
751
+ * Route a formatted log line. When a per-stack output buffer is active in
752
+ * the current async context (parallel multi-stack deploy), capture the
753
+ * line into the buffer so it can be flushed as one atomic block when the
754
+ * stack finishes. Otherwise fall through to the live renderer / console
755
+ * as before.
756
+ */
757
+ emit(level, formatted) {
758
+ const buffer = getCurrentStackOutputBuffer();
759
+ if (buffer) {
760
+ buffer.lines.push(formatted);
761
+ return;
762
+ }
763
+ getLiveRenderer().printAbove(() => {
764
+ if (level === "error")
765
+ console.error(formatted);
766
+ else if (level === "warn")
767
+ console.warn(formatted);
768
+ else if (level === "info")
769
+ console.info(formatted);
770
+ else
771
+ console.debug(formatted);
772
+ });
773
+ }
624
774
  debug(message, ...args) {
625
775
  if (this.shouldLog("debug")) {
626
- const formatted = this.formatMessage("debug", message, ...args);
627
- getLiveRenderer().printAbove(() => console.debug(formatted));
776
+ this.emit("debug", this.formatMessage("debug", message, ...args));
628
777
  }
629
778
  }
630
779
  info(message, ...args) {
631
780
  if (this.shouldLog("info")) {
632
- const formatted = this.formatMessage("info", message, ...args);
633
- getLiveRenderer().printAbove(() => console.info(formatted));
781
+ this.emit("info", this.formatMessage("info", message, ...args));
634
782
  }
635
783
  }
636
784
  warn(message, ...args) {
637
785
  if (this.shouldLog("warn")) {
638
- const formatted = this.formatMessage("warn", message, ...args);
639
- getLiveRenderer().printAbove(() => console.warn(formatted));
786
+ this.emit("warn", this.formatMessage("warn", message, ...args));
640
787
  }
641
788
  }
642
789
  error(message, ...args) {
643
790
  if (this.shouldLog("error")) {
644
- const formatted = this.formatMessage("error", message, ...args);
645
- getLiveRenderer().printAbove(() => console.error(formatted));
791
+ this.emit("error", this.formatMessage("error", message, ...args));
646
792
  }
647
793
  }
648
794
  /**
@@ -7123,112 +7269,6 @@ import {
7123
7269
  } from "@aws-sdk/client-iam";
7124
7270
  init_aws_clients();
7125
7271
 
7126
- // src/provisioning/resource-name.ts
7127
- import { AsyncLocalStorage } from "node:async_hooks";
7128
- import { createHash } from "node:crypto";
7129
- var stackNameStore = new AsyncLocalStorage();
7130
- function withStackName(stackName, fn) {
7131
- return stackNameStore.run(stackName, fn);
7132
- }
7133
- function generateResourceName(name, options) {
7134
- const { maxLength, lowercase = false, allowedPattern = /[^a-zA-Z0-9-]/g } = options;
7135
- const currentStackName = stackNameStore.getStore();
7136
- const fullName = currentStackName ? `${currentStackName}-${name}` : name;
7137
- let sanitized = lowercase ? fullName.toLowerCase() : fullName;
7138
- sanitized = sanitized.replace(allowedPattern, "-");
7139
- sanitized = sanitized.replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "");
7140
- if (sanitized.length <= maxLength) {
7141
- return sanitized;
7142
- }
7143
- const hash = createHash("sha256").update(fullName).digest("hex").substring(0, 8);
7144
- const maxPrefixLength = maxLength - hash.length - 1;
7145
- const prefix = sanitized.substring(0, maxPrefixLength).replace(/-+$/, "");
7146
- return `${prefix}-${hash}`;
7147
- }
7148
- var FALLBACK_NAME_RULES = {
7149
- "AWS::S3::Bucket": { nameProperty: "BucketName", options: { maxLength: 63, lowercase: true } },
7150
- "AWS::SQS::Queue": { nameProperty: "QueueName", options: { maxLength: 80 } },
7151
- "AWS::SNS::Topic": { nameProperty: "TopicName", options: { maxLength: 256 } },
7152
- "AWS::Lambda::Function": { nameProperty: "FunctionName", options: { maxLength: 64 } },
7153
- "AWS::Lambda::LayerVersion": { nameProperty: "LayerName", options: { maxLength: 64 } },
7154
- "AWS::IAM::Role": { nameProperty: "RoleName", options: { maxLength: 64 } },
7155
- "AWS::IAM::Policy": { nameProperty: "PolicyName", options: { maxLength: 64 } },
7156
- "AWS::IAM::User": { nameProperty: "UserName", options: { maxLength: 64 } },
7157
- "AWS::IAM::Group": { nameProperty: "GroupName", options: { maxLength: 128 } },
7158
- "AWS::IAM::InstanceProfile": {
7159
- nameProperty: "InstanceProfileName",
7160
- options: { maxLength: 128 }
7161
- },
7162
- "AWS::DynamoDB::Table": { nameProperty: "TableName", options: { maxLength: 255 } },
7163
- "AWS::ECR::Repository": {
7164
- nameProperty: "RepositoryName",
7165
- options: { maxLength: 256, lowercase: true }
7166
- },
7167
- "AWS::ECS::Cluster": { nameProperty: "ClusterName", options: { maxLength: 255 } },
7168
- "AWS::ECS::Service": { nameProperty: "ServiceName", options: { maxLength: 255 } },
7169
- "AWS::Logs::LogGroup": { nameProperty: "LogGroupName", options: { maxLength: 512 } },
7170
- "AWS::CloudWatch::Alarm": { nameProperty: "AlarmName", options: { maxLength: 256 } },
7171
- "AWS::Events::Rule": { nameProperty: "Name", options: { maxLength: 64 } },
7172
- "AWS::Events::EventBus": { nameProperty: "Name", options: { maxLength: 256 } },
7173
- "AWS::Kinesis::Stream": { nameProperty: "Name", options: { maxLength: 128 } },
7174
- "AWS::StepFunctions::StateMachine": {
7175
- nameProperty: "StateMachineName",
7176
- options: { maxLength: 80 }
7177
- },
7178
- "AWS::SecretsManager::Secret": {
7179
- nameProperty: "Name",
7180
- options: { maxLength: 512, allowedPattern: /[^a-zA-Z0-9-/_]/g }
7181
- },
7182
- "AWS::SSM::Parameter": { nameProperty: "Name", options: { maxLength: 2048 } },
7183
- "AWS::Cognito::UserPool": { nameProperty: "UserPoolName", options: { maxLength: 128 } },
7184
- "AWS::ElastiCache::SubnetGroup": {
7185
- nameProperty: "CacheSubnetGroupName",
7186
- options: { maxLength: 255, lowercase: true }
7187
- },
7188
- "AWS::ElastiCache::CacheCluster": {
7189
- nameProperty: "ClusterName",
7190
- options: { maxLength: 40, lowercase: true }
7191
- },
7192
- "AWS::RDS::DBSubnetGroup": {
7193
- nameProperty: "DBSubnetGroupName",
7194
- options: { maxLength: 255, lowercase: true }
7195
- },
7196
- "AWS::RDS::DBCluster": {
7197
- nameProperty: "DBClusterIdentifier",
7198
- options: { maxLength: 63, lowercase: true }
7199
- },
7200
- "AWS::RDS::DBInstance": {
7201
- nameProperty: "DBInstanceIdentifier",
7202
- options: { maxLength: 63, lowercase: true }
7203
- },
7204
- "AWS::ElasticLoadBalancingV2::LoadBalancer": {
7205
- nameProperty: "Name",
7206
- options: { maxLength: 32 }
7207
- },
7208
- "AWS::ElasticLoadBalancingV2::TargetGroup": {
7209
- nameProperty: "Name",
7210
- options: { maxLength: 32 }
7211
- },
7212
- "AWS::WAFv2::WebACL": { nameProperty: "Name", options: { maxLength: 128 } },
7213
- "AWS::CodeBuild::Project": { nameProperty: "Name", options: { maxLength: 255 } },
7214
- "AWS::S3Express::DirectoryBucket": {
7215
- nameProperty: "BucketName",
7216
- options: { maxLength: 63, lowercase: true }
7217
- }
7218
- };
7219
- function applyDefaultNameForFallback(logicalId, resourceType, properties) {
7220
- const rule = FALLBACK_NAME_RULES[resourceType];
7221
- if (!rule)
7222
- return properties;
7223
- if (properties[rule.nameProperty])
7224
- return properties;
7225
- const generatedName = generateResourceName(logicalId, rule.options);
7226
- return {
7227
- ...properties,
7228
- [rule.nameProperty]: generatedName
7229
- };
7230
- }
7231
-
7232
7272
  // src/provisioning/import-helpers.ts
7233
7273
  function readNameProperty(input, propertyName) {
7234
7274
  const value = input.properties?.[propertyName];