k8s-av 1.0.3 → 1.0.5

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/cli/start.js CHANGED
@@ -46,7 +46,7 @@ const UI_DIR = path.join(ROOT, 'ui');
46
46
  const BACKEND_URL = 'http://localhost:3001';
47
47
  const FRONTEND_URL = 'http://localhost:5173';
48
48
  const log = (msg) => console.log(` ${msg}`);
49
- const warn = (msg) => console.log(` ${msg}`);
49
+ const warn = (msg) => console.log(` ! ${msg}`);
50
50
  function waitFor(url, timeoutMs = 30000) {
51
51
  return new Promise((resolve, reject) => {
52
52
  const deadline = Date.now() + timeoutMs;
@@ -89,12 +89,19 @@ function openBrowser(url) {
89
89
  }
90
90
  async function ensureUiDeps() {
91
91
  const nmDir = path.join(UI_DIR, 'node_modules');
92
- if (fs.existsSync(nmDir))
92
+ const requiredPackages = [
93
+ path.join(nmDir, 'vite', 'package.json'),
94
+ path.join(nmDir, '@vitejs', 'plugin-react', 'package.json'),
95
+ ];
96
+ const hasUiDeps = fs.existsSync(nmDir) && requiredPackages.every((pkg) => fs.existsSync(pkg));
97
+ if (hasUiDeps)
93
98
  return;
94
- log('📦 Installing UI dependencies (first run)...');
99
+ log(fs.existsSync(nmDir)
100
+ ? 'Repairing incomplete UI dependencies...'
101
+ : 'Installing UI dependencies (first run)...');
95
102
  try {
96
- await exec('npm install --omit=dev', { cwd: UI_DIR });
97
- log('UI dependencies installed');
103
+ await exec('npm install', { cwd: UI_DIR });
104
+ log('UI dependencies installed');
98
105
  }
99
106
  catch (err) {
100
107
  throw new Error(`Failed to install UI deps in ${UI_DIR}:\n` +
@@ -103,12 +110,12 @@ async function ensureUiDeps() {
103
110
  }
104
111
  }
105
112
  async function runStart(opts) {
106
- console.log('\n' + ''.repeat(62));
107
- console.log(' 🔐 Kubernetes Attack Path Visualizer');
113
+ console.log('\n' + '='.repeat(62));
114
+ console.log(' Kubernetes Attack Path Visualizer');
108
115
  console.log(' ' + (opts.source === 'mock' ? 'Demo mode (mock data)' : 'Live cluster mode'));
109
- console.log(''.repeat(62));
116
+ console.log('='.repeat(62));
110
117
  if (opts.source === 'mock') {
111
- console.log('\n Mock mode skipping Docker & Neo4j preflight.');
118
+ console.log('\n Info: Mock mode - skipping Docker and Neo4j preflight.');
112
119
  }
113
120
  else {
114
121
  const preflight = await (0, docker_1.runPreflight)();
@@ -116,7 +123,7 @@ async function runStart(opts) {
116
123
  process.exit(1);
117
124
  }
118
125
  console.log();
119
- log('Starting backend...');
126
+ log('Starting backend...');
120
127
  const distServer = path.join(ROOT, 'dist', 'server', 'server.js');
121
128
  const [backendCmd, backendArgs] = fs.existsSync(distServer)
122
129
  ? ['node', [distServer]]
@@ -141,16 +148,16 @@ async function runStart(opts) {
141
148
  backend.once('exit', (code) => {
142
149
  backendExited = true;
143
150
  if (code !== 0 && code !== null) {
144
- console.error(`\n Backend exited with code ${code}`);
151
+ console.error(`\n ERROR: Backend exited with code ${code}`);
145
152
  process.exit(1);
146
153
  }
147
154
  });
148
- log('Waiting for backend...');
155
+ log('Waiting for backend...');
149
156
  try {
150
157
  await waitFor(`${BACKEND_URL}/health`, 60000);
151
158
  }
152
159
  catch {
153
- console.error('\n Backend did not start within 60s.');
160
+ console.error('\n ERROR: Backend did not start within 60s.');
154
161
  if (opts.source !== 'mock') {
155
162
  console.error(' Ensure Neo4j is running:');
156
163
  console.error(' cd docker && docker compose up -d');
@@ -158,25 +165,25 @@ async function runStart(opts) {
158
165
  backend.kill();
159
166
  process.exit(1);
160
167
  }
161
- log('Backend ready');
162
- log(`✔ Loading cluster data (source: ${opts.source})...`);
168
+ log('Backend ready');
169
+ log(`Loading cluster data (source: ${opts.source})...`);
163
170
  try {
164
171
  await ingest(opts.source);
165
- log('Data loaded');
172
+ log('Data loaded');
166
173
  }
167
174
  catch (err) {
168
175
  warn(`Ingest warning: ${err.message}`);
169
- warn(' UI will start in empty state check Neo4j connection.');
176
+ warn('UI will start in empty state - check Neo4j connection.');
170
177
  }
171
178
  try {
172
179
  await ensureUiDeps();
173
180
  }
174
181
  catch (err) {
175
- console.error(`\n ${err.message}`);
182
+ console.error(`\n ERROR: ${err.message}`);
176
183
  backend.kill();
177
184
  process.exit(1);
178
185
  }
179
- log('Starting UI...');
186
+ log('Starting UI...');
180
187
  const frontend = (0, child_process_1.spawn)('npm', ['run', 'dev'], {
181
188
  cwd: UI_DIR,
182
189
  stdio: ['ignore', 'pipe', 'pipe'],
@@ -197,17 +204,17 @@ async function runStart(opts) {
197
204
  await waitFor(FRONTEND_URL, 45000);
198
205
  }
199
206
  catch {
200
- warn('Vite did not respond in time opening browser anyway.');
207
+ warn('Vite did not respond in time - opening browser anyway.');
201
208
  }
202
209
  if (!opts.skipBrowser) {
203
- log('Opening browser...');
210
+ log('Opening browser...');
204
211
  openBrowser(FRONTEND_URL);
205
212
  }
206
- console.log('\n ' + ''.repeat(58));
207
- console.log(' System ready');
208
- console.log(` Backend ${BACKEND_URL}`);
209
- console.log(` UI ${FRONTEND_URL}`);
210
- console.log(' ' + ''.repeat(58));
213
+ console.log('\n ' + '-'.repeat(58));
214
+ console.log(' System ready');
215
+ console.log(` Backend -> ${BACKEND_URL}`);
216
+ console.log(` UI -> ${FRONTEND_URL}`);
217
+ console.log(' ' + '-'.repeat(58));
211
218
  console.log('\n Press Ctrl+C to stop.\n');
212
219
  const shutdown = () => {
213
220
  log('Shutting down...');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "k8s-av",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Kubernetes RBAC Attack Path Visualizer — scan your cluster, detect attack paths, visualize in a local UI",
5
5
  "keywords": [
6
6
  "kubernetes",
package/ui/package.json CHANGED
@@ -14,7 +14,8 @@
14
14
  "jspdf": "^4.2.1",
15
15
  "react": "^18.3.1",
16
16
  "react-dom": "^18.3.1",
17
- "zustand": "^4.5.2"
17
+ "zustand": "^4.5.2",
18
+ "vite": "^5.2.11"
18
19
  },
19
20
  "devDependencies": {
20
21
  "@types/dagre": "^0.7.52",