sidekick-docker 0.1.3 → 0.1.4
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/sidekick-docker.mjs +72 -19
- package/package.json +1 -1
package/dist/sidekick-docker.mjs
CHANGED
|
@@ -77965,6 +77965,29 @@ var import_react37 = __toESM(require_react(), 1);
|
|
|
77965
77965
|
var import_sidekick_docker_shared13 = __toESM(require_dist(), 1);
|
|
77966
77966
|
import { spawnSync } from "child_process";
|
|
77967
77967
|
|
|
77968
|
+
// src/utils/clipboard.ts
|
|
77969
|
+
import { execSync } from "child_process";
|
|
77970
|
+
function copyToClipboard(text) {
|
|
77971
|
+
try {
|
|
77972
|
+
if (process.platform === "darwin") {
|
|
77973
|
+
execSync("pbcopy", { input: text });
|
|
77974
|
+
} else {
|
|
77975
|
+
try {
|
|
77976
|
+
execSync("xclip -selection clipboard", { input: text });
|
|
77977
|
+
} catch {
|
|
77978
|
+
try {
|
|
77979
|
+
execSync("xsel --clipboard --input", { input: text });
|
|
77980
|
+
} catch {
|
|
77981
|
+
execSync("wl-copy", { input: text });
|
|
77982
|
+
}
|
|
77983
|
+
}
|
|
77984
|
+
}
|
|
77985
|
+
return true;
|
|
77986
|
+
} catch {
|
|
77987
|
+
return false;
|
|
77988
|
+
}
|
|
77989
|
+
}
|
|
77990
|
+
|
|
77968
77991
|
// src/dashboard/DockerState.ts
|
|
77969
77992
|
var import_sidekick_docker_shared = __toESM(require_dist(), 1);
|
|
77970
77993
|
var DockerState = class {
|
|
@@ -78316,6 +78339,8 @@ var ContainersPanel = class {
|
|
|
78316
78339
|
onAction;
|
|
78317
78340
|
onError;
|
|
78318
78341
|
onExec;
|
|
78342
|
+
onCopyLogs;
|
|
78343
|
+
lastMetrics = null;
|
|
78319
78344
|
constructor(client, onAction, onError) {
|
|
78320
78345
|
this.client = client;
|
|
78321
78346
|
this.onAction = onAction;
|
|
@@ -78324,6 +78349,9 @@ var ContainersPanel = class {
|
|
|
78324
78349
|
setOnExec(handler) {
|
|
78325
78350
|
this.onExec = handler;
|
|
78326
78351
|
}
|
|
78352
|
+
setOnCopyLogs(handler) {
|
|
78353
|
+
this.onCopyLogs = handler;
|
|
78354
|
+
}
|
|
78327
78355
|
detailTabs = [
|
|
78328
78356
|
{
|
|
78329
78357
|
label: "Logs",
|
|
@@ -78453,10 +78481,11 @@ var ContainersPanel = class {
|
|
|
78453
78481
|
}
|
|
78454
78482
|
];
|
|
78455
78483
|
getItems(metrics) {
|
|
78484
|
+
this.lastMetrics = metrics;
|
|
78456
78485
|
return metrics.containers.map((c) => {
|
|
78457
78486
|
const uptime = compactUptime(c.status);
|
|
78458
78487
|
const portHint = c.state === "running" && c.ports.length > 0 ? `:${c.ports[0].hostPort || c.ports[0].containerPort}` : "";
|
|
78459
|
-
const namePart = portHint ? `${(0, import_sidekick_docker_shared3.truncate)(c.name,
|
|
78488
|
+
const namePart = portHint ? `${(0, import_sidekick_docker_shared3.truncate)(c.name, 34)} ${portHint}` : (0, import_sidekick_docker_shared3.truncate)(c.name, 38);
|
|
78460
78489
|
return {
|
|
78461
78490
|
id: c.id,
|
|
78462
78491
|
label: `${(0, import_sidekick_docker_shared3.stateIcon)(c.state)} ${namePart}`,
|
|
@@ -78515,6 +78544,23 @@ var ContainersPanel = class {
|
|
|
78515
78544
|
this.onExec?.(c.id);
|
|
78516
78545
|
},
|
|
78517
78546
|
condition: (item) => item.data.state === "running"
|
|
78547
|
+
},
|
|
78548
|
+
{
|
|
78549
|
+
key: "c",
|
|
78550
|
+
label: "Copy Logs",
|
|
78551
|
+
handler: () => {
|
|
78552
|
+
if (!this.lastMetrics || !this.onCopyLogs) return;
|
|
78553
|
+
const logs = this.lastMetrics.selectedContainerLogs;
|
|
78554
|
+
const query = this.lastMetrics.logFilterString;
|
|
78555
|
+
const mode = this.lastMetrics.logFilterMode;
|
|
78556
|
+
let lines;
|
|
78557
|
+
if (query) {
|
|
78558
|
+
lines = logs.filter((l) => (0, import_sidekick_docker_shared4.filterLine)(l.message, query, mode).matched).map((l) => l.message);
|
|
78559
|
+
} else {
|
|
78560
|
+
lines = logs.map((l) => l.message);
|
|
78561
|
+
}
|
|
78562
|
+
this.onCopyLogs(lines.join("\n"));
|
|
78563
|
+
}
|
|
78518
78564
|
}
|
|
78519
78565
|
];
|
|
78520
78566
|
}
|
|
@@ -78600,7 +78646,7 @@ var ServicesPanel = class {
|
|
|
78600
78646
|
const icon = (0, import_sidekick_docker_shared3.stateIcon)(service.state);
|
|
78601
78647
|
items.push({
|
|
78602
78648
|
id: `service:${project.name}:${service.name}`,
|
|
78603
|
-
label: ` ${icon} ${(0, import_sidekick_docker_shared3.truncate)(service.name,
|
|
78649
|
+
label: ` ${icon} ${(0, import_sidekick_docker_shared3.truncate)(service.name, 36)}`,
|
|
78604
78650
|
sortKey: sortKey++,
|
|
78605
78651
|
data: { type: "service", service },
|
|
78606
78652
|
iconColor: (0, import_sidekick_docker_shared3.stateColor)(service.state)
|
|
@@ -78709,7 +78755,7 @@ var ImagesPanel = class {
|
|
|
78709
78755
|
const icon = img.isDangling ? "\u25CB" : "\u25CF";
|
|
78710
78756
|
return {
|
|
78711
78757
|
id: img.id,
|
|
78712
|
-
label: `${icon} ${(0, import_sidekick_docker_shared3.truncate)(tag,
|
|
78758
|
+
label: `${icon} ${(0, import_sidekick_docker_shared3.truncate)(tag, 38)}`,
|
|
78713
78759
|
sortKey: img.isDangling ? 1 : 0,
|
|
78714
78760
|
data: img,
|
|
78715
78761
|
iconColor: img.isDangling ? "gray" : "#2B4C7E",
|
|
@@ -78780,7 +78826,7 @@ var VolumesPanel = class {
|
|
|
78780
78826
|
const icon = vol.isInUse ? "\u25CF" : "\u25CB";
|
|
78781
78827
|
return {
|
|
78782
78828
|
id: vol.name,
|
|
78783
|
-
label: `${icon} ${(0, import_sidekick_docker_shared3.truncate)(vol.name,
|
|
78829
|
+
label: `${icon} ${(0, import_sidekick_docker_shared3.truncate)(vol.name, 38)}`,
|
|
78784
78830
|
sortKey: vol.isInUse ? 0 : 1,
|
|
78785
78831
|
data: vol,
|
|
78786
78832
|
iconColor: vol.isInUse ? "green" : "gray",
|
|
@@ -78862,7 +78908,7 @@ var NetworksPanel = class {
|
|
|
78862
78908
|
const countLabel = net.containers.length > 0 ? `${net.containers.length}` : "";
|
|
78863
78909
|
return {
|
|
78864
78910
|
id: net.id,
|
|
78865
|
-
label: `${icon} ${(0, import_sidekick_docker_shared3.truncate)(net.name,
|
|
78911
|
+
label: `${icon} ${(0, import_sidekick_docker_shared3.truncate)(net.name, 38)}`,
|
|
78866
78912
|
sortKey: net.isDefault ? 0 : 1,
|
|
78867
78913
|
data: net,
|
|
78868
78914
|
iconColor: net.isDefault ? "#2B4C7E" : "gray",
|
|
@@ -79362,7 +79408,8 @@ function useKeyboardHandler(ctx) {
|
|
|
79362
79408
|
}
|
|
79363
79409
|
if (input === "z") {
|
|
79364
79410
|
dispatch({ type: "CYCLE_LAYOUT" });
|
|
79365
|
-
|
|
79411
|
+
const nextMode = state.layoutMode === "normal" ? "Wide" : state.layoutMode === "wide" ? "Expanded" : "Normal";
|
|
79412
|
+
addToast(`Layout: ${nextMode}`, "info");
|
|
79366
79413
|
return;
|
|
79367
79414
|
}
|
|
79368
79415
|
if (input === "/") {
|
|
@@ -79573,7 +79620,7 @@ function TabBar({ panels, activeIndex, layoutMode, phrase, panelCounts }) {
|
|
|
79573
79620
|
] }, panel.id);
|
|
79574
79621
|
}),
|
|
79575
79622
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { flexGrow: 1, marginLeft: 1, children: phrase && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "gray", wrap: "truncate", children: phrase }) }),
|
|
79576
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: layoutMode
|
|
79623
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: layoutMode !== "normal" ? "#2B4C7E" : "gray", children: `z: ${layoutMode === "expanded" ? "Expanded" : layoutMode === "wide" ? "Wide" : "Normal"} \u25B8` })
|
|
79577
79624
|
] });
|
|
79578
79625
|
}
|
|
79579
79626
|
|
|
@@ -79746,7 +79793,7 @@ var GLOBAL_BINDINGS = [
|
|
|
79746
79793
|
{ key: "g/G", label: "Jump to first / last" },
|
|
79747
79794
|
{ key: "Tab", label: "Toggle focus" },
|
|
79748
79795
|
{ key: "[/]", label: "Cycle detail tabs" },
|
|
79749
|
-
{ key: "z", label: "
|
|
79796
|
+
{ key: "z", label: "Cycle layout (Normal/Wide/Expanded)" },
|
|
79750
79797
|
{ key: "/", label: "Filter items" },
|
|
79751
79798
|
{ key: "x", label: "Actions menu" },
|
|
79752
79799
|
{ key: "V", label: "Version info" },
|
|
@@ -80147,6 +80194,7 @@ var ExecManager = class {
|
|
|
80147
80194
|
// src/dashboard/ink/Dashboard.tsx
|
|
80148
80195
|
var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
|
|
80149
80196
|
var SIDE_PANEL_WIDTH = 28;
|
|
80197
|
+
var SIDE_PANEL_WIDTH_WIDE = 42;
|
|
80150
80198
|
var MIN_SCREEN_WIDTH = 60;
|
|
80151
80199
|
var MIN_SCREEN_HEIGHT = 15;
|
|
80152
80200
|
var RESERVED_UI_ROWS = 5;
|
|
@@ -80174,7 +80222,7 @@ function reducer(state, action) {
|
|
|
80174
80222
|
return { ...state, detailTabIndex: next, detailScrollOffset: 0 };
|
|
80175
80223
|
}
|
|
80176
80224
|
case "CYCLE_LAYOUT": {
|
|
80177
|
-
const next = state.layoutMode === "normal" ? "expanded" : "normal";
|
|
80225
|
+
const next = state.layoutMode === "normal" ? "wide" : state.layoutMode === "wide" ? "expanded" : "normal";
|
|
80178
80226
|
return { ...state, layoutMode: next, focusTarget: next === "expanded" ? "detail" : state.focusTarget };
|
|
80179
80227
|
}
|
|
80180
80228
|
case "TOGGLE_FOCUS":
|
|
@@ -80261,17 +80309,19 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80261
80309
|
const execManagerRef = (0, import_react36.useRef)(null);
|
|
80262
80310
|
const [phrase, setPhrase] = import_react36.default.useState(() => (0, import_sidekick_docker_shared12.getRandomPhrase)());
|
|
80263
80311
|
const phraseTimerRef = (0, import_react36.useRef)(null);
|
|
80264
|
-
const
|
|
80312
|
+
const rotatePhraseRef = (0, import_react36.useRef)(void 0);
|
|
80313
|
+
rotatePhraseRef.current = () => {
|
|
80265
80314
|
setPhrase((0, import_sidekick_docker_shared12.getRandomPhrase)());
|
|
80266
80315
|
if (phraseTimerRef.current) clearTimeout(phraseTimerRef.current);
|
|
80267
|
-
phraseTimerRef.current = setTimeout(
|
|
80268
|
-
}
|
|
80316
|
+
phraseTimerRef.current = setTimeout(() => rotatePhraseRef.current?.(), 7e3);
|
|
80317
|
+
};
|
|
80318
|
+
const rotatePhrase = (0, import_react36.useCallback)(() => rotatePhraseRef.current?.(), []);
|
|
80269
80319
|
(0, import_react36.useEffect)(() => {
|
|
80270
|
-
phraseTimerRef.current = setTimeout(
|
|
80320
|
+
phraseTimerRef.current = setTimeout(() => rotatePhraseRef.current?.(), 7e3);
|
|
80271
80321
|
return () => {
|
|
80272
80322
|
if (phraseTimerRef.current) clearTimeout(phraseTimerRef.current);
|
|
80273
80323
|
};
|
|
80274
|
-
}, [
|
|
80324
|
+
}, []);
|
|
80275
80325
|
(0, import_react36.useEffect)(() => {
|
|
80276
80326
|
if (!execTriggerRef) return;
|
|
80277
80327
|
execTriggerRef.current = (containerId, containerName) => {
|
|
@@ -80336,7 +80386,7 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80336
80386
|
}, []);
|
|
80337
80387
|
const panel = panels[state.activePanelIndex];
|
|
80338
80388
|
const tooSmall = columns < MIN_SCREEN_WIDTH || rows < MIN_SCREEN_HEIGHT;
|
|
80339
|
-
const sideWidth = state.layoutMode === "expanded" ? 0 : SIDE_PANEL_WIDTH;
|
|
80389
|
+
const sideWidth = state.layoutMode === "expanded" ? 0 : state.layoutMode === "wide" ? SIDE_PANEL_WIDTH_WIDE : SIDE_PANEL_WIDTH;
|
|
80340
80390
|
const allItems = panel.getItems(metrics);
|
|
80341
80391
|
const totalItemCount = allItems.length;
|
|
80342
80392
|
const currentItems = (() => {
|
|
@@ -80473,8 +80523,8 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80473
80523
|
)
|
|
80474
80524
|
] })
|
|
80475
80525
|
] }),
|
|
80476
|
-
state.overlay === "help" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(HelpOverlay, { panels, activePanelIndex: state.activePanelIndex, version: "0.1.
|
|
80477
|
-
state.overlay === "version" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(VersionOverlay, { version: "0.1.
|
|
80526
|
+
state.overlay === "help" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(HelpOverlay, { panels, activePanelIndex: state.activePanelIndex, version: "0.1.4" }),
|
|
80527
|
+
state.overlay === "version" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(VersionOverlay, { version: "0.1.4" }),
|
|
80478
80528
|
state.overlay === "exec" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
80479
80529
|
ExecOverlay,
|
|
80480
80530
|
{
|
|
@@ -80491,7 +80541,7 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80491
80541
|
filterString: state.filterString,
|
|
80492
80542
|
containerCount: metrics.containers.length,
|
|
80493
80543
|
runningCount,
|
|
80494
|
-
version: "0.1.
|
|
80544
|
+
version: "0.1.4",
|
|
80495
80545
|
matchCount: state.filterString ? currentItems.length : void 0,
|
|
80496
80546
|
totalCount: state.filterString ? totalItemCount : void 0,
|
|
80497
80547
|
lastRefresh: metrics.lastRefresh
|
|
@@ -80650,6 +80700,9 @@ async function dashboardAction(_opts, cmd) {
|
|
|
80650
80700
|
onExecFallback(containerId);
|
|
80651
80701
|
}
|
|
80652
80702
|
});
|
|
80703
|
+
containersPanel.setOnCopyLogs((text) => {
|
|
80704
|
+
copyToClipboard(text);
|
|
80705
|
+
});
|
|
80653
80706
|
let renderTimer = null;
|
|
80654
80707
|
function getEnrichedMetrics() {
|
|
80655
80708
|
const m = state.getMetrics();
|
|
@@ -80773,7 +80826,7 @@ async function logsAction(container, opts) {
|
|
|
80773
80826
|
|
|
80774
80827
|
// src/cli.ts
|
|
80775
80828
|
var program2 = new Command();
|
|
80776
|
-
program2.name("sidekick-docker").description("Docker management TUI dashboard").version("0.1.
|
|
80829
|
+
program2.name("sidekick-docker").description("Docker management TUI dashboard").version("0.1.4").option("--socket <path>", "Docker socket path").action(async (_opts, cmd) => {
|
|
80777
80830
|
await dashboardAction(_opts, cmd);
|
|
80778
80831
|
});
|
|
80779
80832
|
program2.command("ps").description("List containers").option("-a, --all", "Show all containers (default: running only)", false).action(async (opts) => {
|