infrawise 0.4.2 → 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 +21 -48
- 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 +178 -215
- package/dist/cli/commands/auth.js +24 -30
- package/dist/cli/commands/dev.js +84 -43
- package/dist/cli/commands/doctor.js +35 -74
- package/dist/cli/commands/init.js +33 -72
- package/dist/cli/index.js +21 -28
- 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 -81
- 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 +236 -302
- package/dist/types.js +1 -2
- package/package.json +34 -31
package/dist/context/index.js
CHANGED
|
@@ -1,43 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
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
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.scanRepository = scanRepository;
|
|
37
|
-
const path = __importStar(require("path"));
|
|
38
|
-
const fs = __importStar(require("fs"));
|
|
39
|
-
const ts_morph_1 = require("ts-morph");
|
|
40
|
-
const core_1 = require("../core");
|
|
1
|
+
import * as path from 'path';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import { Project, SyntaxKind, Node } from 'ts-morph';
|
|
4
|
+
import { RepositoryScanError, logger } from '../core/index.js';
|
|
41
5
|
const DYNAMO_OPERATIONS = new Set([
|
|
42
6
|
'query',
|
|
43
7
|
'scan',
|
|
@@ -109,19 +73,19 @@ const PRISMA_METHODS = new Set([
|
|
|
109
73
|
function getEnclosingFunctionName(node) {
|
|
110
74
|
let current = node.getParent();
|
|
111
75
|
while (current) {
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if (
|
|
76
|
+
if (Node.isFunctionDeclaration(current) ||
|
|
77
|
+
Node.isFunctionExpression(current) ||
|
|
78
|
+
Node.isArrowFunction(current) ||
|
|
79
|
+
Node.isMethodDeclaration(current)) {
|
|
80
|
+
if (Node.isFunctionDeclaration(current) || Node.isMethodDeclaration(current)) {
|
|
117
81
|
return current.getName() ?? '<anonymous>';
|
|
118
82
|
}
|
|
119
83
|
// Arrow function or function expression — check if assigned to a variable
|
|
120
84
|
const parent = current.getParent();
|
|
121
|
-
if (parent &&
|
|
85
|
+
if (parent && Node.isVariableDeclaration(parent)) {
|
|
122
86
|
return parent.getName();
|
|
123
87
|
}
|
|
124
|
-
if (parent &&
|
|
88
|
+
if (parent && Node.isPropertyAssignment(parent)) {
|
|
125
89
|
return parent.getName();
|
|
126
90
|
}
|
|
127
91
|
return '<anonymous>';
|
|
@@ -131,15 +95,15 @@ function getEnclosingFunctionName(node) {
|
|
|
131
95
|
return '<module>';
|
|
132
96
|
}
|
|
133
97
|
function extractTableNameFromArg(arg) {
|
|
134
|
-
if (
|
|
98
|
+
if (Node.isStringLiteral(arg)) {
|
|
135
99
|
return arg.getLiteralValue();
|
|
136
100
|
}
|
|
137
|
-
if (
|
|
101
|
+
if (Node.isObjectLiteralExpression(arg)) {
|
|
138
102
|
// Look for TableName property
|
|
139
103
|
for (const prop of arg.getProperties()) {
|
|
140
|
-
if (
|
|
104
|
+
if (Node.isPropertyAssignment(prop) && prop.getName() === 'TableName') {
|
|
141
105
|
const init = prop.getInitializer();
|
|
142
|
-
if (init &&
|
|
106
|
+
if (init && Node.isStringLiteral(init)) {
|
|
143
107
|
return init.getLiteralValue();
|
|
144
108
|
}
|
|
145
109
|
}
|
|
@@ -151,11 +115,11 @@ function detectDynamoOperations(callExpr, filePath) {
|
|
|
151
115
|
const expr = callExpr.getExpression();
|
|
152
116
|
const args = callExpr.getArguments();
|
|
153
117
|
// Pattern 1: client.send(new QueryCommand({ TableName: '...' }))
|
|
154
|
-
if (
|
|
118
|
+
if (Node.isPropertyAccessExpression(expr)) {
|
|
155
119
|
const methodName = expr.getName();
|
|
156
120
|
if (methodName === 'send' && args.length > 0) {
|
|
157
121
|
const firstArg = args[0];
|
|
158
|
-
if (
|
|
122
|
+
if (Node.isNewExpression(firstArg)) {
|
|
159
123
|
const className = firstArg.getExpression().getText();
|
|
160
124
|
if (DYNAMO_OPERATIONS.has(className)) {
|
|
161
125
|
const cmdArgs = firstArg.getArguments();
|
|
@@ -205,7 +169,7 @@ function extractSqlTableName(sql) {
|
|
|
205
169
|
function detectPostgresOperations(callExpr, filePath) {
|
|
206
170
|
const expr = callExpr.getExpression();
|
|
207
171
|
const args = callExpr.getArguments();
|
|
208
|
-
if (!
|
|
172
|
+
if (!Node.isPropertyAccessExpression(expr))
|
|
209
173
|
return null;
|
|
210
174
|
const methodName = expr.getName();
|
|
211
175
|
const objExpr = expr.getExpression();
|
|
@@ -220,13 +184,13 @@ function detectPostgresOperations(callExpr, filePath) {
|
|
|
220
184
|
let tableName = 'unknown';
|
|
221
185
|
if (args.length > 0) {
|
|
222
186
|
const firstArg = args[0];
|
|
223
|
-
if (
|
|
187
|
+
if (Node.isStringLiteral(firstArg)) {
|
|
224
188
|
tableName = extractSqlTableName(firstArg.getLiteralValue());
|
|
225
189
|
}
|
|
226
|
-
else if (
|
|
190
|
+
else if (Node.isNoSubstitutionTemplateLiteral(firstArg)) {
|
|
227
191
|
tableName = extractSqlTableName(firstArg.getLiteralText());
|
|
228
192
|
}
|
|
229
|
-
else if (
|
|
193
|
+
else if (Node.isTemplateExpression(firstArg)) {
|
|
230
194
|
// Template literal — extract what we can from the head
|
|
231
195
|
tableName = extractSqlTableName(firstArg.getHead().getLiteralText());
|
|
232
196
|
}
|
|
@@ -243,7 +207,7 @@ function detectPostgresOperations(callExpr, filePath) {
|
|
|
243
207
|
// Pattern: Prisma — prisma.user.findMany(), prisma.orders.create()
|
|
244
208
|
if (PRISMA_METHODS.has(methodName)) {
|
|
245
209
|
const accessChain = objExpr;
|
|
246
|
-
if (
|
|
210
|
+
if (Node.isPropertyAccessExpression(accessChain)) {
|
|
247
211
|
const modelName = accessChain.getName();
|
|
248
212
|
const rootObj = accessChain.getExpression().getText().toLowerCase();
|
|
249
213
|
if (rootObj.includes('prisma')) {
|
|
@@ -273,11 +237,11 @@ function detectPostgresOperations(callExpr, filePath) {
|
|
|
273
237
|
};
|
|
274
238
|
}
|
|
275
239
|
// Knex call expression style: knex('users').select(...)
|
|
276
|
-
if (
|
|
240
|
+
if (Node.isCallExpression(objExpr)) {
|
|
277
241
|
const innerExpr = objExpr.getExpression();
|
|
278
242
|
if (innerExpr.getText().toLowerCase().match(/knex|db|trx/)) {
|
|
279
243
|
const innerArgs = objExpr.getArguments();
|
|
280
|
-
const tableName = innerArgs.length > 0 &&
|
|
244
|
+
const tableName = innerArgs.length > 0 && Node.isStringLiteral(innerArgs[0])
|
|
281
245
|
? innerArgs[0].getLiteralValue()
|
|
282
246
|
: 'unknown';
|
|
283
247
|
return {
|
|
@@ -295,7 +259,7 @@ function detectPostgresOperations(callExpr, filePath) {
|
|
|
295
259
|
function detectMySQLOperations(callExpr, filePath) {
|
|
296
260
|
const expr = callExpr.getExpression();
|
|
297
261
|
const args = callExpr.getArguments();
|
|
298
|
-
if (!
|
|
262
|
+
if (!Node.isPropertyAccessExpression(expr))
|
|
299
263
|
return null;
|
|
300
264
|
const methodName = expr.getName();
|
|
301
265
|
const objExpr = expr.getExpression();
|
|
@@ -307,13 +271,13 @@ function detectMySQLOperations(callExpr, filePath) {
|
|
|
307
271
|
let tableName = 'unknown';
|
|
308
272
|
if (args.length > 0) {
|
|
309
273
|
const firstArg = args[0];
|
|
310
|
-
if (
|
|
274
|
+
if (Node.isStringLiteral(firstArg)) {
|
|
311
275
|
tableName = extractSqlTableName(firstArg.getLiteralValue());
|
|
312
276
|
}
|
|
313
|
-
else if (
|
|
277
|
+
else if (Node.isNoSubstitutionTemplateLiteral(firstArg)) {
|
|
314
278
|
tableName = extractSqlTableName(firstArg.getLiteralText());
|
|
315
279
|
}
|
|
316
|
-
else if (
|
|
280
|
+
else if (Node.isTemplateExpression(firstArg)) {
|
|
317
281
|
tableName = extractSqlTableName(firstArg.getHead().getLiteralText());
|
|
318
282
|
}
|
|
319
283
|
}
|
|
@@ -330,9 +294,9 @@ function detectMySQLOperations(callExpr, filePath) {
|
|
|
330
294
|
if (KNEX_METHODS.has(methodName)) {
|
|
331
295
|
if (objText.includes('mysql') || objText.includes('knex')) {
|
|
332
296
|
let tableName = 'unknown';
|
|
333
|
-
if (
|
|
297
|
+
if (Node.isCallExpression(objExpr)) {
|
|
334
298
|
const innerArgs = objExpr.getArguments();
|
|
335
|
-
if (innerArgs.length > 0 &&
|
|
299
|
+
if (innerArgs.length > 0 && Node.isStringLiteral(innerArgs[0])) {
|
|
336
300
|
tableName = innerArgs[0].getLiteralValue();
|
|
337
301
|
}
|
|
338
302
|
}
|
|
@@ -349,7 +313,7 @@ function detectMySQLOperations(callExpr, filePath) {
|
|
|
349
313
|
}
|
|
350
314
|
function detectMongoOperations(callExpr, filePath) {
|
|
351
315
|
const expr = callExpr.getExpression();
|
|
352
|
-
if (!
|
|
316
|
+
if (!Node.isPropertyAccessExpression(expr))
|
|
353
317
|
return null;
|
|
354
318
|
const methodName = expr.getName();
|
|
355
319
|
const objExpr = expr.getExpression();
|
|
@@ -365,17 +329,17 @@ function detectMongoOperations(callExpr, filePath) {
|
|
|
365
329
|
/^[A-Z][a-zA-Z]+$/.test(objExpr.getText())) {
|
|
366
330
|
let collectionName = 'unknown';
|
|
367
331
|
// Try to get collection name from db.collection('name')
|
|
368
|
-
if (
|
|
332
|
+
if (Node.isCallExpression(objExpr)) {
|
|
369
333
|
const innerExpr = objExpr.getExpression();
|
|
370
|
-
if (
|
|
334
|
+
if (Node.isPropertyAccessExpression(innerExpr) &&
|
|
371
335
|
MONGO_COLLECTION_METHODS.has(innerExpr.getName())) {
|
|
372
336
|
const innerArgs = objExpr.getArguments();
|
|
373
|
-
if (innerArgs.length > 0 &&
|
|
337
|
+
if (innerArgs.length > 0 && Node.isStringLiteral(innerArgs[0])) {
|
|
374
338
|
collectionName = innerArgs[0].getLiteralValue();
|
|
375
339
|
}
|
|
376
340
|
}
|
|
377
341
|
}
|
|
378
|
-
else if (
|
|
342
|
+
else if (Node.isPropertyAccessExpression(objExpr)) {
|
|
379
343
|
// db.users.find() → collection name is the property
|
|
380
344
|
collectionName = objExpr.getName();
|
|
381
345
|
}
|
|
@@ -398,7 +362,7 @@ function detectMongoOperations(callExpr, filePath) {
|
|
|
398
362
|
const args = callExpr.getArguments();
|
|
399
363
|
const objText = objExpr.getText().toLowerCase();
|
|
400
364
|
if (objText.includes('db') || objText.includes('mongo')) {
|
|
401
|
-
const collectionName = args.length > 0 &&
|
|
365
|
+
const collectionName = args.length > 0 && Node.isStringLiteral(args[0])
|
|
402
366
|
? args[0].getLiteralValue()
|
|
403
367
|
: 'unknown';
|
|
404
368
|
return {
|
|
@@ -413,11 +377,11 @@ function detectMongoOperations(callExpr, filePath) {
|
|
|
413
377
|
return null;
|
|
414
378
|
}
|
|
415
379
|
function extractArgValue(arg, ...keys) {
|
|
416
|
-
if (
|
|
380
|
+
if (Node.isObjectLiteralExpression(arg)) {
|
|
417
381
|
for (const prop of arg.getProperties()) {
|
|
418
|
-
if (
|
|
382
|
+
if (Node.isPropertyAssignment(prop) && keys.includes(prop.getName())) {
|
|
419
383
|
const init = prop.getInitializer();
|
|
420
|
-
if (init &&
|
|
384
|
+
if (init && Node.isStringLiteral(init)) {
|
|
421
385
|
// For ARNs, extract the last segment as a readable name
|
|
422
386
|
const val = init.getLiteralValue();
|
|
423
387
|
return val.includes(':') ? (val.split(':').pop() ?? val) : val;
|
|
@@ -430,7 +394,7 @@ function extractArgValue(arg, ...keys) {
|
|
|
430
394
|
function detectKafkaOperations(callExpr, filePath) {
|
|
431
395
|
const expr = callExpr.getExpression();
|
|
432
396
|
const args = callExpr.getArguments();
|
|
433
|
-
if (!
|
|
397
|
+
if (!Node.isPropertyAccessExpression(expr))
|
|
434
398
|
return null;
|
|
435
399
|
const methodName = expr.getName();
|
|
436
400
|
const objText = expr.getExpression().getText().toLowerCase();
|
|
@@ -460,9 +424,9 @@ function detectAWSServiceOperations(callExpr, filePath) {
|
|
|
460
424
|
const expr = callExpr.getExpression();
|
|
461
425
|
const args = callExpr.getArguments();
|
|
462
426
|
// Pattern 1: client.send(new XCommand({ ... }))
|
|
463
|
-
if (
|
|
427
|
+
if (Node.isPropertyAccessExpression(expr) && expr.getName() === 'send' && args.length > 0) {
|
|
464
428
|
const firstArg = args[0];
|
|
465
|
-
if (
|
|
429
|
+
if (Node.isNewExpression(firstArg)) {
|
|
466
430
|
const className = firstArg.getExpression().getText();
|
|
467
431
|
const cmdArgs = firstArg.getArguments();
|
|
468
432
|
if (SQS_COMMANDS.has(className)) {
|
|
@@ -513,7 +477,7 @@ function detectAWSServiceOperations(callExpr, filePath) {
|
|
|
513
477
|
}
|
|
514
478
|
}
|
|
515
479
|
// Pattern 2: awsService.method({ ... }) — v2-style or SDK-wrapped clients
|
|
516
|
-
if (
|
|
480
|
+
if (Node.isPropertyAccessExpression(expr)) {
|
|
517
481
|
const methodName = expr.getName();
|
|
518
482
|
const objText = expr.getExpression().getText().toLowerCase();
|
|
519
483
|
if (SQS_COMMANDS.has(methodName) && (objText.includes('sqs') || objText.includes('queue'))) {
|
|
@@ -564,14 +528,14 @@ function detectAWSServiceOperations(callExpr, filePath) {
|
|
|
564
528
|
}
|
|
565
529
|
return null;
|
|
566
530
|
}
|
|
567
|
-
async function scanRepository(repoPath) {
|
|
531
|
+
export async function scanRepository(repoPath) {
|
|
568
532
|
const resolvedPath = path.resolve(repoPath);
|
|
569
533
|
if (!fs.existsSync(resolvedPath)) {
|
|
570
|
-
throw new
|
|
534
|
+
throw new RepositoryScanError(`Path does not exist: ${resolvedPath}`);
|
|
571
535
|
}
|
|
572
536
|
const tsconfigPath = path.join(resolvedPath, 'tsconfig.json');
|
|
573
537
|
const hasTsConfig = fs.existsSync(tsconfigPath);
|
|
574
|
-
const project = new
|
|
538
|
+
const project = new Project({
|
|
575
539
|
tsConfigFilePath: hasTsConfig ? tsconfigPath : undefined,
|
|
576
540
|
compilerOptions: hasTsConfig
|
|
577
541
|
? undefined
|
|
@@ -591,14 +555,14 @@ async function scanRepository(repoPath) {
|
|
|
591
555
|
]);
|
|
592
556
|
}
|
|
593
557
|
const sourceFiles = project.getSourceFiles();
|
|
594
|
-
|
|
558
|
+
logger.debug(`Scanning ${sourceFiles.length} TypeScript file(s) in ${resolvedPath}`);
|
|
595
559
|
const operations = [];
|
|
596
560
|
for (const sourceFile of sourceFiles) {
|
|
597
561
|
const filePath = sourceFile.getFilePath();
|
|
598
562
|
// Skip node_modules and dist
|
|
599
563
|
if (filePath.includes('node_modules') || filePath.includes('/dist/'))
|
|
600
564
|
continue;
|
|
601
|
-
const callExpressions = sourceFile.getDescendantsOfKind(
|
|
565
|
+
const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression);
|
|
602
566
|
for (const callExpr of callExpressions) {
|
|
603
567
|
const dynamoOp = detectDynamoOperations(callExpr, filePath);
|
|
604
568
|
if (dynamoOp) {
|
|
@@ -631,6 +595,6 @@ async function scanRepository(repoPath) {
|
|
|
631
595
|
}
|
|
632
596
|
}
|
|
633
597
|
}
|
|
634
|
-
|
|
598
|
+
logger.debug(`Extracted ${operations.length} database operation(s)`);
|
|
635
599
|
return operations;
|
|
636
600
|
}
|
package/dist/core/cache.js
CHANGED
|
@@ -1,43 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
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
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.writeCache = writeCache;
|
|
37
|
-
exports.readCache = readCache;
|
|
38
|
-
exports.clearCache = clearCache;
|
|
39
|
-
const fs = __importStar(require("fs"));
|
|
40
|
-
const path = __importStar(require("path"));
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
41
3
|
const CACHE_VERSION = '1.0.0';
|
|
42
4
|
const CACHE_DIR = path.join(process.cwd(), '.infrawise', 'cache');
|
|
43
5
|
function ensureCacheDir() {
|
|
@@ -45,7 +7,7 @@ function ensureCacheDir() {
|
|
|
45
7
|
fs.mkdirSync(CACHE_DIR, { recursive: true });
|
|
46
8
|
}
|
|
47
9
|
}
|
|
48
|
-
function writeCache(key, data) {
|
|
10
|
+
export function writeCache(key, data) {
|
|
49
11
|
ensureCacheDir();
|
|
50
12
|
const entry = {
|
|
51
13
|
timestamp: Date.now(),
|
|
@@ -55,7 +17,7 @@ function writeCache(key, data) {
|
|
|
55
17
|
const filePath = path.join(CACHE_DIR, `${key}.json`);
|
|
56
18
|
fs.writeFileSync(filePath, JSON.stringify(entry, null, 2), 'utf-8');
|
|
57
19
|
}
|
|
58
|
-
function readCache(key, maxAgeMs = 3600000) {
|
|
20
|
+
export function readCache(key, maxAgeMs = 3600000) {
|
|
59
21
|
const filePath = path.join(CACHE_DIR, `${key}.json`);
|
|
60
22
|
if (!fs.existsSync(filePath))
|
|
61
23
|
return null;
|
|
@@ -72,7 +34,7 @@ function readCache(key, maxAgeMs = 3600000) {
|
|
|
72
34
|
return null;
|
|
73
35
|
}
|
|
74
36
|
}
|
|
75
|
-
function clearCache(key) {
|
|
37
|
+
export function clearCache(key) {
|
|
76
38
|
if (key) {
|
|
77
39
|
const filePath = path.join(CACHE_DIR, `${key}.json`);
|
|
78
40
|
if (fs.existsSync(filePath))
|
package/dist/core/config.js
CHANGED
|
@@ -1,89 +1,52 @@
|
|
|
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
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.ConfigError = exports.InfrawiseConfigSchema = void 0;
|
|
37
|
-
exports.loadConfig = loadConfig;
|
|
38
|
-
exports.generateDefaultConfig = generateDefaultConfig;
|
|
39
|
-
const zod_1 = require("zod");
|
|
40
|
-
const fs = __importStar(require("fs"));
|
|
41
|
-
const path = __importStar(require("path"));
|
|
42
|
-
const yaml = __importStar(require("js-yaml"));
|
|
43
|
-
exports.InfrawiseConfigSchema = zod_1.z.object({
|
|
44
|
-
project: zod_1.z.string().min(1, 'Project name is required'),
|
|
45
|
-
aws: zod_1.z
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import * as yaml from 'js-yaml';
|
|
5
|
+
export const InfrawiseConfigSchema = z.object({
|
|
6
|
+
project: z.string().min(1, 'Project name is required'),
|
|
7
|
+
aws: z
|
|
46
8
|
.object({
|
|
47
|
-
profile:
|
|
48
|
-
region:
|
|
49
|
-
endpoint:
|
|
9
|
+
profile: z.string().optional().default('default'),
|
|
10
|
+
region: z.string().optional().default('us-east-1'),
|
|
11
|
+
endpoint: z.string().optional(),
|
|
50
12
|
})
|
|
51
13
|
.optional()
|
|
52
|
-
.default({}),
|
|
53
|
-
dynamodb:
|
|
54
|
-
postgres:
|
|
55
|
-
enabled:
|
|
56
|
-
connectionString:
|
|
14
|
+
.default({ profile: 'default', region: 'us-east-1' }),
|
|
15
|
+
dynamodb: z.object({ enabled: z.boolean().optional().default(true), includeTables: z.array(z.string()).optional() }).optional(),
|
|
16
|
+
postgres: z.object({
|
|
17
|
+
enabled: z.boolean().optional().default(false),
|
|
18
|
+
connectionString: z.string().optional(),
|
|
57
19
|
}).optional(),
|
|
58
|
-
mysql:
|
|
59
|
-
enabled:
|
|
60
|
-
connectionString:
|
|
20
|
+
mysql: z.object({
|
|
21
|
+
enabled: z.boolean().optional().default(false),
|
|
22
|
+
connectionString: z.string().optional(),
|
|
61
23
|
}).optional(),
|
|
62
|
-
mongodb:
|
|
63
|
-
enabled:
|
|
64
|
-
connectionString:
|
|
65
|
-
databases:
|
|
24
|
+
mongodb: z.object({
|
|
25
|
+
enabled: z.boolean().optional().default(false),
|
|
26
|
+
connectionString: z.string().optional(),
|
|
27
|
+
databases: z.array(z.string()).optional(),
|
|
66
28
|
}).optional(),
|
|
67
|
-
terraform:
|
|
68
|
-
sqs:
|
|
69
|
-
sns:
|
|
70
|
-
ssm:
|
|
71
|
-
enabled:
|
|
72
|
-
paths:
|
|
29
|
+
terraform: z.object({ enabled: z.boolean().optional().default(true) }).optional(),
|
|
30
|
+
sqs: z.object({ enabled: z.boolean().optional().default(true) }).optional(),
|
|
31
|
+
sns: z.object({ enabled: z.boolean().optional().default(true) }).optional(),
|
|
32
|
+
ssm: z.object({
|
|
33
|
+
enabled: z.boolean().optional().default(true),
|
|
34
|
+
paths: z.array(z.string()).optional(),
|
|
73
35
|
}).optional(),
|
|
74
|
-
secretsManager:
|
|
75
|
-
lambda:
|
|
76
|
-
rds:
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
36
|
+
secretsManager: z.object({ enabled: z.boolean().optional().default(true) }).optional(),
|
|
37
|
+
lambda: z.object({ enabled: z.boolean().optional().default(true) }).optional(),
|
|
38
|
+
rds: z.object({ enabled: z.boolean().optional().default(false) }).optional(),
|
|
39
|
+
kafka: z.object({ enabled: z.boolean().optional().default(false) }).optional(),
|
|
40
|
+
cloudwatchLogs: z.object({
|
|
41
|
+
enabled: z.boolean().optional().default(false),
|
|
42
|
+
logGroupPrefixes: z.array(z.string()).optional(),
|
|
43
|
+
windowHours: z.number().int().positive().optional().default(24),
|
|
81
44
|
}).optional(),
|
|
82
|
-
analysis:
|
|
83
|
-
sampleSize:
|
|
45
|
+
analysis: z.object({
|
|
46
|
+
sampleSize: z.number().int().positive().optional().default(100),
|
|
84
47
|
}).optional(),
|
|
85
48
|
});
|
|
86
|
-
class ConfigError extends Error {
|
|
49
|
+
export class ConfigError extends Error {
|
|
87
50
|
details;
|
|
88
51
|
constructor(message, details) {
|
|
89
52
|
super(message);
|
|
@@ -91,8 +54,7 @@ class ConfigError extends Error {
|
|
|
91
54
|
this.name = 'ConfigError';
|
|
92
55
|
}
|
|
93
56
|
}
|
|
94
|
-
|
|
95
|
-
function loadConfig(configPath) {
|
|
57
|
+
export function loadConfig(configPath) {
|
|
96
58
|
const resolvedPath = configPath
|
|
97
59
|
? path.resolve(configPath)
|
|
98
60
|
: path.resolve(process.cwd(), 'infrawise.yaml');
|
|
@@ -121,14 +83,14 @@ function loadConfig(configPath) {
|
|
|
121
83
|
catch (err) {
|
|
122
84
|
throw new ConfigError(`Invalid YAML in configuration file: ${resolvedPath}`, [String(err)]);
|
|
123
85
|
}
|
|
124
|
-
const result =
|
|
86
|
+
const result = InfrawiseConfigSchema.safeParse(parsedYaml);
|
|
125
87
|
if (!result.success) {
|
|
126
|
-
const details = result.error.
|
|
88
|
+
const details = result.error.issues.map((e) => ` - ${e.path.join('.')}: ${e.message}`);
|
|
127
89
|
throw new ConfigError('Configuration validation failed', details);
|
|
128
90
|
}
|
|
129
91
|
return result.data;
|
|
130
92
|
}
|
|
131
|
-
function generateDefaultConfig(projectName, options) {
|
|
93
|
+
export function generateDefaultConfig(projectName, options) {
|
|
132
94
|
const config = {
|
|
133
95
|
project: projectName,
|
|
134
96
|
aws: {
|
package/dist/core/errors.js
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ConfigError = exports.RepositoryScanError = exports.PostgresConnectionError = exports.DynamoDBError = exports.AWSConnectionError = exports.InfrawiseError = void 0;
|
|
4
|
-
exports.formatError = formatError;
|
|
5
|
-
class InfrawiseError extends Error {
|
|
1
|
+
export class InfrawiseError extends Error {
|
|
6
2
|
reasons;
|
|
7
3
|
remediation;
|
|
8
4
|
constructor(message, reasons, remediation) {
|
|
@@ -26,8 +22,7 @@ class InfrawiseError extends Error {
|
|
|
26
22
|
return lines.join('\n');
|
|
27
23
|
}
|
|
28
24
|
}
|
|
29
|
-
|
|
30
|
-
class AWSConnectionError extends InfrawiseError {
|
|
25
|
+
export class AWSConnectionError extends InfrawiseError {
|
|
31
26
|
constructor(details) {
|
|
32
27
|
super('Unable to connect to AWS.', [
|
|
33
28
|
'Invalid or missing AWS credentials',
|
|
@@ -38,8 +33,7 @@ class AWSConnectionError extends InfrawiseError {
|
|
|
38
33
|
this.name = 'AWSConnectionError';
|
|
39
34
|
}
|
|
40
35
|
}
|
|
41
|
-
|
|
42
|
-
class DynamoDBError extends InfrawiseError {
|
|
36
|
+
export class DynamoDBError extends InfrawiseError {
|
|
43
37
|
constructor(details) {
|
|
44
38
|
super('Unable to access DynamoDB.', [
|
|
45
39
|
'Insufficient IAM permissions (need dynamodb:ListTables, dynamodb:DescribeTable)',
|
|
@@ -50,8 +44,7 @@ class DynamoDBError extends InfrawiseError {
|
|
|
50
44
|
this.name = 'DynamoDBError';
|
|
51
45
|
}
|
|
52
46
|
}
|
|
53
|
-
|
|
54
|
-
class PostgresConnectionError extends InfrawiseError {
|
|
47
|
+
export class PostgresConnectionError extends InfrawiseError {
|
|
55
48
|
constructor(details) {
|
|
56
49
|
super('Unable to connect to PostgreSQL.', [
|
|
57
50
|
'Invalid connection string',
|
|
@@ -62,8 +55,7 @@ class PostgresConnectionError extends InfrawiseError {
|
|
|
62
55
|
this.name = 'PostgresConnectionError';
|
|
63
56
|
}
|
|
64
57
|
}
|
|
65
|
-
|
|
66
|
-
class RepositoryScanError extends InfrawiseError {
|
|
58
|
+
export class RepositoryScanError extends InfrawiseError {
|
|
67
59
|
constructor(details) {
|
|
68
60
|
super('Unable to scan repository.', [
|
|
69
61
|
'Path does not exist or is not accessible',
|
|
@@ -74,8 +66,7 @@ class RepositoryScanError extends InfrawiseError {
|
|
|
74
66
|
this.name = 'RepositoryScanError';
|
|
75
67
|
}
|
|
76
68
|
}
|
|
77
|
-
|
|
78
|
-
class ConfigError extends InfrawiseError {
|
|
69
|
+
export class ConfigError extends InfrawiseError {
|
|
79
70
|
constructor(details) {
|
|
80
71
|
super('Invalid or missing configuration.', [
|
|
81
72
|
'infrawise.yaml not found in current directory',
|
|
@@ -85,8 +76,7 @@ class ConfigError extends InfrawiseError {
|
|
|
85
76
|
this.name = 'ConfigError';
|
|
86
77
|
}
|
|
87
78
|
}
|
|
88
|
-
|
|
89
|
-
function formatError(err) {
|
|
79
|
+
export function formatError(err) {
|
|
90
80
|
if (err instanceof InfrawiseError) {
|
|
91
81
|
return err.format();
|
|
92
82
|
}
|
package/dist/core/index.js
CHANGED
|
@@ -1,22 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return config_1.loadConfig; } });
|
|
6
|
-
Object.defineProperty(exports, "generateDefaultConfig", { enumerable: true, get: function () { return config_1.generateDefaultConfig; } });
|
|
7
|
-
Object.defineProperty(exports, "InfrawiseConfigSchema", { enumerable: true, get: function () { return config_1.InfrawiseConfigSchema; } });
|
|
8
|
-
Object.defineProperty(exports, "ConfigValidationError", { enumerable: true, get: function () { return config_1.ConfigError; } });
|
|
9
|
-
var logger_1 = require("./logger");
|
|
10
|
-
Object.defineProperty(exports, "logger", { enumerable: true, get: function () { return logger_1.logger; } });
|
|
11
|
-
var errors_1 = require("./errors");
|
|
12
|
-
Object.defineProperty(exports, "InfrawiseError", { enumerable: true, get: function () { return errors_1.InfrawiseError; } });
|
|
13
|
-
Object.defineProperty(exports, "AWSConnectionError", { enumerable: true, get: function () { return errors_1.AWSConnectionError; } });
|
|
14
|
-
Object.defineProperty(exports, "DynamoDBError", { enumerable: true, get: function () { return errors_1.DynamoDBError; } });
|
|
15
|
-
Object.defineProperty(exports, "PostgresConnectionError", { enumerable: true, get: function () { return errors_1.PostgresConnectionError; } });
|
|
16
|
-
Object.defineProperty(exports, "RepositoryScanError", { enumerable: true, get: function () { return errors_1.RepositoryScanError; } });
|
|
17
|
-
Object.defineProperty(exports, "ConfigError", { enumerable: true, get: function () { return errors_1.ConfigError; } });
|
|
18
|
-
Object.defineProperty(exports, "formatError", { enumerable: true, get: function () { return errors_1.formatError; } });
|
|
19
|
-
var cache_1 = require("./cache");
|
|
20
|
-
Object.defineProperty(exports, "writeCache", { enumerable: true, get: function () { return cache_1.writeCache; } });
|
|
21
|
-
Object.defineProperty(exports, "readCache", { enumerable: true, get: function () { return cache_1.readCache; } });
|
|
22
|
-
Object.defineProperty(exports, "clearCache", { enumerable: true, get: function () { return cache_1.clearCache; } });
|
|
1
|
+
export { loadConfig, generateDefaultConfig, InfrawiseConfigSchema, ConfigError as ConfigValidationError } from './config.js';
|
|
2
|
+
export { logger } from './logger.js';
|
|
3
|
+
export { InfrawiseError, AWSConnectionError, DynamoDBError, PostgresConnectionError, RepositoryScanError, ConfigError, formatError, } from './errors.js';
|
|
4
|
+
export { writeCache, readCache, clearCache } from './cache.js';
|