@matthesketh/fleet 1.0.0 → 1.2.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 +27 -4
- package/dist/cli.js +8 -0
- package/dist/commands/deps.d.ts +1 -0
- package/dist/commands/deps.js +223 -0
- package/dist/commands/motd.d.ts +1 -0
- package/dist/commands/motd.js +10 -0
- package/dist/core/deps/actors/pr-creator.d.ts +14 -0
- package/dist/core/deps/actors/pr-creator.js +103 -0
- package/dist/core/deps/cache.d.ts +5 -0
- package/dist/core/deps/cache.js +28 -0
- package/dist/core/deps/collectors/composer.d.ts +12 -0
- package/dist/core/deps/collectors/composer.js +70 -0
- package/dist/core/deps/collectors/docker-image.d.ts +18 -0
- package/dist/core/deps/collectors/docker-image.js +132 -0
- package/dist/core/deps/collectors/docker-running.d.ts +17 -0
- package/dist/core/deps/collectors/docker-running.js +55 -0
- package/dist/core/deps/collectors/eol.d.ts +16 -0
- package/dist/core/deps/collectors/eol.js +139 -0
- package/dist/core/deps/collectors/github-pr.d.ts +8 -0
- package/dist/core/deps/collectors/github-pr.js +40 -0
- package/dist/core/deps/collectors/npm.d.ts +12 -0
- package/dist/core/deps/collectors/npm.js +63 -0
- package/dist/core/deps/collectors/pip.d.ts +15 -0
- package/dist/core/deps/collectors/pip.js +94 -0
- package/dist/core/deps/collectors/vulnerability.d.ts +9 -0
- package/dist/core/deps/collectors/vulnerability.js +102 -0
- package/dist/core/deps/config.d.ts +6 -0
- package/dist/core/deps/config.js +55 -0
- package/dist/core/deps/reporters/cli.d.ts +4 -0
- package/dist/core/deps/reporters/cli.js +123 -0
- package/dist/core/deps/reporters/motd.d.ts +3 -0
- package/dist/core/deps/reporters/motd.js +64 -0
- package/dist/core/deps/reporters/telegram.d.ts +6 -0
- package/dist/core/deps/reporters/telegram.js +106 -0
- package/dist/core/deps/scanner.d.ts +4 -0
- package/dist/core/deps/scanner.js +89 -0
- package/dist/core/deps/severity.d.ts +6 -0
- package/dist/core/deps/severity.js +45 -0
- package/dist/core/deps/types.d.ts +64 -0
- package/dist/core/deps/types.js +1 -0
- package/dist/mcp/deps-tools.d.ts +2 -0
- package/dist/mcp/deps-tools.js +81 -0
- package/dist/mcp/server.js +2 -0
- package/dist/templates/motd.d.ts +1 -0
- package/dist/templates/motd.js +7 -0
- package/dist/tui/components/AppList.js +1 -1
- package/dist/tui/components/Confirm.js +3 -4
- package/dist/tui/components/Header.js +37 -8
- package/dist/tui/components/KeyHint.js +4 -5
- 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 +81 -9
- package/dist/tui/state.js +15 -0
- 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 +117 -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 +13 -0
- package/dist/tui/views/AppDetail.js +41 -26
- package/dist/tui/views/Dashboard.js +34 -9
- package/dist/tui/views/HealthView.js +36 -12
- package/dist/tui/views/LogsView.js +14 -9
- package/dist/tui/views/SecretEdit.js +8 -4
- package/dist/tui/views/SecretsView.js +49 -36
- package/package.json +17 -1
|
@@ -1,72 +1,84 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect,
|
|
3
|
-
import { Box, Text
|
|
2
|
+
import { useEffect, useCallback } from 'react';
|
|
3
|
+
import { Box, Text } from 'ink';
|
|
4
|
+
import { useRegisterHandler } from '@matthesketh/ink-input-dispatcher';
|
|
5
|
+
import { ScrollableList } from '@matthesketh/ink-scrollable-list';
|
|
6
|
+
import { useAvailableHeight } from '@matthesketh/ink-viewport';
|
|
4
7
|
import { useAppState, useAppDispatch, useRedact } from '../state.js';
|
|
5
8
|
import { useSecrets } from '../hooks/use-secrets.js';
|
|
6
9
|
import { colors } from '../theme.js';
|
|
7
10
|
export function SecretsView() {
|
|
8
|
-
const
|
|
11
|
+
const state = useAppState();
|
|
9
12
|
const dispatch = useAppDispatch();
|
|
10
13
|
const redact = useRedact();
|
|
11
14
|
const secrets = useSecrets();
|
|
12
|
-
const
|
|
13
|
-
const
|
|
15
|
+
const availableHeight = useAvailableHeight();
|
|
16
|
+
const { secretsSubView: subView, secretsIndex: selectedIndex, selectedApp } = state;
|
|
17
|
+
const refresh = secrets.refresh;
|
|
14
18
|
useEffect(() => {
|
|
15
|
-
|
|
16
|
-
}, []);
|
|
19
|
+
refresh();
|
|
20
|
+
}, [refresh]);
|
|
17
21
|
useEffect(() => {
|
|
18
22
|
if (subView === 'secret-list' && selectedApp) {
|
|
19
23
|
secrets.loadAppSecrets(selectedApp);
|
|
20
24
|
}
|
|
21
|
-
}, [subView, selectedApp]);
|
|
22
|
-
|
|
25
|
+
}, [subView, selectedApp, secrets.loadAppSecrets]);
|
|
26
|
+
const handler = useCallback((input, key) => {
|
|
23
27
|
if (subView === 'app-list') {
|
|
24
28
|
if (input === 'j' || key.downArrow) {
|
|
25
|
-
|
|
29
|
+
dispatch({ type: 'SET_INDEX', view: 'secrets', index: Math.min(selectedIndex + 1, secrets.apps.length - 1) });
|
|
30
|
+
return true;
|
|
26
31
|
}
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
if (input === 'k' || key.upArrow) {
|
|
33
|
+
dispatch({ type: 'SET_INDEX', view: 'secrets', index: Math.max(selectedIndex - 1, 0) });
|
|
34
|
+
return true;
|
|
29
35
|
}
|
|
30
|
-
|
|
36
|
+
if (key.return && secrets.apps[selectedIndex]) {
|
|
31
37
|
dispatch({ type: 'SELECT_APP', app: secrets.apps[selectedIndex].app });
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
dispatch({ type: 'SET_SECRETS_SUBVIEW', subView: 'secret-list' });
|
|
39
|
+
return true;
|
|
34
40
|
}
|
|
35
|
-
|
|
41
|
+
if (input === 'u') {
|
|
36
42
|
const result = secrets.unseal();
|
|
37
43
|
if (!result.ok) {
|
|
38
44
|
dispatch({ type: 'SET_ERROR', error: result.error ?? 'Unseal failed' });
|
|
39
45
|
}
|
|
40
46
|
secrets.refresh();
|
|
47
|
+
return true;
|
|
41
48
|
}
|
|
42
|
-
|
|
49
|
+
if (input === 'l') {
|
|
43
50
|
const result = secrets.seal();
|
|
44
51
|
if (!result.ok) {
|
|
45
52
|
dispatch({ type: 'SET_ERROR', error: result.error ?? 'Seal failed' });
|
|
46
53
|
}
|
|
47
54
|
secrets.refresh();
|
|
55
|
+
return true;
|
|
48
56
|
}
|
|
49
57
|
}
|
|
50
58
|
else if (subView === 'secret-list') {
|
|
51
59
|
if (input === 'j' || key.downArrow) {
|
|
52
|
-
|
|
60
|
+
dispatch({ type: 'SET_INDEX', view: 'secrets', index: Math.min(selectedIndex + 1, secrets.secrets.length - 1) });
|
|
61
|
+
return true;
|
|
53
62
|
}
|
|
54
|
-
|
|
55
|
-
|
|
63
|
+
if (input === 'k' || key.upArrow) {
|
|
64
|
+
dispatch({ type: 'SET_INDEX', view: 'secrets', index: Math.max(selectedIndex - 1, 0) });
|
|
65
|
+
return true;
|
|
56
66
|
}
|
|
57
|
-
|
|
67
|
+
if (key.return && secrets.secrets[selectedIndex] && selectedApp) {
|
|
58
68
|
dispatch({ type: 'SELECT_SECRET', key: secrets.secrets[selectedIndex].key });
|
|
59
69
|
dispatch({ type: 'NAVIGATE', view: 'secret-edit' });
|
|
70
|
+
return true;
|
|
60
71
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
72
|
+
if (key.escape) {
|
|
73
|
+
dispatch({ type: 'SET_SECRETS_SUBVIEW', subView: 'app-list' });
|
|
74
|
+
return true;
|
|
64
75
|
}
|
|
65
|
-
|
|
76
|
+
if (input === 'a' && selectedApp) {
|
|
66
77
|
dispatch({ type: 'SELECT_SECRET', key: null });
|
|
67
78
|
dispatch({ type: 'NAVIGATE', view: 'secret-edit' });
|
|
79
|
+
return true;
|
|
68
80
|
}
|
|
69
|
-
|
|
81
|
+
if (input === 'd' && selectedApp && secrets.secrets[selectedIndex]) {
|
|
70
82
|
const secretKey = secrets.secrets[selectedIndex].key;
|
|
71
83
|
dispatch({
|
|
72
84
|
type: 'CONFIRM',
|
|
@@ -85,8 +97,9 @@ export function SecretsView() {
|
|
|
85
97
|
},
|
|
86
98
|
},
|
|
87
99
|
});
|
|
100
|
+
return true;
|
|
88
101
|
}
|
|
89
|
-
|
|
102
|
+
if (input === 'r' && selectedApp && secrets.secrets[selectedIndex]) {
|
|
90
103
|
const secretKey = secrets.secrets[selectedIndex].key;
|
|
91
104
|
if (secrets.revealedValues[secretKey]) {
|
|
92
105
|
secrets.hideSecret(secretKey);
|
|
@@ -94,15 +107,15 @@ export function SecretsView() {
|
|
|
94
107
|
else {
|
|
95
108
|
secrets.revealSecret(selectedApp, secretKey);
|
|
96
109
|
}
|
|
110
|
+
return true;
|
|
97
111
|
}
|
|
98
112
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
})) })] }))] }));
|
|
113
|
+
return false;
|
|
114
|
+
}, [subView, selectedIndex, selectedApp, secrets, dispatch, redact]);
|
|
115
|
+
useRegisterHandler(handler);
|
|
116
|
+
const listHeight = Math.max(5, availableHeight - 5);
|
|
117
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Box, { marginBottom: 1, paddingX: 1, gap: 2, children: [_jsx(Text, { bold: true, children: "Vault:" }), !secrets.initialized ? (_jsx(Text, { color: colors.error, children: "Not initialized" })) : secrets.sealed ? (_jsx(Text, { color: colors.warning, bold: true, children: "SEALED" })) : (_jsx(Text, { color: colors.success, bold: true, children: "UNSEALED" })), _jsxs(Text, { color: colors.muted, children: [secrets.apps.length, " apps | ", secrets.apps.reduce((sum, a) => sum + a.keyCount, 0), " keys"] })] }), secrets.error && (_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: colors.error, children: secrets.error }) })), subView === 'app-list' ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Apps with secrets:" }), _jsx(ScrollableList, { items: secrets.apps, selectedIndex: Math.min(selectedIndex, secrets.apps.length - 1), maxVisible: listHeight, emptyText: " No secrets managed", renderItem: (app, selected) => (_jsxs(Box, { children: [_jsx(Text, { color: colors.primary, children: selected ? '> ' : ' ' }), _jsx(Text, { bold: selected, color: selected ? colors.primary : colors.text, children: redact(app.app).padEnd(24) }), _jsx(Text, { color: colors.muted, children: app.type.padEnd(14) }), _jsxs(Text, { children: [String(app.keyCount).padEnd(8), " keys"] })] })) })] })) : (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, color: colors.primary, children: redact(selectedApp ?? '') }), _jsx(Box, { marginTop: 1, flexDirection: "column", children: _jsx(ScrollableList, { items: secrets.secrets, selectedIndex: Math.min(selectedIndex, secrets.secrets.length - 1), maxVisible: listHeight, emptyText: " No secrets found", renderItem: (secret, selected) => {
|
|
118
|
+
const revealed = secrets.revealedValues[secret.key];
|
|
119
|
+
return (_jsxs(Box, { children: [_jsx(Text, { color: colors.primary, children: selected ? '> ' : ' ' }), _jsx(Text, { bold: selected, color: selected ? colors.primary : colors.text, children: secret.key.padEnd(30) }), _jsx(Text, { color: revealed ? colors.warning : colors.muted, children: revealed ?? secret.maskedValue })] }));
|
|
120
|
+
} }) })] }))] }));
|
|
108
121
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matthesketh/fleet",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Docker production management CLI + MCP server for Claude Code",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"LICENSE",
|
|
14
14
|
"README.md"
|
|
15
15
|
],
|
|
16
|
+
"workspaces": ["packages/*"],
|
|
16
17
|
"scripts": {
|
|
17
18
|
"build": "tsc",
|
|
18
19
|
"dev": "tsx src/index.ts",
|
|
@@ -48,6 +49,21 @@
|
|
|
48
49
|
},
|
|
49
50
|
"dependencies": {
|
|
50
51
|
"@modelcontextprotocol/sdk": "1.8.0",
|
|
52
|
+
"@matthesketh/ink-breadcrumb": "*",
|
|
53
|
+
"@matthesketh/ink-gauge": "*",
|
|
54
|
+
"@matthesketh/ink-input-dispatcher": "*",
|
|
55
|
+
"@matthesketh/ink-keybinding-help": "*",
|
|
56
|
+
"@matthesketh/ink-log-viewer": "*",
|
|
57
|
+
"@matthesketh/ink-modal": "*",
|
|
58
|
+
"@matthesketh/ink-pipeline": "*",
|
|
59
|
+
"@matthesketh/ink-rule": "*",
|
|
60
|
+
"@matthesketh/ink-scrollable-list": "*",
|
|
61
|
+
"@matthesketh/ink-split-pane": "*",
|
|
62
|
+
"@matthesketh/ink-status-bar": "*",
|
|
63
|
+
"@matthesketh/ink-table": "*",
|
|
64
|
+
"@matthesketh/ink-tabs": "*",
|
|
65
|
+
"@matthesketh/ink-toast": "*",
|
|
66
|
+
"@matthesketh/ink-viewport": "*",
|
|
51
67
|
"ink": "^5.2.1",
|
|
52
68
|
"ink-spinner": "^5.0.0",
|
|
53
69
|
"ink-text-input": "^6.0.0",
|