infrawise 0.5.0 → 0.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 +5 -11
- package/dist/adapters/aws.js +50 -64
- package/dist/adapters/dynamodb.js +17 -22
- package/dist/adapters/logs.js +12 -16
- package/dist/adapters/mongodb.js +10 -16
- package/dist/adapters/mysql.js +8 -17
- package/dist/adapters/postgres.js +9 -13
- package/dist/adapters/terraform.js +14 -56
- package/dist/analyzers/aws-services.js +7 -17
- package/dist/analyzers/dynamodb.js +6 -12
- package/dist/analyzers/index.js +13 -41
- package/dist/analyzers/mongodb.js +4 -9
- package/dist/analyzers/mysql.js +4 -9
- package/dist/analyzers/postgres.js +3 -9
- package/dist/analyzers/rds.js +5 -13
- package/dist/analyzers/terraform.js +1 -5
- package/dist/cli/commands/analyze.js +118 -158
- package/dist/cli/commands/auth.js +24 -30
- package/dist/cli/commands/dev.js +45 -84
- package/dist/cli/commands/doctor.js +35 -74
- package/dist/cli/commands/init.js +33 -72
- package/dist/cli/index.js +21 -23
- package/dist/cli/utils.js +40 -86
- package/dist/context/index.js +49 -85
- package/dist/core/cache.js +5 -43
- package/dist/core/config.js +43 -82
- package/dist/core/errors.js +7 -17
- package/dist/core/index.js +4 -22
- package/dist/core/logger.js +4 -10
- package/dist/graph/index.js +15 -32
- package/dist/server/index.js +84 -89
- package/dist/types.js +1 -2
- package/package.json +31 -30
package/dist/cli/commands/dev.js
CHANGED
|
@@ -1,50 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.runDev = runDev;
|
|
40
|
-
const fs = __importStar(require("fs"));
|
|
41
|
-
const path = __importStar(require("path"));
|
|
42
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
43
|
-
const ora_1 = __importDefault(require("ora"));
|
|
44
|
-
const core_1 = require("../../core");
|
|
45
|
-
const server_1 = require("../../server");
|
|
46
|
-
const utils_1 = require("../utils");
|
|
47
|
-
const analyze_1 = require("./analyze");
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import ora from 'ora';
|
|
5
|
+
import { loadConfig, formatError, readCache } from '../../core/index.js';
|
|
6
|
+
import { createServer, setGraphState } from '../../server/index.js';
|
|
7
|
+
import { log, printHeader } from '../utils.js';
|
|
8
|
+
import { runAnalyze, runCodeRefresh } from './analyze.js';
|
|
48
9
|
const BOX_W = 52;
|
|
49
10
|
const TOOL_MAP = [
|
|
50
11
|
{ name: 'get_infra_overview' },
|
|
@@ -69,10 +30,10 @@ function isEnabled(cfg, service) {
|
|
|
69
30
|
}
|
|
70
31
|
function boxLine(visibleContent, coloredContent) {
|
|
71
32
|
const padding = ' '.repeat(Math.max(0, BOX_W - visibleContent.length));
|
|
72
|
-
console.log(
|
|
33
|
+
console.log(chalk.dim(' │') + coloredContent + padding + chalk.dim('│'));
|
|
73
34
|
}
|
|
74
35
|
function boxDivider() {
|
|
75
|
-
console.log(
|
|
36
|
+
console.log(chalk.dim(' ├────────────────────────────────────────────────────┤'));
|
|
76
37
|
}
|
|
77
38
|
function groupTools(tools) {
|
|
78
39
|
const lines = [];
|
|
@@ -91,40 +52,40 @@ function groupTools(tools) {
|
|
|
91
52
|
}
|
|
92
53
|
return lines;
|
|
93
54
|
}
|
|
94
|
-
async function runDev(options = {}) {
|
|
55
|
+
export async function runDev(options = {}) {
|
|
95
56
|
const port = options.port ?? 3000;
|
|
96
|
-
|
|
57
|
+
printHeader('MCP Server');
|
|
97
58
|
let config;
|
|
98
59
|
try {
|
|
99
|
-
config =
|
|
100
|
-
|
|
60
|
+
config = loadConfig(options.config);
|
|
61
|
+
log.success('Config loaded', options.config ?? 'infrawise.yaml');
|
|
101
62
|
}
|
|
102
63
|
catch (err) {
|
|
103
|
-
console.error(
|
|
64
|
+
console.error(formatError(err));
|
|
104
65
|
process.exit(1);
|
|
105
66
|
}
|
|
106
67
|
const repoPath = process.cwd();
|
|
107
68
|
// Auto-analyze if no cache
|
|
108
|
-
const cachedGraph =
|
|
109
|
-
const cachedFindings =
|
|
69
|
+
const cachedGraph = readCache('graph');
|
|
70
|
+
const cachedFindings = readCache('findings');
|
|
110
71
|
if (cachedGraph && cachedFindings) {
|
|
111
|
-
|
|
112
|
-
|
|
72
|
+
log.success('Cached analysis loaded', `${cachedGraph.nodes.length} nodes · ${cachedGraph.edges.length} edges · ${cachedFindings.length} finding(s)`);
|
|
73
|
+
setGraphState(cachedGraph, cachedFindings);
|
|
113
74
|
}
|
|
114
75
|
else {
|
|
115
|
-
|
|
76
|
+
log.warn('No cache found — running analysis now...');
|
|
116
77
|
console.log('');
|
|
117
|
-
await
|
|
118
|
-
const freshGraph =
|
|
119
|
-
const freshFindings =
|
|
120
|
-
|
|
78
|
+
await runAnalyze({ repo: repoPath, config: options.config });
|
|
79
|
+
const freshGraph = readCache('graph') ?? { nodes: [], edges: [] };
|
|
80
|
+
const freshFindings = readCache('findings') ?? [];
|
|
81
|
+
setGraphState(freshGraph, freshFindings);
|
|
121
82
|
}
|
|
122
83
|
console.log('');
|
|
123
84
|
// Start server
|
|
124
|
-
const spin = (
|
|
125
|
-
const { start } =
|
|
85
|
+
const spin = ora({ text: chalk.dim('Starting server...'), color: 'cyan' }).start();
|
|
86
|
+
const { start } = createServer(port);
|
|
126
87
|
await start();
|
|
127
|
-
spin.succeed(
|
|
88
|
+
spin.succeed(chalk.green('Server running'));
|
|
128
89
|
// Compute active/inactive tools from config
|
|
129
90
|
const activeTools = TOOL_MAP.filter((t) => isEnabled(config, t.service)).map((t) => t.name);
|
|
130
91
|
const inactiveTools = TOOL_MAP.filter((t) => !isEnabled(config, t.service)).map((t) => t.name);
|
|
@@ -133,30 +94,30 @@ async function runDev(options = {}) {
|
|
|
133
94
|
const healthUrl = `http://localhost:${port}/health`;
|
|
134
95
|
// Print box
|
|
135
96
|
console.log('');
|
|
136
|
-
console.log(
|
|
137
|
-
boxLine(' MCP Server',
|
|
97
|
+
console.log(chalk.dim(' ┌────────────────────────────────────────────────────┐'));
|
|
98
|
+
boxLine(' MCP Server', chalk.bold(' MCP Server'));
|
|
138
99
|
boxDivider();
|
|
139
|
-
boxLine(` POST ${mcpUrl}`, ` ${
|
|
140
|
-
boxLine(` GET ${healthUrl}`, ` ${
|
|
100
|
+
boxLine(` POST ${mcpUrl}`, ` ${chalk.dim('POST')} ${chalk.cyan(mcpUrl)}`);
|
|
101
|
+
boxLine(` GET ${healthUrl}`, ` ${chalk.dim('GET')} ${chalk.cyan(healthUrl)}`);
|
|
141
102
|
boxDivider();
|
|
142
103
|
const activeLabel = ` Tools (${activeTools.length} active${inactiveTools.length > 0 ? ` · ${inactiveTools.length} off` : ''})`;
|
|
143
|
-
boxLine(activeLabel,
|
|
104
|
+
boxLine(activeLabel, chalk.dim(activeLabel));
|
|
144
105
|
for (const line of groupTools(activeTools)) {
|
|
145
106
|
boxLine(` ${line}`, ` ${line}`);
|
|
146
107
|
}
|
|
147
108
|
if (inactiveTools.length > 0) {
|
|
148
109
|
boxDivider();
|
|
149
|
-
boxLine(' Off (enable in infrawise.yaml):',
|
|
110
|
+
boxLine(' Off (enable in infrawise.yaml):', chalk.dim(' Off (enable in infrawise.yaml):'));
|
|
150
111
|
for (const line of groupTools(inactiveTools)) {
|
|
151
|
-
boxLine(` ${line}`,
|
|
112
|
+
boxLine(` ${line}`, chalk.dim(` ${line}`));
|
|
152
113
|
}
|
|
153
114
|
}
|
|
154
|
-
console.log(
|
|
115
|
+
console.log(chalk.dim(' └────────────────────────────────────────────────────┘'));
|
|
155
116
|
console.log('');
|
|
156
|
-
console.log(
|
|
157
|
-
console.log(
|
|
117
|
+
console.log(chalk.dim(' Add via CLI:'));
|
|
118
|
+
console.log(chalk.dim(` claude mcp add --transport http infrawise ${mcpUrl}`));
|
|
158
119
|
console.log('');
|
|
159
|
-
console.log(
|
|
120
|
+
console.log(chalk.dim(' Watching for file changes... Press Ctrl+C to stop\n'));
|
|
160
121
|
// File watch — re-run code analysis on save, skip slow AWS/DB extraction
|
|
161
122
|
let debounceTimer = null;
|
|
162
123
|
let refreshing = false;
|
|
@@ -167,7 +128,7 @@ async function runDev(options = {}) {
|
|
|
167
128
|
return;
|
|
168
129
|
const abs = path.join(repoPath, filename);
|
|
169
130
|
if (abs === configFile) {
|
|
170
|
-
console.log(
|
|
131
|
+
console.log(chalk.dim('\n infrawise.yaml changed — restart to apply config changes\n'));
|
|
171
132
|
return;
|
|
172
133
|
}
|
|
173
134
|
const ext = path.extname(filename);
|
|
@@ -181,14 +142,14 @@ async function runDev(options = {}) {
|
|
|
181
142
|
if (refreshing)
|
|
182
143
|
return;
|
|
183
144
|
refreshing = true;
|
|
184
|
-
const spin = (
|
|
145
|
+
const spin = ora({ text: chalk.dim('Refreshing code analysis...'), color: 'cyan' }).start();
|
|
185
146
|
try {
|
|
186
|
-
const { graph, findings } = await
|
|
187
|
-
|
|
188
|
-
spin.succeed(
|
|
147
|
+
const { graph, findings } = await runCodeRefresh(repoPath, config);
|
|
148
|
+
setGraphState(graph, findings);
|
|
149
|
+
spin.succeed(chalk.green('Analysis refreshed') + chalk.dim(` ${graph.nodes.length} nodes · ${findings.length} finding(s)`));
|
|
189
150
|
}
|
|
190
151
|
catch (err) {
|
|
191
|
-
spin.warn(
|
|
152
|
+
spin.warn(chalk.yellow('Refresh failed') + chalk.dim(` ${err instanceof Error ? err.message : String(err)}`));
|
|
192
153
|
}
|
|
193
154
|
finally {
|
|
194
155
|
refreshing = false;
|
|
@@ -200,7 +161,7 @@ async function runDev(options = {}) {
|
|
|
200
161
|
// fs.watch may not support recursive on all platforms — silently skip
|
|
201
162
|
}
|
|
202
163
|
process.on('SIGINT', () => {
|
|
203
|
-
console.log(
|
|
164
|
+
console.log(chalk.dim('\n Shutting down...\n'));
|
|
204
165
|
process.exit(0);
|
|
205
166
|
});
|
|
206
167
|
await new Promise(() => { });
|
|
@@ -1,78 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.runDoctor = runDoctor;
|
|
40
|
-
const fs = __importStar(require("fs"));
|
|
41
|
-
const path = __importStar(require("path"));
|
|
42
|
-
const os = __importStar(require("os"));
|
|
43
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
44
|
-
const ora_1 = __importDefault(require("ora"));
|
|
45
|
-
const core_1 = require("../../core");
|
|
46
|
-
const dynamodb_1 = require("../../adapters/dynamodb");
|
|
47
|
-
const postgres_1 = require("../../adapters/postgres");
|
|
48
|
-
const mysql_1 = require("../../adapters/mysql");
|
|
49
|
-
const mongodb_1 = require("../../adapters/mongodb");
|
|
50
|
-
const aws_1 = require("../../adapters/aws");
|
|
51
|
-
const logs_1 = require("../../adapters/logs");
|
|
52
|
-
const utils_1 = require("../utils");
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as os from 'os';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import ora from 'ora';
|
|
6
|
+
import { loadConfig } from '../../core/index.js';
|
|
7
|
+
import { probeDynamoAccess } from '../../adapters/dynamodb.js';
|
|
8
|
+
import { validatePostgresAccess } from '../../adapters/postgres.js';
|
|
9
|
+
import { validateMySQLAccess } from '../../adapters/mysql.js';
|
|
10
|
+
import { validateMongoAccess } from '../../adapters/mongodb.js';
|
|
11
|
+
import { validateSQSAccess, validateSNSAccess, validateSSMAccess, validateSecretsAccess, validateLambdaAccess, } from '../../adapters/aws.js';
|
|
12
|
+
import { validateLogsAccess } from '../../adapters/logs.js';
|
|
13
|
+
import { printHeader } from '../utils.js';
|
|
53
14
|
async function runCheck(label, fn) {
|
|
54
|
-
const spin = (
|
|
15
|
+
const spin = ora({ text: chalk.dim(label), color: 'cyan' }).start();
|
|
55
16
|
const result = await fn();
|
|
56
17
|
switch (result.status) {
|
|
57
18
|
case 'pass':
|
|
58
|
-
spin.succeed(
|
|
19
|
+
spin.succeed(chalk.green(result.name) + chalk.dim(` ${result.message}`));
|
|
59
20
|
break;
|
|
60
21
|
case 'fail':
|
|
61
|
-
spin.fail(
|
|
22
|
+
spin.fail(chalk.red(result.name) + chalk.dim(` ${result.message}`));
|
|
62
23
|
break;
|
|
63
24
|
case 'warn':
|
|
64
|
-
spin.warn(
|
|
25
|
+
spin.warn(chalk.yellow(result.name) + chalk.dim(` ${result.message}`));
|
|
65
26
|
break;
|
|
66
27
|
case 'skip':
|
|
67
|
-
spin.info(
|
|
28
|
+
spin.info(chalk.dim(`${result.name} ${result.message}`));
|
|
68
29
|
break;
|
|
69
30
|
}
|
|
70
31
|
if (result.detail)
|
|
71
|
-
console.log(
|
|
32
|
+
console.log(chalk.dim(` ${result.detail}`));
|
|
72
33
|
return result;
|
|
73
34
|
}
|
|
74
|
-
async function runDoctor(options = {}) {
|
|
75
|
-
|
|
35
|
+
export async function runDoctor(options = {}) {
|
|
36
|
+
printHeader('Infrawise Doctor');
|
|
76
37
|
const configPath = path.resolve(options.config ?? 'infrawise.yaml');
|
|
77
38
|
const results = [];
|
|
78
39
|
// Config file
|
|
@@ -91,7 +52,7 @@ async function runDoctor(options = {}) {
|
|
|
91
52
|
if (!fs.existsSync(configPath))
|
|
92
53
|
return { name: 'Config validation', status: 'skip', message: 'No config file' };
|
|
93
54
|
try {
|
|
94
|
-
config =
|
|
55
|
+
config = loadConfig(options.config);
|
|
95
56
|
return { name: 'Config validation', status: 'pass', message: `project: ${config.project}` };
|
|
96
57
|
}
|
|
97
58
|
catch (err) {
|
|
@@ -121,7 +82,7 @@ async function runDoctor(options = {}) {
|
|
|
121
82
|
if (config.dynamodb?.enabled !== true)
|
|
122
83
|
return { name: 'DynamoDB', status: 'skip', message: 'Disabled in config' };
|
|
123
84
|
try {
|
|
124
|
-
await
|
|
85
|
+
await probeDynamoAccess(config);
|
|
125
86
|
return { name: 'DynamoDB', status: 'pass', message: `Connected (profile: ${config.aws?.profile ?? 'default'})` };
|
|
126
87
|
}
|
|
127
88
|
catch (err) {
|
|
@@ -137,7 +98,7 @@ async function runDoctor(options = {}) {
|
|
|
137
98
|
if (config?.sqs?.enabled !== true)
|
|
138
99
|
return { name: 'SQS', status: 'skip', message: 'Disabled in config' };
|
|
139
100
|
try {
|
|
140
|
-
await
|
|
101
|
+
await validateSQSAccess(awsCfg);
|
|
141
102
|
return { name: 'SQS', status: 'pass', message: 'Connected' };
|
|
142
103
|
}
|
|
143
104
|
catch (err) {
|
|
@@ -153,7 +114,7 @@ async function runDoctor(options = {}) {
|
|
|
153
114
|
if (config?.sns?.enabled !== true)
|
|
154
115
|
return { name: 'SNS', status: 'skip', message: 'Disabled in config' };
|
|
155
116
|
try {
|
|
156
|
-
await
|
|
117
|
+
await validateSNSAccess(awsCfg);
|
|
157
118
|
return { name: 'SNS', status: 'pass', message: 'Connected' };
|
|
158
119
|
}
|
|
159
120
|
catch (err) {
|
|
@@ -169,7 +130,7 @@ async function runDoctor(options = {}) {
|
|
|
169
130
|
if (config?.ssm?.enabled !== true)
|
|
170
131
|
return { name: 'SSM', status: 'skip', message: 'Disabled in config' };
|
|
171
132
|
try {
|
|
172
|
-
await
|
|
133
|
+
await validateSSMAccess(awsCfg);
|
|
173
134
|
return { name: 'SSM', status: 'pass', message: 'Connected (metadata only)' };
|
|
174
135
|
}
|
|
175
136
|
catch (err) {
|
|
@@ -185,7 +146,7 @@ async function runDoctor(options = {}) {
|
|
|
185
146
|
if (config?.secretsManager?.enabled !== true)
|
|
186
147
|
return { name: 'Secrets Manager', status: 'skip', message: 'Disabled in config' };
|
|
187
148
|
try {
|
|
188
|
-
await
|
|
149
|
+
await validateSecretsAccess(awsCfg);
|
|
189
150
|
return { name: 'Secrets Manager', status: 'pass', message: 'Connected (names/rotation only)' };
|
|
190
151
|
}
|
|
191
152
|
catch (err) {
|
|
@@ -201,7 +162,7 @@ async function runDoctor(options = {}) {
|
|
|
201
162
|
if (config?.lambda?.enabled !== true)
|
|
202
163
|
return { name: 'Lambda', status: 'skip', message: 'Disabled in config' };
|
|
203
164
|
try {
|
|
204
|
-
await
|
|
165
|
+
await validateLambdaAccess(awsCfg);
|
|
205
166
|
return { name: 'Lambda', status: 'pass', message: 'Connected' };
|
|
206
167
|
}
|
|
207
168
|
catch (err) {
|
|
@@ -217,7 +178,7 @@ async function runDoctor(options = {}) {
|
|
|
217
178
|
if (!config?.cloudwatchLogs?.enabled)
|
|
218
179
|
return { name: 'CloudWatch Logs', status: 'skip', message: 'Not enabled in config' };
|
|
219
180
|
try {
|
|
220
|
-
await
|
|
181
|
+
await validateLogsAccess(awsCfg);
|
|
221
182
|
return { name: 'CloudWatch Logs', status: 'pass', message: 'Connected' };
|
|
222
183
|
}
|
|
223
184
|
catch (err) {
|
|
@@ -234,7 +195,7 @@ async function runDoctor(options = {}) {
|
|
|
234
195
|
return { name: 'PostgreSQL', status: 'skip', message: 'Not configured' };
|
|
235
196
|
}
|
|
236
197
|
try {
|
|
237
|
-
const ok = await
|
|
198
|
+
const ok = await validatePostgresAccess(config.postgres.connectionString);
|
|
238
199
|
return {
|
|
239
200
|
name: 'PostgreSQL', status: ok ? 'pass' : 'fail',
|
|
240
201
|
message: ok ? 'Connected' : 'Cannot connect',
|
|
@@ -251,7 +212,7 @@ async function runDoctor(options = {}) {
|
|
|
251
212
|
return { name: 'MySQL', status: 'skip', message: 'Not configured' };
|
|
252
213
|
}
|
|
253
214
|
try {
|
|
254
|
-
const ok = await
|
|
215
|
+
const ok = await validateMySQLAccess(config.mysql.connectionString);
|
|
255
216
|
return {
|
|
256
217
|
name: 'MySQL', status: ok ? 'pass' : 'fail',
|
|
257
218
|
message: ok ? 'Connected' : 'Cannot connect',
|
|
@@ -268,7 +229,7 @@ async function runDoctor(options = {}) {
|
|
|
268
229
|
return { name: 'MongoDB', status: 'skip', message: 'Not configured' };
|
|
269
230
|
}
|
|
270
231
|
try {
|
|
271
|
-
const ok = await
|
|
232
|
+
const ok = await validateMongoAccess(config.mongodb.connectionString);
|
|
272
233
|
return {
|
|
273
234
|
name: 'MongoDB', status: ok ? 'pass' : 'fail',
|
|
274
235
|
message: ok ? 'Connected' : 'Cannot connect',
|
|
@@ -329,12 +290,12 @@ async function runDoctor(options = {}) {
|
|
|
329
290
|
const failed = results.filter((r) => r.status === 'fail').length;
|
|
330
291
|
const warned = results.filter((r) => r.status === 'warn').length;
|
|
331
292
|
console.log('');
|
|
332
|
-
console.log(
|
|
293
|
+
console.log(chalk.dim(' ' + '─'.repeat(40)));
|
|
333
294
|
if (failed === 0) {
|
|
334
|
-
console.log(` ${
|
|
295
|
+
console.log(` ${chalk.green.bold('All checks passed')} ${chalk.dim(`${passed} passed, ${warned} warning(s)`)}`);
|
|
335
296
|
}
|
|
336
297
|
else {
|
|
337
|
-
console.log(` ${
|
|
298
|
+
console.log(` ${chalk.red.bold(`${failed} check(s) failed`)} ${chalk.dim(`${passed} passed, ${warned} warning(s)`)}`);
|
|
338
299
|
}
|
|
339
300
|
console.log('');
|
|
340
301
|
if (failed > 0)
|
|
@@ -1,66 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.runInit = runInit;
|
|
40
|
-
const fs = __importStar(require("fs"));
|
|
41
|
-
const path = __importStar(require("path"));
|
|
42
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
43
|
-
const inquirer_1 = __importDefault(require("inquirer"));
|
|
44
|
-
const core_1 = require("../../core");
|
|
45
|
-
const utils_1 = require("../utils");
|
|
46
|
-
async function runInit(options = {}) {
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
import { generateDefaultConfig } from '../../core/index.js';
|
|
6
|
+
import { readAWSProfiles, detectAWSRegion, detectRepoType, log, printHeader } from '../utils.js';
|
|
7
|
+
export async function runInit(options = {}) {
|
|
47
8
|
const cwd = process.cwd();
|
|
48
9
|
const configPath = path.join(cwd, 'infrawise.yaml');
|
|
49
10
|
if (fs.existsSync(configPath) && !options.force) {
|
|
50
|
-
console.log(`\n ${
|
|
11
|
+
console.log(`\n ${chalk.yellow('⚠')} ${chalk.yellow('infrawise.yaml already exists.')} ${chalk.dim('Use --force to overwrite.')}\n`);
|
|
51
12
|
return;
|
|
52
13
|
}
|
|
53
|
-
|
|
54
|
-
const repoType =
|
|
14
|
+
printHeader('Initialize Infrawise');
|
|
15
|
+
const repoType = detectRepoType(cwd);
|
|
55
16
|
const repoName = path.basename(cwd);
|
|
56
|
-
const profiles =
|
|
57
|
-
const detectedRegion =
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
17
|
+
const profiles = readAWSProfiles();
|
|
18
|
+
const detectedRegion = detectAWSRegion();
|
|
19
|
+
log.success(`Repository detected`, repoName);
|
|
20
|
+
log.success(`Type`, repoType);
|
|
21
|
+
log.success(`AWS profiles found`, String(profiles.length));
|
|
61
22
|
console.log('');
|
|
62
23
|
// ── Core settings ──────────────────────────────────────────────────────────
|
|
63
|
-
const core = await
|
|
24
|
+
const core = await inquirer.prompt([
|
|
64
25
|
{
|
|
65
26
|
type: 'input',
|
|
66
27
|
name: 'project',
|
|
@@ -72,10 +33,10 @@ async function runInit(options = {}) {
|
|
|
72
33
|
name: 'awsProfile',
|
|
73
34
|
message: 'AWS profile:',
|
|
74
35
|
choices: [
|
|
75
|
-
new
|
|
36
|
+
new inquirer.Separator('── no profile ──'),
|
|
76
37
|
{ name: 'Environment variables (CI/CD, real AWS)', value: '__env__' },
|
|
77
38
|
{ name: 'LocalStack (local development)', value: '__localstack__' },
|
|
78
|
-
new
|
|
39
|
+
new inquirer.Separator('── named profiles ──'),
|
|
79
40
|
...profiles,
|
|
80
41
|
],
|
|
81
42
|
default: profiles[0],
|
|
@@ -95,9 +56,9 @@ async function runInit(options = {}) {
|
|
|
95
56
|
},
|
|
96
57
|
]);
|
|
97
58
|
// ── Databases ──────────────────────────────────────────────────────────────
|
|
98
|
-
console.log('\n ' +
|
|
99
|
-
console.log(
|
|
100
|
-
const databases = await
|
|
59
|
+
console.log('\n ' + chalk.bold('Databases'));
|
|
60
|
+
console.log(chalk.dim(' Self-hosted databases (PostgreSQL, MySQL, MongoDB).'));
|
|
61
|
+
const databases = await inquirer.prompt([
|
|
101
62
|
{
|
|
102
63
|
type: 'confirm',
|
|
103
64
|
name: 'pgEnabled',
|
|
@@ -139,9 +100,9 @@ async function runInit(options = {}) {
|
|
|
139
100
|
},
|
|
140
101
|
]);
|
|
141
102
|
// ── AWS services ───────────────────────────────────────────────────────────
|
|
142
|
-
console.log('\n ' +
|
|
143
|
-
console.log(
|
|
144
|
-
const services = await
|
|
103
|
+
console.log('\n ' + chalk.bold('AWS Services'));
|
|
104
|
+
console.log(chalk.dim(' Infrawise will introspect these services using the credentials configured above.'));
|
|
105
|
+
const services = await inquirer.prompt([
|
|
145
106
|
{
|
|
146
107
|
type: 'confirm',
|
|
147
108
|
name: 'dynamoEnabled',
|
|
@@ -153,7 +114,7 @@ async function runInit(options = {}) {
|
|
|
153
114
|
name: 'dynamoTables',
|
|
154
115
|
message: 'DynamoDB tables to include:',
|
|
155
116
|
default: '',
|
|
156
|
-
suffix:
|
|
117
|
+
suffix: chalk.dim(' (comma-separated, blank = all)'),
|
|
157
118
|
when: (a) => a.dynamoEnabled,
|
|
158
119
|
},
|
|
159
120
|
{
|
|
@@ -179,7 +140,7 @@ async function runInit(options = {}) {
|
|
|
179
140
|
name: 'ssmPaths',
|
|
180
141
|
message: 'SSM path prefixes to filter:',
|
|
181
142
|
default: '',
|
|
182
|
-
suffix:
|
|
143
|
+
suffix: chalk.dim(' (comma-separated, blank = all e.g. /myapp/prod)'),
|
|
183
144
|
when: (a) => a.ssmEnabled,
|
|
184
145
|
},
|
|
185
146
|
{
|
|
@@ -205,7 +166,7 @@ async function runInit(options = {}) {
|
|
|
205
166
|
name: 'logGroupPrefixes',
|
|
206
167
|
message: 'CloudWatch log group prefixes:',
|
|
207
168
|
default: '',
|
|
208
|
-
suffix:
|
|
169
|
+
suffix: chalk.dim(' (comma-separated, blank = all)'),
|
|
209
170
|
when: (a) => a.logsEnabled,
|
|
210
171
|
},
|
|
211
172
|
]);
|
|
@@ -223,7 +184,7 @@ async function runInit(options = {}) {
|
|
|
223
184
|
const isEnvVars = core.awsProfile === '__env__';
|
|
224
185
|
const resolvedProfile = isLocalStack || isEnvVars ? '' : core.awsProfile;
|
|
225
186
|
const resolvedEndpoint = isLocalStack ? (core.endpoint || 'http://localhost:4566') : undefined;
|
|
226
|
-
const configContent =
|
|
187
|
+
const configContent = generateDefaultConfig(core.project, {
|
|
227
188
|
aws: { profile: resolvedProfile, region: core.region, endpoint: resolvedEndpoint },
|
|
228
189
|
dynamodb: { enabled: services.dynamoEnabled, includeTables },
|
|
229
190
|
postgres: { enabled: databases.pgEnabled, connectionString: databases.pgConnectionString ?? '' },
|
|
@@ -242,11 +203,11 @@ async function runInit(options = {}) {
|
|
|
242
203
|
});
|
|
243
204
|
fs.writeFileSync(configPath, configContent, 'utf-8');
|
|
244
205
|
console.log('');
|
|
245
|
-
|
|
206
|
+
log.success(`Created ${chalk.bold('infrawise.yaml')}`);
|
|
246
207
|
console.log('');
|
|
247
|
-
console.log(
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
208
|
+
console.log(chalk.bold(' Next steps:'));
|
|
209
|
+
log.info(`Run ${chalk.cyan('infrawise doctor')} to validate your setup`);
|
|
210
|
+
log.info(`Run ${chalk.cyan('infrawise analyze')} to scan your infrastructure`);
|
|
211
|
+
log.info(`Run ${chalk.cyan('infrawise dev')} to start the MCP server`);
|
|
251
212
|
console.log('');
|
|
252
213
|
}
|