aegis-ast 1.0.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.
Files changed (78) hide show
  1. package/README.md +138 -0
  2. package/dist/core/comparator.d.ts +32 -0
  3. package/dist/core/comparator.d.ts.map +1 -0
  4. package/dist/core/comparator.js +57 -0
  5. package/dist/core/comparator.js.map +1 -0
  6. package/dist/core/fetcher.d.ts +37 -0
  7. package/dist/core/fetcher.d.ts.map +1 -0
  8. package/dist/core/fetcher.js +144 -0
  9. package/dist/core/fetcher.js.map +1 -0
  10. package/dist/core/imports.d.ts +27 -0
  11. package/dist/core/imports.d.ts.map +1 -0
  12. package/dist/core/imports.js +200 -0
  13. package/dist/core/imports.js.map +1 -0
  14. package/dist/core/index.d.ts +23 -0
  15. package/dist/core/index.d.ts.map +1 -0
  16. package/dist/core/index.js +54 -0
  17. package/dist/core/index.js.map +1 -0
  18. package/dist/core/policy.d.ts +40 -0
  19. package/dist/core/policy.d.ts.map +1 -0
  20. package/dist/core/policy.js +166 -0
  21. package/dist/core/policy.js.map +1 -0
  22. package/dist/core/risk_engine.d.ts +164 -0
  23. package/dist/core/risk_engine.d.ts.map +1 -0
  24. package/dist/core/risk_engine.js +234 -0
  25. package/dist/core/risk_engine.js.map +1 -0
  26. package/dist/main.d.ts +3 -0
  27. package/dist/main.d.ts.map +1 -0
  28. package/dist/main.js +524 -0
  29. package/dist/main.js.map +1 -0
  30. package/dist/scanner/entropy.d.ts +26 -0
  31. package/dist/scanner/entropy.d.ts.map +1 -0
  32. package/dist/scanner/entropy.js +172 -0
  33. package/dist/scanner/entropy.js.map +1 -0
  34. package/dist/scanner/eval.d.ts +21 -0
  35. package/dist/scanner/eval.d.ts.map +1 -0
  36. package/dist/scanner/eval.js +151 -0
  37. package/dist/scanner/eval.js.map +1 -0
  38. package/dist/scanner/exec.d.ts +20 -0
  39. package/dist/scanner/exec.d.ts.map +1 -0
  40. package/dist/scanner/exec.js +166 -0
  41. package/dist/scanner/exec.js.map +1 -0
  42. package/dist/scanner/fs_access.d.ts +20 -0
  43. package/dist/scanner/fs_access.d.ts.map +1 -0
  44. package/dist/scanner/fs_access.js +164 -0
  45. package/dist/scanner/fs_access.js.map +1 -0
  46. package/dist/scanner/gemini.d.ts +45 -0
  47. package/dist/scanner/gemini.d.ts.map +1 -0
  48. package/dist/scanner/gemini.js +323 -0
  49. package/dist/scanner/gemini.js.map +1 -0
  50. package/dist/scanner/index.d.ts +15 -0
  51. package/dist/scanner/index.d.ts.map +1 -0
  52. package/dist/scanner/index.js +24 -0
  53. package/dist/scanner/index.js.map +1 -0
  54. package/dist/scanner/network.d.ts +20 -0
  55. package/dist/scanner/network.d.ts.map +1 -0
  56. package/dist/scanner/network.js +163 -0
  57. package/dist/scanner/network.js.map +1 -0
  58. package/dist/scanner/scripts.d.ts +20 -0
  59. package/dist/scanner/scripts.d.ts.map +1 -0
  60. package/dist/scanner/scripts.js +157 -0
  61. package/dist/scanner/scripts.js.map +1 -0
  62. package/dist/types/index.d.ts +149 -0
  63. package/dist/types/index.d.ts.map +1 -0
  64. package/dist/types/index.js +10 -0
  65. package/dist/types/index.js.map +1 -0
  66. package/dist/utils/file_walker.d.ts +71 -0
  67. package/dist/utils/file_walker.d.ts.map +1 -0
  68. package/dist/utils/file_walker.js +194 -0
  69. package/dist/utils/file_walker.js.map +1 -0
  70. package/dist/utils/index.d.ts +9 -0
  71. package/dist/utils/index.d.ts.map +1 -0
  72. package/dist/utils/index.js +19 -0
  73. package/dist/utils/index.js.map +1 -0
  74. package/dist/utils/logger.d.ts +57 -0
  75. package/dist/utils/logger.d.ts.map +1 -0
  76. package/dist/utils/logger.js +176 -0
  77. package/dist/utils/logger.js.map +1 -0
  78. package/package.json +52 -0
package/README.md ADDED
@@ -0,0 +1,138 @@
1
+ # 🛡️ Aegis
2
+
3
+ ### Secure Package Installation via Static Code Verification
4
+
5
+ ---
6
+
7
+ ## One-Line Pitch
8
+
9
+ > **Aegis-AST verifies code truth before execution, stopping supply-chain attacks at install time.**
10
+
11
+ ---
12
+
13
+ ## 🚀 Quick Start
14
+
15
+ ```bash
16
+ # 1. Install dependencies
17
+ npm install
18
+
19
+ # 2. Build
20
+ npm run build
21
+
22
+ # 3. Run in development mode
23
+ npm run dev
24
+
25
+ # 4. Or run the CLI directly
26
+ npx ts-node src/main.ts install axios
27
+ ```
28
+
29
+ ---
30
+
31
+ ## 📁 Project Structure
32
+
33
+ ```
34
+ aegis/
35
+ ├── src/
36
+ │ ├── main.ts # CLI entry point (Person 4)
37
+ │ ├── types/
38
+ │ │ └── index.ts # 🔒 Shared type contracts (DO NOT modify alone)
39
+ │ ├── core/
40
+ │ │ ├── index.ts # Barrel export
41
+ │ │ ├── fetcher.ts # Package fetcher (Person 1)
42
+ │ │ ├── imports.ts # Import extractor (Person 1)
43
+ │ │ ├── comparator.ts # Dependency comparator (Person 1)
44
+ │ │ ├── risk_engine.ts # Risk scoring (Person 3)
45
+ │ │ └── policy.ts # Decision engine (Person 3)
46
+ │ ├── scanner/
47
+ │ │ ├── index.ts # Barrel export
48
+ │ │ ├── scripts.ts # Script scanner (Person 2)
49
+ │ │ ├── network.ts # Network detection (Person 2)
50
+ │ │ ├── entropy.ts # Entropy detection (Person 2)
51
+ │ │ ├── fs_access.ts # FS access detection (Person 2)
52
+ │ │ ├── exec.ts # Exec detection (Person 2)
53
+ │ │ └── eval.ts # Eval detection (Person 2)
54
+ │ └── utils/
55
+ │ ├── index.ts # Barrel export
56
+ │ ├── logger.ts # MongoDB logger (Person 3)
57
+ │ └── file_walker.ts # 🔧 Shared file walker (IMPLEMENTED)
58
+ ├── tests/
59
+ │ └── comparator.test.ts # Example test
60
+ ├── package.json
61
+ ├── tsconfig.json
62
+ ├── jest.config.js
63
+ ├── .env.example
64
+ ├── .gitignore
65
+ └── README.md
66
+ ```
67
+
68
+ ---
69
+
70
+ ## 👥 Team Ownership
71
+
72
+ | Person | Role | Files |
73
+ |--------|------|-------|
74
+ | **P1** | Core Engine | `fetcher.ts`, `imports.ts`, `comparator.ts` |
75
+ | **P2** | Security Detection | `scripts.ts`, `network.ts`, `entropy.ts`, `fs_access.ts`, `exec.ts`, `eval.ts` |
76
+ | **P3** | Risk Engine + Backend | `risk_engine.ts`, `policy.ts`, `logger.ts` |
77
+ | **P4** | CLI + Demo + UX | `main.ts`, demo setup, dashboard |
78
+
79
+ ---
80
+
81
+ ## 🔗 Integration Contract
82
+
83
+ ### Input to Risk Engine (all signals merged)
84
+
85
+ ```json
86
+ {
87
+ "phantom": [],
88
+ "scripts": [],
89
+ "network": [],
90
+ "entropy": [],
91
+ "fs": [],
92
+ "exec": [],
93
+ "eval": []
94
+ }
95
+ ```
96
+
97
+ ### Output from Policy Engine
98
+
99
+ ```json
100
+ {
101
+ "score": 85,
102
+ "decision": "BLOCK",
103
+ "reasons": ["Phantom dependencies detected: evil-pkg"]
104
+ }
105
+ ```
106
+
107
+ ---
108
+
109
+ ## ⚙️ Environment Variables
110
+
111
+ Copy `.env.example` to `.env` and configure:
112
+
113
+ ```bash
114
+ cp .env.example .env
115
+ ```
116
+
117
+ | Variable | Description |
118
+ |----------|-------------|
119
+ | `MONGODB_URI` | MongoDB Atlas connection string |
120
+ | `GEMINI_API_KEY` | (Optional) Gemini API key |
121
+ | `NPM_REGISTRY_URL` | npm registry URL (default: registry.npmjs.org) |
122
+
123
+ ---
124
+
125
+ ## 🧪 Testing
126
+
127
+ ```bash
128
+ npm test
129
+ ```
130
+
131
+ ---
132
+
133
+ ## 🎤 Demo Flow
134
+
135
+ 1. `npm install axios` → compromised package gets through
136
+ 2. `aegis install axios` → **BLOCKED** by Aegis
137
+ 3. Show scan reasons and risk breakdown
138
+ 4. (Optional) View dashboard
@@ -0,0 +1,32 @@
1
+ /**
2
+ * ═══════════════════════════════════════════════════════════
3
+ * AEGIS-AST — Dependency Comparator
4
+ * Owner: Person 1 (Core Engine)
5
+ *
6
+ * Responsibilities:
7
+ * - Compare declared dependencies (package.json) vs used (imports)
8
+ * - Identify PHANTOM dependencies (declared but NOT used)
9
+ * - Identify MISSING dependencies (used but NOT declared)
10
+ *
11
+ * ⚠️ PHANTOM DEPENDENCIES = MALICIOUS SIGNAL
12
+ * Declared ≠ Used → suspicious
13
+ * ═══════════════════════════════════════════════════════════
14
+ */
15
+ import { ComparatorResult, PackageMetadata, ImportScanResult } from '../types';
16
+ /**
17
+ * Compares declared dependencies against actually used imports.
18
+ *
19
+ * @param metadata - Parsed package.json with declared dependencies
20
+ * @param imports - Extracted imports from source code
21
+ * @returns ComparatorResult with phantom, used, and missing deps
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * const result = compareDependencies(metadata, imports);
26
+ * if (result.phantom.length > 0) {
27
+ * console.warn('🚨 PHANTOM DEPENDENCIES DETECTED:', result.phantom);
28
+ * }
29
+ * ```
30
+ */
31
+ export declare function compareDependencies(metadata: PackageMetadata, imports: ImportScanResult): ComparatorResult;
32
+ //# sourceMappingURL=comparator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comparator.d.ts","sourceRoot":"","sources":["../../src/core/comparator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE/E;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,gBAAgB,GACxB,gBAAgB,CA6BlB"}
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ /**
3
+ * ═══════════════════════════════════════════════════════════
4
+ * AEGIS-AST — Dependency Comparator
5
+ * Owner: Person 1 (Core Engine)
6
+ *
7
+ * Responsibilities:
8
+ * - Compare declared dependencies (package.json) vs used (imports)
9
+ * - Identify PHANTOM dependencies (declared but NOT used)
10
+ * - Identify MISSING dependencies (used but NOT declared)
11
+ *
12
+ * ⚠️ PHANTOM DEPENDENCIES = MALICIOUS SIGNAL
13
+ * Declared ≠ Used → suspicious
14
+ * ═══════════════════════════════════════════════════════════
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.compareDependencies = compareDependencies;
18
+ /**
19
+ * Compares declared dependencies against actually used imports.
20
+ *
21
+ * @param metadata - Parsed package.json with declared dependencies
22
+ * @param imports - Extracted imports from source code
23
+ * @returns ComparatorResult with phantom, used, and missing deps
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * const result = compareDependencies(metadata, imports);
28
+ * if (result.phantom.length > 0) {
29
+ * console.warn('🚨 PHANTOM DEPENDENCIES DETECTED:', result.phantom);
30
+ * }
31
+ * ```
32
+ */
33
+ function compareDependencies(metadata, imports) {
34
+ // 1. Get all declared deps from metadata.dependencies
35
+ const declaredDeps = Object.keys(metadata.dependencies || {});
36
+ // 2. Get all used deps from imports.usedDependencies
37
+ const usedDeps = imports.usedDependencies || [];
38
+ // 3. Collect optional & peer deps — these are NOT phantoms.
39
+ // They are dynamically loaded at runtime by design (e.g. vite uses picomatch, postcss).
40
+ const optionalDeps = new Set([
41
+ ...Object.keys(metadata.optionalDependencies || {}),
42
+ ...Object.keys(metadata.peerDependencies || {}),
43
+ ]);
44
+ // Convert arrays to Sets for O(1) lookup efficiency
45
+ const declaredSet = new Set(declaredDeps);
46
+ const usedSet = new Set(usedDeps);
47
+ // 4. phantom = declared - used - optional/peer - @types/* (TS type packages, never require()'d)
48
+ const phantom = declaredDeps.filter(dep => !usedSet.has(dep) &&
49
+ !optionalDeps.has(dep) &&
50
+ !dep.startsWith('@types/'));
51
+ // 5. missing = used - declared
52
+ const missing = usedDeps.filter(dep => !declaredSet.has(dep));
53
+ // 6. usedDependencies = declared ∩ used
54
+ const usedDependencies = declaredDeps.filter(dep => usedSet.has(dep));
55
+ return { usedDependencies, phantom, missing };
56
+ }
57
+ //# sourceMappingURL=comparator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comparator.js","sourceRoot":"","sources":["../../src/core/comparator.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;AAmBH,kDAgCC;AA/CD;;;;;;;;;;;;;;GAcG;AACH,SAAgB,mBAAmB,CACjC,QAAyB,EACzB,OAAyB;IAEzB,sDAAsD;IACtD,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;IAC9D,qDAAqD;IACrD,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,IAAI,EAAE,CAAC;IAEhD,4DAA4D;IAC5D,2FAA2F;IAC3F,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;QAC3B,GAAG,MAAM,CAAC,IAAI,CAAE,QAAgB,CAAC,oBAAoB,IAAI,EAAE,CAAC;QAC5D,GAAG,MAAM,CAAC,IAAI,CAAE,QAAgB,CAAC,gBAAgB,IAAI,EAAE,CAAC;KACzD,CAAC,CAAC;IAEH,oDAAoD;IACpD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IAElC,gGAAgG;IAChG,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACxC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;QACjB,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC;QACtB,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,CAC3B,CAAC;IACF,+BAA+B;IAC/B,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9D,wCAAwC;IACxC,MAAM,gBAAgB,GAAG,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAEtE,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAChD,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * ═══════════════════════════════════════════════════════════
3
+ * AEGIS-AST — Package Fetcher
4
+ * Owner: Person 1 (Core Engine)
5
+ *
6
+ * Responsibilities:
7
+ * - Download package tarball from npm registry
8
+ * - Extract to /tmp/aegis/<package-name>
9
+ * - Parse and return package.json metadata
10
+ * ═══════════════════════════════════════════════════════════
11
+ */
12
+ import { FetchResult, PackageMetadata } from '../types';
13
+ /**
14
+ * Fetches a package from the npm registry, downloads the tarball,
15
+ * and extracts it to a temporary directory.
16
+ *
17
+ * @param packageName - Name of the npm package (e.g., "axios")
18
+ * @param version - Specific version or "latest"
19
+ * @returns FetchResult with extractedPath and metadata
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * const result = await fetchPackage("axios", "latest");
24
+ * console.log(result.extractedPath); // /tmp/aegis/axios
25
+ * console.log(result.metadata.dependencies);
26
+ * ```
27
+ */
28
+ export declare function fetchPackage(packageName: string, version?: string): Promise<FetchResult>;
29
+ /**
30
+ * Parses package.json from an extracted package directory.
31
+ */
32
+ export declare function parsePackageJson(extractedPath: string): PackageMetadata;
33
+ /**
34
+ * Cleans up the temporary extraction directory.
35
+ */
36
+ export declare function cleanup(extractedPath: string): Promise<void>;
37
+ //# sourceMappingURL=fetcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetcher.d.ts","sourceRoot":"","sources":["../../src/core/fetcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAUxD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,MAAiB,GACzB,OAAO,CAAC,WAAW,CAAC,CAoDtB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,eAAe,CAcvE;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMlE"}
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ /**
3
+ * ═══════════════════════════════════════════════════════════
4
+ * AEGIS-AST — Package Fetcher
5
+ * Owner: Person 1 (Core Engine)
6
+ *
7
+ * Responsibilities:
8
+ * - Download package tarball from npm registry
9
+ * - Extract to /tmp/aegis/<package-name>
10
+ * - Parse and return package.json metadata
11
+ * ═══════════════════════════════════════════════════════════
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.fetchPackage = fetchPackage;
48
+ exports.parsePackageJson = parsePackageJson;
49
+ exports.cleanup = cleanup;
50
+ const fs = __importStar(require("fs"));
51
+ const fsp = __importStar(require("fs/promises"));
52
+ const path = __importStar(require("path"));
53
+ const os = __importStar(require("os"));
54
+ const child_process_1 = require("child_process");
55
+ const util_1 = require("util");
56
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
57
+ /**
58
+ * Fetches a package from the npm registry, downloads the tarball,
59
+ * and extracts it to a temporary directory.
60
+ *
61
+ * @param packageName - Name of the npm package (e.g., "axios")
62
+ * @param version - Specific version or "latest"
63
+ * @returns FetchResult with extractedPath and metadata
64
+ *
65
+ * @example
66
+ * ```ts
67
+ * const result = await fetchPackage("axios", "latest");
68
+ * console.log(result.extractedPath); // /tmp/aegis/axios
69
+ * console.log(result.metadata.dependencies);
70
+ * ```
71
+ */
72
+ async function fetchPackage(packageName, version = 'latest') {
73
+ const registryUrl = process.env.NPM_REGISTRY_URL || 'https://registry.npmjs.org';
74
+ const packageUrl = `${registryUrl}/${packageName}/${version}`;
75
+ try {
76
+ // 1. GET package metadata from registry
77
+ const res = await fetch(packageUrl);
78
+ if (!res.ok) {
79
+ throw new Error(`Failed to fetch metadata for ${packageName}@${version}: ${res.statusText}`);
80
+ }
81
+ const data = (await res.json());
82
+ // 2. Extract tarball URL
83
+ const tarballUrl = data.dist?.tarball;
84
+ if (!tarballUrl) {
85
+ throw new Error(`No tarball URL found for ${packageName}@${version}`);
86
+ }
87
+ // Prepare temp directories
88
+ const tmpBase = path.join(os.tmpdir(), 'aegis');
89
+ const extractPath = path.join(tmpBase, packageName);
90
+ const tarballPath = path.join(tmpBase, `${packageName.replace(/\//g, '-')}.tgz`);
91
+ await fsp.mkdir(extractPath, { recursive: true });
92
+ // 3. Download tarball
93
+ const tarRes = await fetch(tarballUrl);
94
+ if (!tarRes.ok) {
95
+ throw new Error(`Failed to download tarball: ${tarRes.statusText}`);
96
+ }
97
+ const arrayBuffer = await tarRes.arrayBuffer();
98
+ await fsp.writeFile(tarballPath, Buffer.from(arrayBuffer));
99
+ // 4. Extract tarball
100
+ // Note: NPM tarballs always wrap their contents in a 'package/' directory.
101
+ // We use --strip-components=1 to dump the files directly into our target folder.
102
+ await execAsync(`tar -xzf ${tarballPath} -C ${extractPath} --strip-components=1`);
103
+ // Clean up the raw .tgz file now that we've extracted it
104
+ await fsp.rm(tarballPath, { force: true });
105
+ // 5. Parse package.json
106
+ const metadata = parsePackageJson(extractPath);
107
+ // 6. Return FetchResult
108
+ return {
109
+ extractedPath: extractPath,
110
+ metadata
111
+ };
112
+ }
113
+ catch (error) {
114
+ throw new Error(`Fetcher Error [${packageName}]: ${error.message}`);
115
+ }
116
+ }
117
+ /**
118
+ * Parses package.json from an extracted package directory.
119
+ */
120
+ function parsePackageJson(extractedPath) {
121
+ const pkgPath = path.join(extractedPath, 'package.json');
122
+ if (!fs.existsSync(pkgPath)) {
123
+ throw new Error(`package.json not found at ${pkgPath}`);
124
+ }
125
+ const fileContent = fs.readFileSync(pkgPath, 'utf-8');
126
+ try {
127
+ return JSON.parse(fileContent);
128
+ }
129
+ catch (error) {
130
+ throw new Error(`Failed to parse package.json at ${pkgPath}`);
131
+ }
132
+ }
133
+ /**
134
+ * Cleans up the temporary extraction directory.
135
+ */
136
+ async function cleanup(extractedPath) {
137
+ try {
138
+ await fsp.rm(extractedPath, { recursive: true, force: true });
139
+ }
140
+ catch (error) {
141
+ console.error(`Cleanup failed for ${extractedPath}:`, error);
142
+ }
143
+ }
144
+ //# sourceMappingURL=fetcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetcher.js","sourceRoot":"","sources":["../../src/core/fetcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * ═══════════════════════════════════════════════════════════
3
+ * AEGIS-AST — Import Extractor
4
+ * Owner: Person 1 (Core Engine)
5
+ * * Responsibilities:
6
+ * - Walk all .js/.ts files in extracted package
7
+ * - Extract require() and import statements via AST (Primary)
8
+ * - Fallback to regex extraction if AST parsing fails
9
+ * - Return deduplicated list of used dependencies
10
+ * ═══════════════════════════════════════════════════════════
11
+ */
12
+ import { ImportScanResult } from '../types';
13
+ /**
14
+ * Regex patterns for extracting imports from JavaScript/TypeScript files.
15
+ * Used strictly as a fallback if AST parsing fails.
16
+ */
17
+ export declare const IMPORT_PATTERNS: {
18
+ REQUIRE: RegExp;
19
+ ES_IMPORT: RegExp;
20
+ DYNAMIC_IMPORT: RegExp;
21
+ };
22
+ export declare function extractImports(extractedPath: string): Promise<ImportScanResult>;
23
+ /**
24
+ * Normalizes a raw import string to a package name.
25
+ */
26
+ export declare function normalizeImport(rawImport: string): string | null;
27
+ //# sourceMappingURL=imports.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imports.d.ts","sourceRoot":"","sources":["../../src/core/imports.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAa5C;;;GAGG;AACH,eAAO,MAAM,eAAe;;;;CAI3B,CAAC;AAEF,wBAAsB,cAAc,CAClC,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,gBAAgB,CAAC,CA0H3B;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgBhE"}
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ /**
3
+ * ═══════════════════════════════════════════════════════════
4
+ * AEGIS-AST — Import Extractor
5
+ * Owner: Person 1 (Core Engine)
6
+ * * Responsibilities:
7
+ * - Walk all .js/.ts files in extracted package
8
+ * - Extract require() and import statements via AST (Primary)
9
+ * - Fallback to regex extraction if AST parsing fails
10
+ * - Return deduplicated list of used dependencies
11
+ * ═══════════════════════════════════════════════════════════
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ var __importDefault = (this && this.__importDefault) || function (mod) {
47
+ return (mod && mod.__esModule) ? mod : { "default": mod };
48
+ };
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ exports.IMPORT_PATTERNS = void 0;
51
+ exports.extractImports = extractImports;
52
+ exports.normalizeImport = normalizeImport;
53
+ const file_walker_1 = require("../utils/file_walker");
54
+ const module_1 = require("module");
55
+ const path = __importStar(require("path"));
56
+ const parser = __importStar(require("@babel/parser"));
57
+ const DEBUG = process.env.AEGIS_DEBUG === 'true';
58
+ // Safely import Babel traverse for TypeScript environments
59
+ const traverse_1 = __importDefault(require("@babel/traverse"));
60
+ const traverse = typeof traverse_1.default === 'function' ? traverse_1.default : traverse_1.default.default;
61
+ /**
62
+ * Regex patterns for extracting imports from JavaScript/TypeScript files.
63
+ * Used strictly as a fallback if AST parsing fails.
64
+ */
65
+ exports.IMPORT_PATTERNS = {
66
+ REQUIRE: /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
67
+ ES_IMPORT: /import\s+(?:(?:[\w*{}\s,]+)\s+from\s+)?['"]([^'"]+)['"]/g,
68
+ DYNAMIC_IMPORT: /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
69
+ };
70
+ async function extractImports(extractedPath) {
71
+ const usedDependencies = new Set();
72
+ const rawImports = [];
73
+ // Helper to process, normalize, and store a found import (used by both AST and Regex)
74
+ function processImportRecord(rawImport, line, file) {
75
+ rawImports.push({
76
+ filePath: file,
77
+ importName: rawImport,
78
+ line: line,
79
+ });
80
+ const normalized = normalizeImport(rawImport);
81
+ if (normalized) {
82
+ usedDependencies.add(normalized);
83
+ }
84
+ }
85
+ // Helper to calculate the line number of a regex match
86
+ function getLineNumber(content, matchIndex) {
87
+ return content.substring(0, matchIndex).split('\n').length;
88
+ }
89
+ try {
90
+ // Uses your existing utils/file_walker.ts implementation
91
+ const files = (0, file_walker_1.walkSourceFiles)(extractedPath);
92
+ for (const sourceFile of files) {
93
+ const file = sourceFile.absolutePath;
94
+ const content = sourceFile.content;
95
+ try {
96
+ // ==========================================
97
+ // PRIMARY ENGINE: Babel AST Parsing
98
+ // ==========================================
99
+ const ast = parser.parse(content, {
100
+ sourceType: 'unambiguous', // Auto-detects ESM vs CommonJS
101
+ plugins: [
102
+ 'typescript',
103
+ 'jsx',
104
+ ['decorators', { decoratorsBeforeExport: true }] // Prevents crashes on NestJS/Angular files
105
+ ],
106
+ });
107
+ if (DEBUG)
108
+ console.log(`🟢 [AST] Successfully parsed: ${path.basename(file)}`);
109
+ traverse(ast, {
110
+ // Catch: import { x } from 'y'
111
+ ImportDeclaration(astPath) {
112
+ if (astPath.node.source && astPath.node.source.value) {
113
+ const line = astPath.node.loc?.start.line || 1;
114
+ processImportRecord(astPath.node.source.value, line, file);
115
+ }
116
+ },
117
+ // Catch: export { x } from 'y'
118
+ ExportNamedDeclaration(astPath) {
119
+ if (astPath.node.source && astPath.node.source.value) {
120
+ const line = astPath.node.loc?.start.line || 1;
121
+ processImportRecord(astPath.node.source.value, line, file);
122
+ }
123
+ },
124
+ // Catch: export * from 'y'
125
+ ExportAllDeclaration(astPath) {
126
+ if (astPath.node.source && astPath.node.source.value) {
127
+ const line = astPath.node.loc?.start.line || 1;
128
+ processImportRecord(astPath.node.source.value, line, file);
129
+ }
130
+ },
131
+ // Catch: require('y') and import('y')
132
+ CallExpression(astPath) {
133
+ const callee = astPath.node.callee;
134
+ const args = astPath.node.arguments;
135
+ if (args.length > 0 && args[0].type === 'StringLiteral') {
136
+ // Handle require()
137
+ if (callee.type === 'Identifier' && callee.name === 'require') {
138
+ const line = astPath.node.loc?.start.line || 1;
139
+ processImportRecord(args[0].value, line, file);
140
+ }
141
+ // Handle dynamic import()
142
+ else if (callee.type === 'Import') {
143
+ const line = astPath.node.loc?.start.line || 1;
144
+ processImportRecord(args[0].value, line, file);
145
+ }
146
+ }
147
+ }
148
+ });
149
+ }
150
+ catch (astError) {
151
+ // ==========================================
152
+ // BACKUP ENGINE: Regex Parsing
153
+ // Executes if file contains syntax errors / heavily obfuscated code
154
+ // ==========================================
155
+ const extractWithRegex = (pattern) => {
156
+ let match;
157
+ pattern.lastIndex = 0; // Reset global regex state
158
+ while ((match = pattern.exec(content)) !== null) {
159
+ const rawImport = match[1];
160
+ const lineNumber = getLineNumber(content, match.index);
161
+ processImportRecord(rawImport, lineNumber, file);
162
+ }
163
+ };
164
+ if (DEBUG)
165
+ console.log(`🟠 [REGEX] AST failed. Regex fallback triggered for: ${path.basename(file)}`);
166
+ extractWithRegex(exports.IMPORT_PATTERNS.REQUIRE);
167
+ extractWithRegex(exports.IMPORT_PATTERNS.ES_IMPORT);
168
+ extractWithRegex(exports.IMPORT_PATTERNS.DYNAMIC_IMPORT);
169
+ }
170
+ }
171
+ return {
172
+ usedDependencies: Array.from(usedDependencies),
173
+ rawImports,
174
+ };
175
+ }
176
+ catch (error) {
177
+ throw new Error(`Failed to extract imports from ${extractedPath}: ${error.message}`);
178
+ }
179
+ }
180
+ /**
181
+ * Normalizes a raw import string to a package name.
182
+ */
183
+ function normalizeImport(rawImport) {
184
+ if (rawImport.startsWith('.') || rawImport.startsWith('/')) {
185
+ return null;
186
+ }
187
+ const cleanImport = rawImport.startsWith('node:') ? rawImport.substring(5) : rawImport;
188
+ if (module_1.builtinModules.includes(cleanImport)) {
189
+ return null;
190
+ }
191
+ if (cleanImport.startsWith('@')) {
192
+ const parts = cleanImport.split('/');
193
+ if (parts.length >= 2) {
194
+ return `${parts[0]}/${parts[1]}`;
195
+ }
196
+ return cleanImport;
197
+ }
198
+ return cleanImport.split('/')[0];
199
+ }
200
+ //# sourceMappingURL=imports.js.map