@matthesketh/fleet 1.1.0 → 1.6.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 +183 -251
- package/dist/adapters/detector/index.d.ts +8 -0
- package/dist/adapters/detector/index.js +54 -0
- package/dist/adapters/notifier/index.d.ts +2 -0
- package/dist/adapters/notifier/index.js +2 -0
- package/dist/adapters/notifier/stdout.d.ts +2 -0
- package/dist/adapters/notifier/stdout.js +8 -0
- package/dist/adapters/notifier/webhook.d.ts +9 -0
- package/dist/adapters/notifier/webhook.js +38 -0
- package/dist/adapters/runner/claude-cli.d.ts +7 -0
- package/dist/adapters/runner/claude-cli.js +231 -0
- package/dist/adapters/runner/mcp-call.d.ts +8 -0
- package/dist/adapters/runner/mcp-call.js +82 -0
- package/dist/adapters/runner/shell.d.ts +2 -0
- package/dist/adapters/runner/shell.js +103 -0
- package/dist/adapters/scheduler/systemd-timer.d.ts +17 -0
- package/dist/adapters/scheduler/systemd-timer.js +149 -0
- package/dist/adapters/signals/ci-status.d.ts +2 -0
- package/dist/adapters/signals/ci-status.js +79 -0
- package/dist/adapters/signals/container-up.d.ts +5 -0
- package/dist/adapters/signals/container-up.js +54 -0
- package/dist/adapters/signals/git-clean.d.ts +2 -0
- package/dist/adapters/signals/git-clean.js +55 -0
- package/dist/adapters/signals/index.d.ts +6 -0
- package/dist/adapters/signals/index.js +7 -0
- package/dist/adapters/types.d.ts +52 -0
- package/dist/adapters/types.js +1 -0
- package/dist/cli.js +43 -2
- package/dist/commands/add.js +0 -6
- package/dist/commands/boot-start.d.ts +1 -0
- package/dist/commands/boot-start.js +51 -0
- package/dist/commands/deploy.js +13 -0
- package/dist/commands/deps.js +5 -0
- package/dist/commands/egress.d.ts +1 -0
- package/dist/commands/egress.js +106 -0
- package/dist/commands/freeze.d.ts +4 -0
- package/dist/commands/freeze.js +64 -0
- package/dist/commands/logs.d.ts +1 -1
- package/dist/commands/logs.js +237 -8
- package/dist/commands/patch-systemd.d.ts +1 -0
- package/dist/commands/patch-systemd.js +126 -0
- package/dist/commands/rollback.d.ts +1 -0
- package/dist/commands/rollback.js +58 -0
- package/dist/commands/routine-run.d.ts +1 -0
- package/dist/commands/routine-run.js +122 -0
- package/dist/commands/routines.d.ts +1 -0
- package/dist/commands/routines.js +25 -0
- package/dist/commands/secrets.js +449 -16
- package/dist/commands/status.js +7 -3
- package/dist/commands/watchdog.d.ts +1 -1
- package/dist/commands/watchdog.js +16 -40
- package/dist/core/boot-refresh.d.ts +57 -0
- package/dist/core/boot-refresh.js +116 -0
- package/dist/core/deps/actors/pr-creator.js +11 -9
- package/dist/core/deps/collectors/docker-running.js +2 -2
- package/dist/core/deps/collectors/github-pr.js +5 -2
- package/dist/core/deps/collectors/npm.js +10 -5
- package/dist/core/deps/collectors/vulnerability.js +10 -6
- package/dist/core/deps/reporters/motd.js +1 -1
- package/dist/core/deps/reporters/telegram.js +2 -29
- package/dist/core/docker.js +45 -15
- package/dist/core/egress.d.ts +41 -0
- package/dist/core/egress.js +161 -0
- package/dist/core/exec.d.ts +7 -1
- package/dist/core/exec.js +25 -17
- package/dist/core/git.d.ts +1 -0
- package/dist/core/git.js +36 -23
- package/dist/core/github.js +27 -8
- package/dist/core/health.d.ts +3 -0
- package/dist/core/health.js +15 -3
- package/dist/core/logs-multi.d.ts +73 -0
- package/dist/core/logs-multi.js +163 -0
- package/dist/core/logs-policy.d.ts +55 -0
- package/dist/core/logs-policy.js +148 -0
- package/dist/core/nginx.js +8 -4
- package/dist/core/notify.d.ts +15 -0
- package/dist/core/notify.js +55 -0
- package/dist/core/registry.d.ts +25 -0
- package/dist/core/registry.js +57 -10
- package/dist/core/routines/cost-queries.d.ts +24 -0
- package/dist/core/routines/cost-queries.js +65 -0
- package/dist/core/routines/db.d.ts +9 -0
- package/dist/core/routines/db.js +126 -0
- package/dist/core/routines/defaults.d.ts +2 -0
- package/dist/core/routines/defaults.js +72 -0
- package/dist/core/routines/engine.d.ts +59 -0
- package/dist/core/routines/engine.js +175 -0
- package/dist/core/routines/incidents.d.ts +13 -0
- package/dist/core/routines/incidents.js +35 -0
- package/dist/core/routines/schema.d.ts +418 -0
- package/dist/core/routines/schema.js +113 -0
- package/dist/core/routines/signals-collector.d.ts +35 -0
- package/dist/core/routines/signals-collector.js +114 -0
- package/dist/core/routines/store.d.ts +316 -0
- package/dist/core/routines/store.js +99 -0
- package/dist/core/routines/test-utils.d.ts +2 -0
- package/dist/core/routines/test-utils.js +13 -0
- package/dist/core/secrets-audit.d.ts +21 -0
- package/dist/core/secrets-audit.js +60 -0
- package/dist/core/secrets-metadata.d.ts +39 -0
- package/dist/core/secrets-metadata.js +82 -0
- package/dist/core/secrets-motd.d.ts +20 -0
- package/dist/core/secrets-motd.js +72 -0
- package/dist/core/secrets-ops.d.ts +3 -1
- package/dist/core/secrets-ops.js +78 -13
- package/dist/core/secrets-providers.d.ts +50 -0
- package/dist/core/secrets-providers.js +291 -0
- package/dist/core/secrets-rotation.d.ts +52 -0
- package/dist/core/secrets-rotation.js +165 -0
- package/dist/core/secrets-snapshots.d.ts +26 -0
- package/dist/core/secrets-snapshots.js +95 -0
- package/dist/core/secrets-validate.js +2 -1
- package/dist/core/secrets.d.ts +12 -1
- package/dist/core/secrets.js +35 -24
- package/dist/core/self-update.d.ts +41 -0
- package/dist/core/self-update.js +73 -0
- package/dist/core/systemd.js +29 -12
- package/dist/core/telegram.d.ts +6 -0
- package/dist/core/telegram.js +32 -0
- package/dist/core/validate.d.ts +7 -0
- package/dist/core/validate.js +42 -0
- package/dist/index.js +0 -4
- package/dist/mcp/deps-tools.js +9 -1
- package/dist/mcp/git-tools.js +4 -4
- package/dist/mcp/server.js +193 -8
- package/dist/templates/systemd.js +3 -3
- package/dist/templates/unseal.js +5 -1
- package/dist/tui/components/Confirm.js +3 -4
- package/dist/tui/components/Header.js +37 -8
- package/dist/tui/components/KeyHint.js +14 -5
- package/dist/tui/exec-bridge.js +26 -12
- package/dist/tui/hooks/use-fleet-data.js +5 -2
- package/dist/tui/hooks/use-health.js +5 -2
- package/dist/tui/hooks/use-terminal-size.d.ts +1 -0
- package/dist/tui/hooks/use-terminal-size.js +1 -0
- package/dist/tui/router.js +133 -8
- package/dist/tui/routines/RoutinesApp.d.ts +8 -0
- package/dist/tui/routines/RoutinesApp.js +277 -0
- package/dist/tui/routines/components/AlertsPanel.d.ts +7 -0
- package/dist/tui/routines/components/AlertsPanel.js +22 -0
- package/dist/tui/routines/components/AlertsPanel.test.d.ts +1 -0
- package/dist/tui/routines/components/AlertsPanel.test.js +52 -0
- package/dist/tui/routines/components/CommandPalette.d.ts +12 -0
- package/dist/tui/routines/components/CommandPalette.js +21 -0
- package/dist/tui/routines/components/LiveRunPanel.d.ts +12 -0
- package/dist/tui/routines/components/LiveRunPanel.js +107 -0
- package/dist/tui/routines/components/RoutineForm.d.ts +8 -0
- package/dist/tui/routines/components/RoutineForm.js +254 -0
- package/dist/tui/routines/components/SignalsGrid.d.ts +13 -0
- package/dist/tui/routines/components/SignalsGrid.js +34 -0
- package/dist/tui/routines/components/SignalsGrid.test.d.ts +1 -0
- package/dist/tui/routines/components/SignalsGrid.test.js +43 -0
- package/dist/tui/routines/format.d.ts +7 -0
- package/dist/tui/routines/format.js +51 -0
- package/dist/tui/routines/hooks/use-git-fleet.d.ts +33 -0
- package/dist/tui/routines/hooks/use-git-fleet.js +82 -0
- package/dist/tui/routines/hooks/use-logs-stream.d.ts +13 -0
- package/dist/tui/routines/hooks/use-logs-stream.js +64 -0
- package/dist/tui/routines/hooks/use-ops-fleet.d.ts +20 -0
- package/dist/tui/routines/hooks/use-ops-fleet.js +70 -0
- package/dist/tui/routines/hooks/use-repo-detail.d.ts +31 -0
- package/dist/tui/routines/hooks/use-repo-detail.js +104 -0
- package/dist/tui/routines/hooks/use-security.d.ts +33 -0
- package/dist/tui/routines/hooks/use-security.js +110 -0
- package/dist/tui/routines/hooks/use-signals.d.ts +9 -0
- package/dist/tui/routines/hooks/use-signals.js +60 -0
- package/dist/tui/routines/runtime.d.ts +20 -0
- package/dist/tui/routines/runtime.js +40 -0
- package/dist/tui/routines/tabs/CostTab.d.ts +7 -0
- package/dist/tui/routines/tabs/CostTab.js +24 -0
- package/dist/tui/routines/tabs/DashboardTab.d.ts +15 -0
- package/dist/tui/routines/tabs/DashboardTab.js +10 -0
- package/dist/tui/routines/tabs/GitTab.d.ts +6 -0
- package/dist/tui/routines/tabs/GitTab.js +39 -0
- package/dist/tui/routines/tabs/LogsTab.d.ts +6 -0
- package/dist/tui/routines/tabs/LogsTab.js +58 -0
- package/dist/tui/routines/tabs/OpsTab.d.ts +6 -0
- package/dist/tui/routines/tabs/OpsTab.js +34 -0
- package/dist/tui/routines/tabs/RepoDetailView.d.ts +6 -0
- package/dist/tui/routines/tabs/RepoDetailView.js +12 -0
- package/dist/tui/routines/tabs/RoutinesTab.d.ts +10 -0
- package/dist/tui/routines/tabs/RoutinesTab.js +58 -0
- package/dist/tui/routines/tabs/ScaffoldTab.d.ts +2 -0
- package/dist/tui/routines/tabs/ScaffoldTab.js +127 -0
- package/dist/tui/routines/tabs/SecurityTab.d.ts +6 -0
- package/dist/tui/routines/tabs/SecurityTab.js +31 -0
- package/dist/tui/routines/tabs/SettingsTab.d.ts +6 -0
- package/dist/tui/routines/tabs/SettingsTab.js +61 -0
- package/dist/tui/routines/tabs/TimelineTab.d.ts +7 -0
- package/dist/tui/routines/tabs/TimelineTab.js +26 -0
- package/dist/tui/state.js +16 -1
- package/dist/tui/tests/flicker.test.d.ts +1 -0
- package/dist/tui/tests/flicker.test.js +105 -0
- package/dist/tui/tests/keyboard-integration.test.d.ts +1 -0
- package/dist/tui/tests/keyboard-integration.test.js +120 -0
- package/dist/tui/tests/test-app.d.ts +4 -0
- package/dist/tui/tests/test-app.js +79 -0
- package/dist/tui/types.d.ts +14 -1
- package/dist/tui/views/AppDetail.js +40 -26
- package/dist/tui/views/Dashboard.js +34 -9
- package/dist/tui/views/HealthView.js +42 -12
- package/dist/tui/views/LogsView.js +38 -10
- package/dist/tui/views/MultiLogsView.d.ts +2 -0
- package/dist/tui/views/MultiLogsView.js +165 -0
- package/dist/tui/views/SecretEdit.js +18 -7
- package/dist/tui/views/SecretsView.js +55 -39
- package/dist/ui/prompt.d.ts +52 -0
- package/dist/ui/prompt.js +169 -0
- package/package.json +33 -5
- package/dist/commands/motd.d.ts +0 -1
- package/dist/commands/motd.js +0 -10
- package/dist/templates/motd.d.ts +0 -1
- package/dist/templates/motd.js +0 -7
- package/dist/tui/components/AppList.d.ts +0 -12
- package/dist/tui/components/AppList.js +0 -32
- package/dist/tui/hooks/use-keyboard.d.ts +0 -1
- package/dist/tui/hooks/use-keyboard.js +0 -44
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain-text and hidden-input prompts, no external deps.
|
|
3
|
+
*
|
|
4
|
+
* promptHidden uses raw mode + manual char-by-char read so the echoed value
|
|
5
|
+
* never appears on the terminal — important for pasting secrets and for
|
|
6
|
+
* tools like `script` / asciinema.
|
|
7
|
+
*/
|
|
8
|
+
import * as readline from 'node:readline';
|
|
9
|
+
export async function prompt(message, defaultValue) {
|
|
10
|
+
const hint = defaultValue !== undefined ? ` [${defaultValue}]` : '';
|
|
11
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
12
|
+
return new Promise(resolve => {
|
|
13
|
+
rl.question(`${message}${hint}: `, answer => {
|
|
14
|
+
rl.close();
|
|
15
|
+
const trimmed = answer.trim();
|
|
16
|
+
resolve(trimmed === '' && defaultValue !== undefined ? defaultValue : trimmed);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* String variant — convenience wrapper around the Buffer variant. Use the
|
|
22
|
+
* Buffer variant directly if you want the strongest in-memory guarantees;
|
|
23
|
+
* this one converts to string and the result lives in the V8 heap until GC.
|
|
24
|
+
*/
|
|
25
|
+
export async function promptHidden(message) {
|
|
26
|
+
const buf = await promptHiddenBuffer(message);
|
|
27
|
+
try {
|
|
28
|
+
return buf.toString('utf8');
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
buf.fill(0);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Buffer-based hidden input. Returns the raw input bytes in a Buffer the
|
|
36
|
+
* caller is expected to zero out (`buf.fill(0)`) when finished — see
|
|
37
|
+
* `withSecretBuffer` for an automated pattern.
|
|
38
|
+
*
|
|
39
|
+
* Why Buffer (not string)?
|
|
40
|
+
* - Node strings are immutable + interned in V8 heap; you can't zero them.
|
|
41
|
+
* Once a secret string exists, it sits in the heap until GC.
|
|
42
|
+
* - Buffer is a writable byte array. Calling `buf.fill(0)` overwrites the
|
|
43
|
+
* bytes in-place; subsequent heap dumps and core dumps contain zeros.
|
|
44
|
+
*
|
|
45
|
+
* Hardening:
|
|
46
|
+
* - Buffer is grown by `Buffer.concat` and the intermediate buffers are
|
|
47
|
+
* zeroed before being released.
|
|
48
|
+
* - Non-TTY fallback uses `terminal: false` so readline can never promote
|
|
49
|
+
* stdout to terminal mode and echo the value.
|
|
50
|
+
* - End/error/SIGINT all reject + restore terminal state and zero the
|
|
51
|
+
* in-flight buffer so a death never leaves bytes behind.
|
|
52
|
+
*
|
|
53
|
+
* KNOWN LIMITATION: any string copy made downstream (e.g. `buf.toString()`
|
|
54
|
+
* for regex validation) lives in V8 heap until GC. Convert as late as
|
|
55
|
+
* possible and let the string go out of scope ASAP.
|
|
56
|
+
*/
|
|
57
|
+
export function promptHiddenBuffer(message) {
|
|
58
|
+
if (!process.stdin.isTTY) {
|
|
59
|
+
return new Promise((resolve, reject) => {
|
|
60
|
+
const rl = readline.createInterface({ input: process.stdin, terminal: false });
|
|
61
|
+
process.stdout.write(message + ': ');
|
|
62
|
+
let done = false;
|
|
63
|
+
const finish = (cb) => { if (done)
|
|
64
|
+
return; done = true; rl.close(); cb(); };
|
|
65
|
+
rl.once('line', line => finish(() => resolve(Buffer.from(line, 'utf8'))));
|
|
66
|
+
rl.once('close', () => finish(() => reject(new Error('Cancelled (stdin closed)'))));
|
|
67
|
+
rl.once('error', err => finish(() => reject(err)));
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return new Promise((resolve, reject) => {
|
|
71
|
+
const stdin = process.stdin;
|
|
72
|
+
process.stdout.write(message + ': ');
|
|
73
|
+
// Pre-allocate; grow geometrically to avoid quadratic Buffer.concat.
|
|
74
|
+
let buf = Buffer.alloc(64);
|
|
75
|
+
let len = 0;
|
|
76
|
+
let settled = false;
|
|
77
|
+
const wasRaw = stdin.isRaw;
|
|
78
|
+
const grow = (need) => {
|
|
79
|
+
if (len + need <= buf.length)
|
|
80
|
+
return;
|
|
81
|
+
const next = Buffer.alloc(Math.max(buf.length * 2, len + need));
|
|
82
|
+
buf.copy(next);
|
|
83
|
+
buf.fill(0); // zero the old buffer before releasing
|
|
84
|
+
buf = next;
|
|
85
|
+
};
|
|
86
|
+
const cleanup = () => {
|
|
87
|
+
stdin.removeListener('data', onData);
|
|
88
|
+
stdin.removeListener('end', onEnd);
|
|
89
|
+
stdin.removeListener('error', onError);
|
|
90
|
+
process.removeListener('SIGINT', onSigint);
|
|
91
|
+
try {
|
|
92
|
+
stdin.setRawMode(wasRaw);
|
|
93
|
+
}
|
|
94
|
+
catch { /* terminal may be gone */ }
|
|
95
|
+
stdin.pause();
|
|
96
|
+
};
|
|
97
|
+
const settle = (fn) => {
|
|
98
|
+
if (settled)
|
|
99
|
+
return;
|
|
100
|
+
settled = true;
|
|
101
|
+
cleanup();
|
|
102
|
+
fn();
|
|
103
|
+
};
|
|
104
|
+
const wipeAndReject = (err) => {
|
|
105
|
+
buf.fill(0);
|
|
106
|
+
settle(() => reject(err));
|
|
107
|
+
};
|
|
108
|
+
const onData = (chunk) => {
|
|
109
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
110
|
+
const c = chunk[i];
|
|
111
|
+
if (c === 0x0d || c === 0x0a) { // \r \n
|
|
112
|
+
process.stdout.write('\n');
|
|
113
|
+
const out = Buffer.alloc(len);
|
|
114
|
+
buf.copy(out, 0, 0, len);
|
|
115
|
+
buf.fill(0);
|
|
116
|
+
settle(() => resolve(out));
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
else if (c === 0x03) { // Ctrl-C
|
|
120
|
+
process.stdout.write('\n');
|
|
121
|
+
wipeAndReject(new Error('Cancelled'));
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
else if (c === 0x7f || c === 0x08) { // backspace
|
|
125
|
+
if (len > 0) {
|
|
126
|
+
len -= 1;
|
|
127
|
+
buf[len] = 0;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else if (c >= 0x20) { // printable
|
|
131
|
+
grow(1);
|
|
132
|
+
buf[len++] = c;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
const onEnd = () => wipeAndReject(new Error('Cancelled (stdin ended)'));
|
|
137
|
+
const onError = (err) => wipeAndReject(err);
|
|
138
|
+
const onSigint = () => { process.stdout.write('\n'); wipeAndReject(new Error('Cancelled (SIGINT)')); };
|
|
139
|
+
stdin.setRawMode(true);
|
|
140
|
+
stdin.resume();
|
|
141
|
+
// Note: do NOT setEncoding — we want raw bytes, not auto-decoded strings.
|
|
142
|
+
stdin.on('data', onData);
|
|
143
|
+
stdin.on('end', onEnd);
|
|
144
|
+
stdin.on('error', onError);
|
|
145
|
+
process.on('SIGINT', onSigint);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Recommended pattern for handling a secret in memory: read into a Buffer,
|
|
150
|
+
* pass to your callback, zero on exit (success or throw). Use this instead
|
|
151
|
+
* of `promptHidden` when the value will be processed by code under your
|
|
152
|
+
* control end-to-end.
|
|
153
|
+
*
|
|
154
|
+
* Example:
|
|
155
|
+
* await withSecretBuffer('Paste new STRIPE_SECRET_KEY', async (buf) => {
|
|
156
|
+
* const asString = buf.toString('utf8'); // brief string copy
|
|
157
|
+
* await sealApp(app, applyRotation(...)); // age-encrypt happens here
|
|
158
|
+
* // String copy is unreferenced from this point; buf is zeroed on exit.
|
|
159
|
+
* });
|
|
160
|
+
*/
|
|
161
|
+
export async function withSecretBuffer(message, fn) {
|
|
162
|
+
const buf = await promptHiddenBuffer(message);
|
|
163
|
+
try {
|
|
164
|
+
return await fn(buf);
|
|
165
|
+
}
|
|
166
|
+
finally {
|
|
167
|
+
buf.fill(0);
|
|
168
|
+
}
|
|
169
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matthesketh/fleet",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Docker production management CLI + MCP server for Claude Code",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"README.md"
|
|
15
15
|
],
|
|
16
16
|
"scripts": {
|
|
17
|
-
"build": "tsc",
|
|
17
|
+
"build": "tsc && tsc-alias",
|
|
18
18
|
"dev": "tsx src/index.ts",
|
|
19
19
|
"test": "vitest run",
|
|
20
20
|
"prepublishOnly": "npm run build"
|
|
@@ -47,18 +47,46 @@
|
|
|
47
47
|
"node": ">=20"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@
|
|
50
|
+
"@matthesketh/ink-breadcrumb": "^0.1.0",
|
|
51
|
+
"@matthesketh/ink-chart": "0.1.0",
|
|
52
|
+
"@matthesketh/ink-form": "0.1.0",
|
|
53
|
+
"@matthesketh/ink-fuzzy-select": "0.1.0",
|
|
54
|
+
"@matthesketh/ink-gauge": "^0.1.0",
|
|
55
|
+
"@matthesketh/ink-input-dispatcher": "^0.1.0",
|
|
56
|
+
"@matthesketh/ink-keybinding-help": "^0.1.0",
|
|
57
|
+
"@matthesketh/ink-log-viewer": "^0.1.0",
|
|
58
|
+
"@matthesketh/ink-modal": "^0.1.0",
|
|
59
|
+
"@matthesketh/ink-pipeline": "^0.1.0",
|
|
60
|
+
"@matthesketh/ink-rule": "^0.1.0",
|
|
61
|
+
"@matthesketh/ink-scrollable-list": "^0.1.1",
|
|
62
|
+
"@matthesketh/ink-split-pane": "^0.1.0",
|
|
63
|
+
"@matthesketh/ink-stable-state": "^0.1.0",
|
|
64
|
+
"@matthesketh/ink-status-bar": "^0.1.0",
|
|
65
|
+
"@matthesketh/ink-table": "^0.1.0",
|
|
66
|
+
"@matthesketh/ink-tabs": "^0.1.0",
|
|
67
|
+
"@matthesketh/ink-task-list": "0.1.0",
|
|
68
|
+
"@matthesketh/ink-timeline": "0.1.0",
|
|
69
|
+
"@matthesketh/ink-toast": "^0.1.0",
|
|
70
|
+
"@matthesketh/ink-viewport": "^0.1.0",
|
|
71
|
+
"@modelcontextprotocol/sdk": "1.29.0",
|
|
72
|
+
"better-sqlite3": "12.9.0",
|
|
73
|
+
"chokidar": "5.0.0",
|
|
51
74
|
"ink": "^5.2.1",
|
|
52
75
|
"ink-spinner": "^5.0.0",
|
|
53
76
|
"ink-text-input": "^6.0.0",
|
|
77
|
+
"proper-lockfile": "4.1.2",
|
|
54
78
|
"react": "^18.3.1",
|
|
55
79
|
"zod": "^3.24.0"
|
|
56
80
|
},
|
|
57
81
|
"devDependencies": {
|
|
82
|
+
"@types/better-sqlite3": "7.6.13",
|
|
58
83
|
"@types/node": "20.17.0",
|
|
84
|
+
"@types/proper-lockfile": "4.1.4",
|
|
59
85
|
"@types/react": "^18.3.28",
|
|
60
|
-
"
|
|
86
|
+
"ink-testing-library": "^4.0.0",
|
|
87
|
+
"tsc-alias": "1.8.16",
|
|
88
|
+
"tsx": "4.21.0",
|
|
61
89
|
"typescript": "5.6.3",
|
|
62
90
|
"vitest": "4.0.18"
|
|
63
91
|
}
|
|
64
|
-
}
|
|
92
|
+
}
|
package/dist/commands/motd.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function motdInstallCommand(): void;
|
package/dist/commands/motd.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { writeFileSync, chmodSync } from 'node:fs';
|
|
2
|
-
import { generateMotdScript } from '../templates/motd.js';
|
|
3
|
-
import { success } from '../ui/output.js';
|
|
4
|
-
const MOTD_PATH = '/etc/update-motd.d/50-fleet-status';
|
|
5
|
-
export function motdInstallCommand() {
|
|
6
|
-
const script = generateMotdScript();
|
|
7
|
-
writeFileSync(MOTD_PATH, script);
|
|
8
|
-
chmodSync(MOTD_PATH, 0o755);
|
|
9
|
-
success(`Installed MOTD script at ${MOTD_PATH}`);
|
|
10
|
-
}
|
package/dist/templates/motd.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function generateMotdScript(): string;
|
package/dist/templates/motd.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export function generateMotdScript() {
|
|
2
|
-
return `#!/bin/bash
|
|
3
|
-
# Fleet service health check — installed by "fleet motd install"
|
|
4
|
-
# Shows service status on SSH login
|
|
5
|
-
/usr/bin/node /home/matt/fleet/dist/index.js watchdog --motd 2>/dev/null || echo " Fleet: health check failed to run"
|
|
6
|
-
`;
|
|
7
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
interface AppListItem {
|
|
3
|
-
name: string;
|
|
4
|
-
label?: string;
|
|
5
|
-
}
|
|
6
|
-
interface AppListProps {
|
|
7
|
-
items: AppListItem[];
|
|
8
|
-
onSelect: (item: AppListItem) => void;
|
|
9
|
-
renderItem?: (item: AppListItem, selected: boolean) => React.JSX.Element;
|
|
10
|
-
}
|
|
11
|
-
export declare function AppList({ items, onSelect, renderItem }: AppListProps): React.JSX.Element;
|
|
12
|
-
export {};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from 'react';
|
|
3
|
-
import { Box, Text, useInput } from 'ink';
|
|
4
|
-
import { colors } from '../theme.js';
|
|
5
|
-
export function AppList({ items, onSelect, renderItem }) {
|
|
6
|
-
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
7
|
-
useInput((input, key) => {
|
|
8
|
-
if (items.length === 0)
|
|
9
|
-
return;
|
|
10
|
-
if (input === 'j' || key.downArrow) {
|
|
11
|
-
setSelectedIndex(prev => Math.min(prev + 1, items.length - 1));
|
|
12
|
-
}
|
|
13
|
-
else if (input === 'k' || key.upArrow) {
|
|
14
|
-
setSelectedIndex(prev => Math.max(prev - 1, 0));
|
|
15
|
-
}
|
|
16
|
-
else if (key.return) {
|
|
17
|
-
if (items[selectedIndex]) {
|
|
18
|
-
onSelect(items[selectedIndex]);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
if (items.length === 0) {
|
|
23
|
-
return _jsx(Text, { color: colors.muted, children: "No items" });
|
|
24
|
-
}
|
|
25
|
-
return (_jsx(Box, { flexDirection: "column", children: items.map((item, i) => {
|
|
26
|
-
const selected = i === selectedIndex;
|
|
27
|
-
if (renderItem) {
|
|
28
|
-
return (_jsxs(Box, { children: [_jsx(Text, { color: colors.primary, children: selected ? '> ' : ' ' }), renderItem(item, selected)] }, item.name));
|
|
29
|
-
}
|
|
30
|
-
return (_jsxs(Text, { bold: selected, color: selected ? colors.primary : colors.text, children: [selected ? '> ' : ' ', item.label ?? item.name] }, item.name));
|
|
31
|
-
}) }));
|
|
32
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function useKeyboard(): void;
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { useInput } from 'ink';
|
|
2
|
-
import { useAppState, useAppDispatch, nextTopView } from '../state.js';
|
|
3
|
-
export function useKeyboard() {
|
|
4
|
-
const state = useAppState();
|
|
5
|
-
const dispatch = useAppDispatch();
|
|
6
|
-
useInput((input, key) => {
|
|
7
|
-
// Confirm dialog takes priority
|
|
8
|
-
if (state.confirmAction) {
|
|
9
|
-
if (input === 'y' || input === 'Y') {
|
|
10
|
-
state.confirmAction.onConfirm();
|
|
11
|
-
dispatch({ type: 'CANCEL_CONFIRM' });
|
|
12
|
-
}
|
|
13
|
-
else if (input === 'n' || input === 'N' || key.escape) {
|
|
14
|
-
dispatch({ type: 'CANCEL_CONFIRM' });
|
|
15
|
-
}
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
// Redact toggle (not in text-input views)
|
|
19
|
-
if (input === 'x' && state.currentView !== 'secret-edit') {
|
|
20
|
-
dispatch({ type: 'TOGGLE_REDACT' });
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
// Quit
|
|
24
|
-
if (input === 'q') {
|
|
25
|
-
process.exit(0);
|
|
26
|
-
}
|
|
27
|
-
// Tab cycles top-level views (only from top-level views)
|
|
28
|
-
if (key.tab) {
|
|
29
|
-
const topViews = ['dashboard', 'health', 'secrets'];
|
|
30
|
-
const base = topViews.includes(state.currentView)
|
|
31
|
-
? state.currentView
|
|
32
|
-
: state.previousView ?? 'dashboard';
|
|
33
|
-
dispatch({ type: 'NAVIGATE', view: nextTopView(base) });
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
// Escape goes back
|
|
37
|
-
if (key.escape) {
|
|
38
|
-
if (state.previousView) {
|
|
39
|
-
dispatch({ type: 'GO_BACK' });
|
|
40
|
-
}
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
}
|