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/dist/cli/index.js CHANGED
@@ -1,17 +1,15 @@
1
1
  #!/usr/bin/env node
2
- "use strict";
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- const fs_1 = require("fs");
5
- const path_1 = require("path");
6
- const commander_1 = require("commander");
7
- const utils_1 = require("./utils");
8
- const init_1 = require("./commands/init");
9
- const auth_1 = require("./commands/auth");
10
- const analyze_1 = require("./commands/analyze");
11
- const dev_1 = require("./commands/dev");
12
- const doctor_1 = require("./commands/doctor");
13
- const { version } = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, '../../package.json'), 'utf8'));
14
- const program = new commander_1.Command();
2
+ import { readFileSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { Command } from 'commander';
5
+ import { printBanner } from './utils.js';
6
+ import { runInit } from './commands/init.js';
7
+ import { runAuth } from './commands/auth.js';
8
+ import { runAnalyze } from './commands/analyze.js';
9
+ import { runDev } from './commands/dev.js';
10
+ import { runDoctor } from './commands/doctor.js';
11
+ const { version } = JSON.parse(readFileSync(join(import.meta.dirname, '../../package.json'), 'utf8'));
12
+ const program = new Command();
15
13
  program
16
14
  .name('infrawise')
17
15
  .description('CLI-first infrastructure intelligence platform — analyze your databases, AWS services, and IaC')
@@ -21,15 +19,15 @@ program
21
19
  .description('Detect AWS profile/region, discover DynamoDB tables, and generate infrawise.yaml')
22
20
  .option('--force', 'Overwrite existing infrawise.yaml')
23
21
  .action(async (options) => {
24
- (0, utils_1.printBanner)();
25
- await (0, init_1.runInit)({ force: options.force });
22
+ printBanner();
23
+ await runInit({ force: options.force });
26
24
  });
27
25
  program
28
26
  .command('auth')
29
27
  .description('Validate and select AWS profile from ~/.aws/credentials')
30
28
  .action(async () => {
31
- (0, utils_1.printBanner)();
32
- await (0, auth_1.runAuth)();
29
+ printBanner();
30
+ await runAuth();
33
31
  });
34
32
  program
35
33
  .command('analyze')
@@ -38,8 +36,8 @@ program
38
36
  .option('-r, --repo <path>', 'Path to repository to scan', process.cwd())
39
37
  .option('--no-cache', 'Skip reading/writing the cache')
40
38
  .action(async (options) => {
41
- (0, utils_1.printBanner)();
42
- await (0, analyze_1.runAnalyze)({
39
+ printBanner();
40
+ await runAnalyze({
43
41
  config: options.config !== 'infrawise.yaml' ? options.config : undefined,
44
42
  repo: options.repo,
45
43
  noCache: !options.cache,
@@ -51,8 +49,8 @@ program
51
49
  .option('-c, --config <path>', 'Path to infrawise.yaml', 'infrawise.yaml')
52
50
  .option('-p, --port <number>', 'Port to listen on', '3000')
53
51
  .action(async (options) => {
54
- (0, utils_1.printBanner)();
55
- await (0, dev_1.runDev)({
52
+ printBanner();
53
+ await runDev({
56
54
  config: options.config !== 'infrawise.yaml' ? options.config : undefined,
57
55
  port: parseInt(options.port, 10),
58
56
  });
@@ -62,8 +60,8 @@ program
62
60
  .description('Validate AWS access, postgres connectivity, config, and repo scan')
63
61
  .option('-c, --config <path>', 'Path to infrawise.yaml', 'infrawise.yaml')
64
62
  .action(async (options) => {
65
- (0, utils_1.printBanner)();
66
- await (0, doctor_1.runDoctor)({
63
+ printBanner();
64
+ await runDoctor({
67
65
  config: options.config !== 'infrawise.yaml' ? options.config : undefined,
68
66
  });
69
67
  });
package/dist/cli/utils.js CHANGED
@@ -1,55 +1,9 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
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
- 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.log = void 0;
40
- exports.readAWSProfiles = readAWSProfiles;
41
- exports.detectAWSRegion = detectAWSRegion;
42
- exports.detectRepoType = detectRepoType;
43
- exports.printBanner = printBanner;
44
- exports.printHeader = printHeader;
45
- exports.printFinding = printFinding;
46
- exports.printSummaryBox = printSummaryBox;
47
- const fs = __importStar(require("fs"));
48
- const path = __importStar(require("path"));
49
- const os = __importStar(require("os"));
50
- const chalk_1 = __importDefault(require("chalk"));
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
4
+ import chalk from 'chalk';
51
5
  // ─── AWS helpers ─────────────────────────────────────────────────────────────
52
- function readAWSProfiles() {
6
+ export function readAWSProfiles() {
53
7
  const credentialsPath = path.join(os.homedir(), '.aws', 'credentials');
54
8
  const configPath = path.join(os.homedir(), '.aws', 'config');
55
9
  const profiles = new Set();
@@ -70,7 +24,7 @@ function readAWSProfiles() {
70
24
  parseFile(configPath);
71
25
  return profiles.size > 0 ? [...profiles] : ['default'];
72
26
  }
73
- function detectAWSRegion() {
27
+ export function detectAWSRegion() {
74
28
  if (process.env.AWS_DEFAULT_REGION)
75
29
  return process.env.AWS_DEFAULT_REGION;
76
30
  if (process.env.AWS_REGION)
@@ -83,7 +37,7 @@ function detectAWSRegion() {
83
37
  }
84
38
  return 'us-east-1';
85
39
  }
86
- function detectRepoType(repoPath) {
40
+ export function detectRepoType(repoPath) {
87
41
  if (fs.existsSync(path.join(repoPath, 'tsconfig.json')))
88
42
  return 'typescript';
89
43
  if (fs.existsSync(path.join(repoPath, 'package.json')))
@@ -93,73 +47,73 @@ function detectRepoType(repoPath) {
93
47
  // ─── Banner ──────────────────────────────────────────────────────────────────
94
48
  function readVersion() {
95
49
  try {
96
- const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '../../package.json'), 'utf-8'));
50
+ const pkg = JSON.parse(fs.readFileSync(path.join(import.meta.dirname, '../../package.json'), 'utf-8'));
97
51
  return pkg.version;
98
52
  }
99
53
  catch {
100
54
  return 'unknown';
101
55
  }
102
56
  }
103
- function printBanner() {
104
- const line1 = chalk_1.default.bold.hex('#6366f1')(' infrawise');
105
- const version = chalk_1.default.dim(` v${readVersion()}`);
106
- const tagline = chalk_1.default.dim(' Infrastructure Intelligence Platform\n');
57
+ export function printBanner() {
58
+ const line1 = chalk.bold.hex('#6366f1')(' infrawise');
59
+ const version = chalk.dim(` v${readVersion()}`);
60
+ const tagline = chalk.dim(' Infrastructure Intelligence Platform\n');
107
61
  console.log(`\n${line1}${version}`);
108
62
  console.log(tagline);
109
63
  }
110
64
  // ─── Section header ──────────────────────────────────────────────────────────
111
- function printHeader(title) {
112
- console.log(chalk_1.default.bold(`\n${title}`));
113
- console.log(chalk_1.default.dim('─'.repeat(title.length + 2)));
65
+ export function printHeader(title) {
66
+ console.log(chalk.bold(`\n${title}`));
67
+ console.log(chalk.dim('─'.repeat(title.length + 2)));
114
68
  }
115
69
  // ─── Status lines ────────────────────────────────────────────────────────────
116
- exports.log = {
70
+ export const log = {
117
71
  success: (msg, detail) => {
118
- console.log(` ${chalk_1.default.green('✓')} ${msg}${detail ? chalk_1.default.dim(` ${detail}`) : ''}`);
72
+ console.log(` ${chalk.green('✓')} ${msg}${detail ? chalk.dim(` ${detail}`) : ''}`);
119
73
  },
120
74
  fail: (msg, detail) => {
121
- console.log(` ${chalk_1.default.red('✗')} ${chalk_1.default.red(msg)}${detail ? chalk_1.default.dim(`\n ${detail}`) : ''}`);
75
+ console.log(` ${chalk.red('✗')} ${chalk.red(msg)}${detail ? chalk.dim(`\n ${detail}`) : ''}`);
122
76
  },
123
77
  warn: (msg, detail) => {
124
- console.log(` ${chalk_1.default.yellow('⚠')} ${chalk_1.default.yellow(msg)}${detail ? chalk_1.default.dim(`\n ${detail}`) : ''}`);
78
+ console.log(` ${chalk.yellow('⚠')} ${chalk.yellow(msg)}${detail ? chalk.dim(`\n ${detail}`) : ''}`);
125
79
  },
126
80
  skip: (msg, detail) => {
127
- console.log(` ${chalk_1.default.dim('−')} ${chalk_1.default.dim(msg)}${detail ? chalk_1.default.dim(` ${detail}`) : ''}`);
81
+ console.log(` ${chalk.dim('−')} ${chalk.dim(msg)}${detail ? chalk.dim(` ${detail}`) : ''}`);
128
82
  },
129
83
  info: (msg) => {
130
- console.log(` ${chalk_1.default.cyan('›')} ${msg}`);
84
+ console.log(` ${chalk.cyan('›')} ${msg}`);
131
85
  },
132
86
  dim: (msg) => {
133
- console.log(chalk_1.default.dim(` ${msg}`));
87
+ console.log(chalk.dim(` ${msg}`));
134
88
  },
135
89
  };
136
90
  // ─── Findings ────────────────────────────────────────────────────────────────
137
91
  function severityBadge(severity) {
138
92
  switch (severity) {
139
- case 'high': return chalk_1.default.bgRed.white.bold(` HIGH `);
140
- case 'medium': return chalk_1.default.bgYellow.black.bold(` MED `);
141
- case 'low': return chalk_1.default.bgCyan.black.bold(` LOW `);
93
+ case 'high': return chalk.bgRed.white.bold(` HIGH `);
94
+ case 'medium': return chalk.bgYellow.black.bold(` MED `);
95
+ case 'low': return chalk.bgCyan.black.bold(` LOW `);
142
96
  }
143
97
  }
144
- function printFinding(finding, index) {
98
+ export function printFinding(finding, index) {
145
99
  const badge = severityBadge(finding.severity);
146
- const num = chalk_1.default.dim(`${index + 1}.`);
147
- console.log(`\n ${num} ${badge} ${chalk_1.default.bold(finding.issue)}`);
148
- console.log(chalk_1.default.dim(` ${finding.description}`));
149
- console.log(` ${chalk_1.default.green('→')} ${finding.recommendation}`);
100
+ const num = chalk.dim(`${index + 1}.`);
101
+ console.log(`\n ${num} ${badge} ${chalk.bold(finding.issue)}`);
102
+ console.log(chalk.dim(` ${finding.description}`));
103
+ console.log(` ${chalk.green('→')} ${finding.recommendation}`);
150
104
  }
151
- function printSummaryBox(findings) {
105
+ export function printSummaryBox(findings) {
152
106
  const high = findings.filter((f) => f.severity === 'high').length;
153
107
  const medium = findings.filter((f) => f.severity === 'medium').length;
154
108
  const low = findings.filter((f) => f.severity === 'low').length;
155
109
  console.log('');
156
- console.log(chalk_1.default.dim(' ┌─────────────────────────────┐'));
157
- console.log(chalk_1.default.dim(' │') + chalk_1.default.bold(' Analysis Summary ') + chalk_1.default.dim('│'));
158
- console.log(chalk_1.default.dim(' ├─────────────────────────────┤'));
159
- console.log(chalk_1.default.dim(' │') + ` ${chalk_1.default.red('●')} High ${chalk_1.default.red.bold(String(high).padStart(3))} ` + chalk_1.default.dim('│'));
160
- console.log(chalk_1.default.dim(' │') + ` ${chalk_1.default.yellow('●')} Medium ${chalk_1.default.yellow.bold(String(medium).padStart(3))} ` + chalk_1.default.dim('│'));
161
- console.log(chalk_1.default.dim(' │') + ` ${chalk_1.default.cyan('●')} Low ${chalk_1.default.cyan.bold(String(low).padStart(3))} ` + chalk_1.default.dim('│'));
162
- console.log(chalk_1.default.dim(' ├─────────────────────────────┤'));
163
- console.log(chalk_1.default.dim(' │') + ` Total ${chalk_1.default.bold(String(findings.length).padStart(3))} ` + chalk_1.default.dim('│'));
164
- console.log(chalk_1.default.dim(' └─────────────────────────────┘'));
110
+ console.log(chalk.dim(' ┌─────────────────────────────┐'));
111
+ console.log(chalk.dim(' │') + chalk.bold(' Analysis Summary ') + chalk.dim('│'));
112
+ console.log(chalk.dim(' ├─────────────────────────────┤'));
113
+ console.log(chalk.dim(' │') + ` ${chalk.red('●')} High ${chalk.red.bold(String(high).padStart(3))} ` + chalk.dim('│'));
114
+ console.log(chalk.dim(' │') + ` ${chalk.yellow('●')} Medium ${chalk.yellow.bold(String(medium).padStart(3))} ` + chalk.dim('│'));
115
+ console.log(chalk.dim(' │') + ` ${chalk.cyan('●')} Low ${chalk.cyan.bold(String(low).padStart(3))} ` + chalk.dim('│'));
116
+ console.log(chalk.dim(' ├─────────────────────────────┤'));
117
+ console.log(chalk.dim(' │') + ` Total ${chalk.bold(String(findings.length).padStart(3))} ` + chalk.dim('│'));
118
+ console.log(chalk.dim(' └─────────────────────────────┘'));
165
119
  }
@@ -1,43 +1,7 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
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.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 (ts_morph_1.Node.isFunctionDeclaration(current) ||
113
- ts_morph_1.Node.isFunctionExpression(current) ||
114
- ts_morph_1.Node.isArrowFunction(current) ||
115
- ts_morph_1.Node.isMethodDeclaration(current)) {
116
- if (ts_morph_1.Node.isFunctionDeclaration(current) || ts_morph_1.Node.isMethodDeclaration(current)) {
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 && ts_morph_1.Node.isVariableDeclaration(parent)) {
85
+ if (parent && Node.isVariableDeclaration(parent)) {
122
86
  return parent.getName();
123
87
  }
124
- if (parent && ts_morph_1.Node.isPropertyAssignment(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 (ts_morph_1.Node.isStringLiteral(arg)) {
98
+ if (Node.isStringLiteral(arg)) {
135
99
  return arg.getLiteralValue();
136
100
  }
137
- if (ts_morph_1.Node.isObjectLiteralExpression(arg)) {
101
+ if (Node.isObjectLiteralExpression(arg)) {
138
102
  // Look for TableName property
139
103
  for (const prop of arg.getProperties()) {
140
- if (ts_morph_1.Node.isPropertyAssignment(prop) && prop.getName() === 'TableName') {
104
+ if (Node.isPropertyAssignment(prop) && prop.getName() === 'TableName') {
141
105
  const init = prop.getInitializer();
142
- if (init && ts_morph_1.Node.isStringLiteral(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 (ts_morph_1.Node.isPropertyAccessExpression(expr)) {
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 (ts_morph_1.Node.isNewExpression(firstArg)) {
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 (!ts_morph_1.Node.isPropertyAccessExpression(expr))
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 (ts_morph_1.Node.isStringLiteral(firstArg)) {
187
+ if (Node.isStringLiteral(firstArg)) {
224
188
  tableName = extractSqlTableName(firstArg.getLiteralValue());
225
189
  }
226
- else if (ts_morph_1.Node.isNoSubstitutionTemplateLiteral(firstArg)) {
190
+ else if (Node.isNoSubstitutionTemplateLiteral(firstArg)) {
227
191
  tableName = extractSqlTableName(firstArg.getLiteralText());
228
192
  }
229
- else if (ts_morph_1.Node.isTemplateExpression(firstArg)) {
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 (ts_morph_1.Node.isPropertyAccessExpression(accessChain)) {
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 (ts_morph_1.Node.isCallExpression(objExpr)) {
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 && ts_morph_1.Node.isStringLiteral(innerArgs[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 (!ts_morph_1.Node.isPropertyAccessExpression(expr))
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 (ts_morph_1.Node.isStringLiteral(firstArg)) {
274
+ if (Node.isStringLiteral(firstArg)) {
311
275
  tableName = extractSqlTableName(firstArg.getLiteralValue());
312
276
  }
313
- else if (ts_morph_1.Node.isNoSubstitutionTemplateLiteral(firstArg)) {
277
+ else if (Node.isNoSubstitutionTemplateLiteral(firstArg)) {
314
278
  tableName = extractSqlTableName(firstArg.getLiteralText());
315
279
  }
316
- else if (ts_morph_1.Node.isTemplateExpression(firstArg)) {
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 (ts_morph_1.Node.isCallExpression(objExpr)) {
297
+ if (Node.isCallExpression(objExpr)) {
334
298
  const innerArgs = objExpr.getArguments();
335
- if (innerArgs.length > 0 && ts_morph_1.Node.isStringLiteral(innerArgs[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 (!ts_morph_1.Node.isPropertyAccessExpression(expr))
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 (ts_morph_1.Node.isCallExpression(objExpr)) {
332
+ if (Node.isCallExpression(objExpr)) {
369
333
  const innerExpr = objExpr.getExpression();
370
- if (ts_morph_1.Node.isPropertyAccessExpression(innerExpr) &&
334
+ if (Node.isPropertyAccessExpression(innerExpr) &&
371
335
  MONGO_COLLECTION_METHODS.has(innerExpr.getName())) {
372
336
  const innerArgs = objExpr.getArguments();
373
- if (innerArgs.length > 0 && ts_morph_1.Node.isStringLiteral(innerArgs[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 (ts_morph_1.Node.isPropertyAccessExpression(objExpr)) {
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 && ts_morph_1.Node.isStringLiteral(args[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 (ts_morph_1.Node.isObjectLiteralExpression(arg)) {
380
+ if (Node.isObjectLiteralExpression(arg)) {
417
381
  for (const prop of arg.getProperties()) {
418
- if (ts_morph_1.Node.isPropertyAssignment(prop) && keys.includes(prop.getName())) {
382
+ if (Node.isPropertyAssignment(prop) && keys.includes(prop.getName())) {
419
383
  const init = prop.getInitializer();
420
- if (init && ts_morph_1.Node.isStringLiteral(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 (!ts_morph_1.Node.isPropertyAccessExpression(expr))
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 (ts_morph_1.Node.isPropertyAccessExpression(expr) && expr.getName() === 'send' && args.length > 0) {
427
+ if (Node.isPropertyAccessExpression(expr) && expr.getName() === 'send' && args.length > 0) {
464
428
  const firstArg = args[0];
465
- if (ts_morph_1.Node.isNewExpression(firstArg)) {
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 (ts_morph_1.Node.isPropertyAccessExpression(expr)) {
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 core_1.RepositoryScanError(`Path does not exist: ${resolvedPath}`);
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 ts_morph_1.Project({
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
- core_1.logger.debug(`Scanning ${sourceFiles.length} TypeScript file(s) in ${resolvedPath}`);
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(ts_morph_1.SyntaxKind.CallExpression);
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
- core_1.logger.debug(`Extracted ${operations.length} database operation(s)`);
598
+ logger.debug(`Extracted ${operations.length} database operation(s)`);
635
599
  return operations;
636
600
  }