@go-to-k/cdkd 0.3.6 → 0.4.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/README.md +7 -1
- package/dist/cli.js +239 -40
- package/dist/cli.js.map +4 -4
- package/dist/go-to-k-cdkd-0.4.0.tgz +0 -0
- package/dist/index.js +165 -9
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/dist/go-to-k-cdkd-0.3.6.tgz +0 -0
|
Binary file
|
package/dist/index.js
CHANGED
|
@@ -432,6 +432,141 @@ var init_aws_clients = __esm({
|
|
|
432
432
|
}
|
|
433
433
|
});
|
|
434
434
|
|
|
435
|
+
// src/utils/live-renderer.ts
|
|
436
|
+
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
437
|
+
var FRAME_INTERVAL_MS = 80;
|
|
438
|
+
var ESC = "\x1B[";
|
|
439
|
+
var LiveRenderer = class {
|
|
440
|
+
constructor(stream = process.stdout) {
|
|
441
|
+
this.stream = stream;
|
|
442
|
+
}
|
|
443
|
+
tasks = /* @__PURE__ */ new Map();
|
|
444
|
+
active = false;
|
|
445
|
+
spinnerIndex = 0;
|
|
446
|
+
interval = null;
|
|
447
|
+
linesDrawn = 0;
|
|
448
|
+
cursorHidden = false;
|
|
449
|
+
exitListener = null;
|
|
450
|
+
isActive() {
|
|
451
|
+
return this.active;
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Enable the live renderer. No-op if stdout is not a TTY or if
|
|
455
|
+
* `CDKD_NO_LIVE=1`. Returns true if successfully enabled.
|
|
456
|
+
*/
|
|
457
|
+
start() {
|
|
458
|
+
if (this.active)
|
|
459
|
+
return true;
|
|
460
|
+
if (!this.stream.isTTY)
|
|
461
|
+
return false;
|
|
462
|
+
if (process.env["CDKD_NO_LIVE"] === "1")
|
|
463
|
+
return false;
|
|
464
|
+
this.active = true;
|
|
465
|
+
this.hideCursor();
|
|
466
|
+
if (!this.exitListener) {
|
|
467
|
+
this.exitListener = () => this.showCursor();
|
|
468
|
+
process.on("exit", this.exitListener);
|
|
469
|
+
}
|
|
470
|
+
this.interval = setInterval(() => this.draw(), FRAME_INTERVAL_MS);
|
|
471
|
+
if (typeof this.interval.unref === "function")
|
|
472
|
+
this.interval.unref();
|
|
473
|
+
return true;
|
|
474
|
+
}
|
|
475
|
+
stop() {
|
|
476
|
+
if (!this.active)
|
|
477
|
+
return;
|
|
478
|
+
if (this.interval) {
|
|
479
|
+
clearInterval(this.interval);
|
|
480
|
+
this.interval = null;
|
|
481
|
+
}
|
|
482
|
+
this.clear();
|
|
483
|
+
this.showCursor();
|
|
484
|
+
if (this.exitListener) {
|
|
485
|
+
process.removeListener("exit", this.exitListener);
|
|
486
|
+
this.exitListener = null;
|
|
487
|
+
}
|
|
488
|
+
this.tasks.clear();
|
|
489
|
+
this.active = false;
|
|
490
|
+
}
|
|
491
|
+
addTask(id, label) {
|
|
492
|
+
this.tasks.set(id, { label, startedAt: Date.now() });
|
|
493
|
+
if (this.active)
|
|
494
|
+
this.draw();
|
|
495
|
+
}
|
|
496
|
+
removeTask(id) {
|
|
497
|
+
if (!this.tasks.delete(id))
|
|
498
|
+
return;
|
|
499
|
+
if (this.active)
|
|
500
|
+
this.draw();
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Print content above the live area. Clears the live area, runs the writer,
|
|
504
|
+
* then redraws the live area. When the renderer is inactive, the writer
|
|
505
|
+
* runs directly so callers can use this unconditionally.
|
|
506
|
+
*/
|
|
507
|
+
printAbove(write) {
|
|
508
|
+
if (!this.active) {
|
|
509
|
+
write();
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
this.clear();
|
|
513
|
+
write();
|
|
514
|
+
this.draw();
|
|
515
|
+
}
|
|
516
|
+
clear() {
|
|
517
|
+
if (this.linesDrawn === 0)
|
|
518
|
+
return;
|
|
519
|
+
this.stream.write("\r");
|
|
520
|
+
for (let i = 0; i < this.linesDrawn; i++) {
|
|
521
|
+
this.stream.write(`${ESC}1A${ESC}2K`);
|
|
522
|
+
}
|
|
523
|
+
this.linesDrawn = 0;
|
|
524
|
+
}
|
|
525
|
+
draw() {
|
|
526
|
+
if (!this.active)
|
|
527
|
+
return;
|
|
528
|
+
this.clear();
|
|
529
|
+
if (this.tasks.size === 0)
|
|
530
|
+
return;
|
|
531
|
+
const frame = SPINNER_FRAMES[this.spinnerIndex % SPINNER_FRAMES.length];
|
|
532
|
+
this.spinnerIndex++;
|
|
533
|
+
const cols = this.stream.columns ?? 80;
|
|
534
|
+
const lines = [];
|
|
535
|
+
for (const task of this.tasks.values()) {
|
|
536
|
+
const elapsed = ((Date.now() - task.startedAt) / 1e3).toFixed(1);
|
|
537
|
+
const raw = ` ${frame} ${task.label} (${elapsed}s)`;
|
|
538
|
+
lines.push(this.truncate(raw, cols));
|
|
539
|
+
}
|
|
540
|
+
this.stream.write(lines.join("\n") + "\n");
|
|
541
|
+
this.linesDrawn = lines.length;
|
|
542
|
+
}
|
|
543
|
+
truncate(s, maxLen) {
|
|
544
|
+
if (s.length <= maxLen)
|
|
545
|
+
return s;
|
|
546
|
+
if (maxLen <= 1)
|
|
547
|
+
return "\u2026";
|
|
548
|
+
return s.substring(0, maxLen - 1) + "\u2026";
|
|
549
|
+
}
|
|
550
|
+
hideCursor() {
|
|
551
|
+
if (this.cursorHidden)
|
|
552
|
+
return;
|
|
553
|
+
this.stream.write(`${ESC}?25l`);
|
|
554
|
+
this.cursorHidden = true;
|
|
555
|
+
}
|
|
556
|
+
showCursor() {
|
|
557
|
+
if (!this.cursorHidden)
|
|
558
|
+
return;
|
|
559
|
+
this.stream.write(`${ESC}?25h`);
|
|
560
|
+
this.cursorHidden = false;
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
var globalRenderer = null;
|
|
564
|
+
function getLiveRenderer() {
|
|
565
|
+
if (!globalRenderer)
|
|
566
|
+
globalRenderer = new LiveRenderer();
|
|
567
|
+
return globalRenderer;
|
|
568
|
+
}
|
|
569
|
+
|
|
435
570
|
// src/utils/logger.ts
|
|
436
571
|
var colors = {
|
|
437
572
|
reset: "\x1B[0m",
|
|
@@ -488,22 +623,26 @@ var ConsoleLogger = class {
|
|
|
488
623
|
}
|
|
489
624
|
debug(message, ...args) {
|
|
490
625
|
if (this.shouldLog("debug")) {
|
|
491
|
-
|
|
626
|
+
const formatted = this.formatMessage("debug", message, ...args);
|
|
627
|
+
getLiveRenderer().printAbove(() => console.debug(formatted));
|
|
492
628
|
}
|
|
493
629
|
}
|
|
494
630
|
info(message, ...args) {
|
|
495
631
|
if (this.shouldLog("info")) {
|
|
496
|
-
|
|
632
|
+
const formatted = this.formatMessage("info", message, ...args);
|
|
633
|
+
getLiveRenderer().printAbove(() => console.info(formatted));
|
|
497
634
|
}
|
|
498
635
|
}
|
|
499
636
|
warn(message, ...args) {
|
|
500
637
|
if (this.shouldLog("warn")) {
|
|
501
|
-
|
|
638
|
+
const formatted = this.formatMessage("warn", message, ...args);
|
|
639
|
+
getLiveRenderer().printAbove(() => console.warn(formatted));
|
|
502
640
|
}
|
|
503
641
|
}
|
|
504
642
|
error(message, ...args) {
|
|
505
643
|
if (this.shouldLog("error")) {
|
|
506
|
-
|
|
644
|
+
const formatted = this.formatMessage("error", message, ...args);
|
|
645
|
+
getLiveRenderer().printAbove(() => console.error(formatted));
|
|
507
646
|
}
|
|
508
647
|
}
|
|
509
648
|
/**
|
|
@@ -934,6 +1073,7 @@ var AssemblyReader = class {
|
|
|
934
1073
|
}
|
|
935
1074
|
return {
|
|
936
1075
|
stackName,
|
|
1076
|
+
displayName: artifact.displayName ?? stackName,
|
|
937
1077
|
artifactId,
|
|
938
1078
|
template,
|
|
939
1079
|
assetManifestPath,
|
|
@@ -7247,11 +7387,15 @@ var DeployEngine = class {
|
|
|
7247
7387
|
this.logger.debug(`Starting deployment for stack: ${stackName}`);
|
|
7248
7388
|
setCurrentStackName(stackName);
|
|
7249
7389
|
await this.lockManager.acquireLockWithRetry(stackName, void 0, "deploy");
|
|
7390
|
+
const renderer = getLiveRenderer();
|
|
7391
|
+
renderer.start();
|
|
7250
7392
|
this.interrupted = false;
|
|
7251
7393
|
const sigintHandler = () => {
|
|
7252
|
-
|
|
7253
|
-
|
|
7254
|
-
|
|
7394
|
+
renderer.printAbove(() => {
|
|
7395
|
+
process.stderr.write(
|
|
7396
|
+
"\nInterrupted \u2014 saving partial state after current operations complete...\n"
|
|
7397
|
+
);
|
|
7398
|
+
});
|
|
7255
7399
|
this.interrupted = true;
|
|
7256
7400
|
};
|
|
7257
7401
|
process.on("SIGINT", sigintHandler);
|
|
@@ -7366,6 +7510,7 @@ var DeployEngine = class {
|
|
|
7366
7510
|
durationMs
|
|
7367
7511
|
};
|
|
7368
7512
|
} finally {
|
|
7513
|
+
renderer.stop();
|
|
7369
7514
|
process.removeListener("SIGINT", sigintHandler);
|
|
7370
7515
|
try {
|
|
7371
7516
|
await this.lockManager.releaseLock(stackName);
|
|
@@ -7794,6 +7939,10 @@ var DeployEngine = class {
|
|
|
7794
7939
|
async provisionResource(logicalId, change, stateResources, stackName, template, parameterValues, conditions, counts, progress) {
|
|
7795
7940
|
const resourceType = change.resourceType;
|
|
7796
7941
|
const provider = this.providerRegistry.getProvider(resourceType);
|
|
7942
|
+
const renderer = getLiveRenderer();
|
|
7943
|
+
const needsReplacement = change.changeType === "UPDATE" && (change.propertyChanges?.some((pc) => pc.requiresReplacement) ?? false);
|
|
7944
|
+
const verb = change.changeType === "CREATE" ? "Creating" : change.changeType === "DELETE" ? "Deleting" : needsReplacement ? "Replacing" : "Updating";
|
|
7945
|
+
renderer.addTask(logicalId, `${verb} ${logicalId} (${resourceType})`);
|
|
7797
7946
|
try {
|
|
7798
7947
|
switch (change.changeType) {
|
|
7799
7948
|
case "CREATE": {
|
|
@@ -7825,6 +7974,7 @@ var DeployEngine = class {
|
|
|
7825
7974
|
if (progress)
|
|
7826
7975
|
progress.current++;
|
|
7827
7976
|
const createPrefix = progress ? `[${progress.current}/${progress.total}] ` : " ";
|
|
7977
|
+
renderer.removeTask(logicalId);
|
|
7828
7978
|
this.logger.info(`${createPrefix}\u2705 ${logicalId} (${resourceType}) created`);
|
|
7829
7979
|
break;
|
|
7830
7980
|
}
|
|
@@ -7852,9 +8002,9 @@ var DeployEngine = class {
|
|
|
7852
8002
|
counts.skipped++;
|
|
7853
8003
|
break;
|
|
7854
8004
|
}
|
|
7855
|
-
const
|
|
8005
|
+
const needsReplacement2 = change.propertyChanges?.some((pc) => pc.requiresReplacement);
|
|
7856
8006
|
const dependencies = this.extractAllDependencies(template, logicalId);
|
|
7857
|
-
if (
|
|
8007
|
+
if (needsReplacement2) {
|
|
7858
8008
|
const replacedProps = change.propertyChanges?.filter((pc) => pc.requiresReplacement).map((pc) => pc.path).join(", ");
|
|
7859
8009
|
this.logger.info(
|
|
7860
8010
|
`Replacing ${logicalId} (${resourceType}) - immutable properties changed: ${replacedProps}`
|
|
@@ -7898,6 +8048,7 @@ var DeployEngine = class {
|
|
|
7898
8048
|
if (progress)
|
|
7899
8049
|
progress.current++;
|
|
7900
8050
|
const replacePrefix = progress ? `[${progress.current}/${progress.total}] ` : " ";
|
|
8051
|
+
renderer.removeTask(logicalId);
|
|
7901
8052
|
this.logger.info(`${replacePrefix}\u2705 ${logicalId} (${resourceType}) replaced`);
|
|
7902
8053
|
} else {
|
|
7903
8054
|
this.logger.debug(`Updating ${logicalId} (${resourceType})`);
|
|
@@ -7973,6 +8124,7 @@ var DeployEngine = class {
|
|
|
7973
8124
|
if (progress)
|
|
7974
8125
|
progress.current++;
|
|
7975
8126
|
const updatePrefix = progress ? `[${progress.current}/${progress.total}] ` : " ";
|
|
8127
|
+
renderer.removeTask(logicalId);
|
|
7976
8128
|
this.logger.info(`${updatePrefix}\u2705 ${logicalId} (${resourceType}) updated`);
|
|
7977
8129
|
}
|
|
7978
8130
|
break;
|
|
@@ -8018,11 +8170,13 @@ var DeployEngine = class {
|
|
|
8018
8170
|
if (progress)
|
|
8019
8171
|
progress.current++;
|
|
8020
8172
|
const deletePrefix = progress ? `[${progress.current}/${progress.total}] ` : " ";
|
|
8173
|
+
renderer.removeTask(logicalId);
|
|
8021
8174
|
this.logger.info(`${deletePrefix}\u2705 ${logicalId} (${resourceType}) deleted`);
|
|
8022
8175
|
break;
|
|
8023
8176
|
}
|
|
8024
8177
|
}
|
|
8025
8178
|
} catch (error) {
|
|
8179
|
+
renderer.removeTask(logicalId);
|
|
8026
8180
|
const message = error instanceof Error ? error.message : String(error);
|
|
8027
8181
|
this.logger.error(`Failed to ${change.changeType.toLowerCase()} ${logicalId}: ${message}`);
|
|
8028
8182
|
throw new ProvisioningError(
|
|
@@ -8032,6 +8186,8 @@ var DeployEngine = class {
|
|
|
8032
8186
|
stateResources[logicalId]?.physicalId,
|
|
8033
8187
|
error instanceof Error ? error : void 0
|
|
8034
8188
|
);
|
|
8189
|
+
} finally {
|
|
8190
|
+
renderer.removeTask(logicalId);
|
|
8035
8191
|
}
|
|
8036
8192
|
}
|
|
8037
8193
|
/**
|