Merge pull request #85 from avenue9977/refactor/Improve-graph-builder

Refactor/improve graph builder
This commit is contained in:
Yuxiang Lin
2026-04-13 16:59:38 +08:00
committed by GitHub
Unverified
2 changed files with 297 additions and 165 deletions
+212 -74
View File
@@ -13,13 +13,13 @@ importers:
version: 5.9.3
vitest:
specifier: ^3.1.0
version: 3.2.4(@types/debug@4.1.12)(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)
version: 3.2.4(@types/debug@4.1.12)(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
homepage:
dependencies:
astro:
specifier: ^6.0.4
version: 6.0.4(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.59.0)(typescript@5.9.3)(yaml@2.8.3)
version: 6.0.4(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.59.0)(typescript@5.9.3)(yaml@2.8.3)
understand-anything-plugin:
dependencies:
@@ -35,7 +35,7 @@ importers:
version: 5.9.3
vitest:
specifier: ^3.1.0
version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)
version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
understand-anything-plugin/packages/core:
dependencies:
@@ -66,13 +66,13 @@ importers:
version: 25.5.0
'@vitest/coverage-v8':
specifier: 3.2.4
version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3))
version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3))
typescript:
specifier: ^5.7.0
version: 5.9.3
vitest:
specifier: ^3.1.0
version: 3.2.4(@types/debug@4.1.12)(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)
version: 3.2.4(@types/debug@4.1.12)(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
understand-anything-plugin/packages/dashboard:
dependencies:
@@ -109,7 +109,7 @@ importers:
devDependencies:
'@tailwindcss/vite':
specifier: ^4.0.0
version: 4.2.1(vite@6.4.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3))
version: 4.2.1(vite@6.4.2(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3))
'@types/d3-force':
specifier: ^3.0.10
version: 3.0.10
@@ -121,7 +121,7 @@ importers:
version: 19.2.3(@types/react@19.2.14)
'@vitejs/plugin-react':
specifier: ^4.3.0
version: 4.7.0(vite@6.4.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3))
version: 4.7.0(vite@6.4.2(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3))
tailwindcss:
specifier: ^4.0.0
version: 4.2.1
@@ -130,7 +130,7 @@ importers:
version: 5.9.3
vite:
specifier: ^6.0.0
version: 6.4.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)
version: 6.4.2(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
packages:
@@ -205,8 +205,8 @@ packages:
resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
engines: {node: '>=6.9.0'}
'@babel/helpers@7.28.6':
resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==}
'@babel/helpers@7.29.2':
resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==}
engines: {node: '>=6.9.0'}
'@babel/parser@7.29.0':
@@ -1191,8 +1191,8 @@ packages:
resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
engines: {node: 18 || 20 || >=22}
baseline-browser-mapping@2.10.7:
resolution: {integrity: sha512-1ghYO3HnxGec0TCGBXiDLVns4eCSx4zJpxnHrlqFQajmhfKMQBzUGDdkMK7fUW7PTHTeLf+j87aTuKuuwWzMGw==}
baseline-browser-mapping@2.10.18:
resolution: {integrity: sha512-VSnGQAOLtP5mib/DPyg2/t+Tlv65NTBz83BJBJvmLVHHuKJVaDOBvJJykiT5TR++em5nfAySPccDZDa4oSrn8A==}
engines: {node: '>=6.0.0'}
hasBin: true
@@ -1206,8 +1206,8 @@ packages:
resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==}
engines: {node: 18 || 20 || >=22}
browserslist@4.28.1:
resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==}
browserslist@4.28.2:
resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
@@ -1215,8 +1215,8 @@ packages:
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
engines: {node: '>=8'}
caniuse-lite@1.0.30001778:
resolution: {integrity: sha512-PN7uxFL+ExFJO61aVmP1aIEG4i9whQd4eoSCebav62UwDyp5OHh06zN4jqKSMePVgxHifCw1QJxdRkA1Pisekg==}
caniuse-lite@1.0.30001787:
resolution: {integrity: sha512-mNcrMN9KeI68u7muanUpEejSLghOKlVhRqS/Za2IeyGllJ9I9otGpR9g3nsw7n4W378TE/LyIteA0+/FOZm4Kg==}
ccount@2.0.1:
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
@@ -1422,8 +1422,8 @@ packages:
eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
electron-to-chromium@1.5.313:
resolution: {integrity: sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA==}
electron-to-chromium@1.5.335:
resolution: {integrity: sha512-q9n5T4BR4Xwa2cwbrwcsDJtHD/enpQ5S1xF1IAtdqf5AAgqDFmR/aakqH3ChFdqd/QXJhS3rnnXFtexU7rax6Q==}
emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
@@ -1688,70 +1688,140 @@ packages:
cpu: [arm64]
os: [android]
lightningcss-android-arm64@1.32.0:
resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [android]
lightningcss-darwin-arm64@1.31.1:
resolution: {integrity: sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [darwin]
lightningcss-darwin-arm64@1.32.0:
resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [darwin]
lightningcss-darwin-x64@1.31.1:
resolution: {integrity: sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [darwin]
lightningcss-darwin-x64@1.32.0:
resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [darwin]
lightningcss-freebsd-x64@1.31.1:
resolution: {integrity: sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [freebsd]
lightningcss-freebsd-x64@1.32.0:
resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [freebsd]
lightningcss-linux-arm-gnueabihf@1.31.1:
resolution: {integrity: sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==}
engines: {node: '>= 12.0.0'}
cpu: [arm]
os: [linux]
lightningcss-linux-arm-gnueabihf@1.32.0:
resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==}
engines: {node: '>= 12.0.0'}
cpu: [arm]
os: [linux]
lightningcss-linux-arm64-gnu@1.31.1:
resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
lightningcss-linux-arm64-gnu@1.32.0:
resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
lightningcss-linux-arm64-musl@1.31.1:
resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
lightningcss-linux-arm64-musl@1.32.0:
resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
lightningcss-linux-x64-gnu@1.31.1:
resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
lightningcss-linux-x64-gnu@1.32.0:
resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
lightningcss-linux-x64-musl@1.31.1:
resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
lightningcss-linux-x64-musl@1.32.0:
resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
lightningcss-win32-arm64-msvc@1.31.1:
resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [win32]
lightningcss-win32-arm64-msvc@1.32.0:
resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [win32]
lightningcss-win32-x64-msvc@1.31.1:
resolution: {integrity: sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [win32]
lightningcss-win32-x64-msvc@1.32.0:
resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [win32]
lightningcss@1.31.1:
resolution: {integrity: sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==}
engines: {node: '>= 12.0.0'}
lightningcss@1.32.0:
resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==}
engines: {node: '>= 12.0.0'}
longest-streak@3.1.0:
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
@@ -1967,8 +2037,8 @@ packages:
node-mock-http@1.0.4:
resolution: {integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==}
node-releases@2.0.36:
resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==}
node-releases@2.0.37:
resolution: {integrity: sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==}
normalize-path@3.0.0:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
@@ -2048,6 +2118,10 @@ packages:
resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
engines: {node: '>=12'}
picomatch@4.0.4:
resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==}
engines: {node: '>=12'}
postcss@8.5.8:
resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==}
engines: {node: ^10 || ^12 || >=14}
@@ -2462,8 +2536,8 @@ packages:
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
vite@6.4.1:
resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==}
vite@6.4.2:
resolution: {integrity: sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
peerDependencies:
@@ -2732,7 +2806,7 @@ snapshots:
'@babel/generator': 7.29.1
'@babel/helper-compilation-targets': 7.28.6
'@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0)
'@babel/helpers': 7.28.6
'@babel/helpers': 7.29.2
'@babel/parser': 7.29.0
'@babel/template': 7.28.6
'@babel/traverse': 7.29.0
@@ -2758,7 +2832,7 @@ snapshots:
dependencies:
'@babel/compat-data': 7.29.0
'@babel/helper-validator-option': 7.27.1
browserslist: 4.28.1
browserslist: 4.28.2
lru-cache: 5.1.1
semver: 6.3.1
@@ -2788,7 +2862,7 @@ snapshots:
'@babel/helper-validator-option@7.27.1': {}
'@babel/helpers@7.28.6':
'@babel/helpers@7.29.2':
dependencies:
'@babel/template': 7.28.6
'@babel/types': 7.29.0
@@ -3330,12 +3404,12 @@ snapshots:
'@tailwindcss/oxide-win32-arm64-msvc': 4.2.1
'@tailwindcss/oxide-win32-x64-msvc': 4.2.1
'@tailwindcss/vite@4.2.1(vite@6.4.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3))':
'@tailwindcss/vite@4.2.1(vite@6.4.2(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3))':
dependencies:
'@tailwindcss/node': 4.2.1
'@tailwindcss/oxide': 4.2.1
tailwindcss: 4.2.1
vite: 6.4.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)
vite: 6.4.2(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
'@types/babel__core@7.20.5':
dependencies:
@@ -3434,7 +3508,7 @@ snapshots:
'@ungap/structured-clone@1.3.0': {}
'@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3))':
'@vitejs/plugin-react@4.7.0(vite@6.4.2(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3))':
dependencies:
'@babel/core': 7.29.0
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0)
@@ -3442,11 +3516,11 @@ snapshots:
'@rolldown/pluginutils': 1.0.0-beta.27
'@types/babel__core': 7.20.5
react-refresh: 0.17.0
vite: 6.4.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)
vite: 6.4.2(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
transitivePeerDependencies:
- supports-color
'@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3))':
'@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3))':
dependencies:
'@ampproject/remapping': 2.3.0
'@bcoe/v8-coverage': 1.0.2
@@ -3461,7 +3535,7 @@ snapshots:
std-env: 3.10.0
test-exclude: 7.0.2
tinyrainbow: 2.0.0
vitest: 3.2.4(@types/debug@4.1.12)(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)
vitest: 3.2.4(@types/debug@4.1.12)(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
transitivePeerDependencies:
- supports-color
@@ -3473,13 +3547,21 @@ snapshots:
chai: 5.3.3
tinyrainbow: 2.0.0
'@vitest/mocker@3.2.4(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3))':
'@vitest/mocker@3.2.4(vite@7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3))':
dependencies:
'@vitest/spy': 3.2.4
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)
vite: 7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
'@vitest/mocker@3.2.4(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3))':
dependencies:
'@vitest/spy': 3.2.4
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
'@vitest/pretty-format@3.2.4':
dependencies:
@@ -3559,7 +3641,7 @@ snapshots:
estree-walker: 3.0.3
js-tokens: 10.0.0
astro@6.0.4(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.59.0)(typescript@5.9.3)(yaml@2.8.3):
astro@6.0.4(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.59.0)(typescript@5.9.3)(yaml@2.8.3):
dependencies:
'@astrojs/compiler': 3.0.0
'@astrojs/internal-helpers': 0.8.0
@@ -3611,8 +3693,8 @@ snapshots:
unist-util-visit: 5.1.0
unstorage: 1.17.4
vfile: 6.0.3
vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)
vitefu: 1.1.2(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3))
vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
vitefu: 1.1.2(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3))
xxhash-wasm: 1.1.0
yargs-parser: 22.0.0
zod: 4.3.6
@@ -3661,7 +3743,7 @@ snapshots:
balanced-match@4.0.4: {}
baseline-browser-mapping@2.10.7: {}
baseline-browser-mapping@2.10.18: {}
boolbase@1.0.0: {}
@@ -3673,17 +3755,17 @@ snapshots:
dependencies:
balanced-match: 4.0.4
browserslist@4.28.1:
browserslist@4.28.2:
dependencies:
baseline-browser-mapping: 2.10.7
caniuse-lite: 1.0.30001778
electron-to-chromium: 1.5.313
node-releases: 2.0.36
update-browserslist-db: 1.2.3(browserslist@4.28.1)
baseline-browser-mapping: 2.10.18
caniuse-lite: 1.0.30001787
electron-to-chromium: 1.5.335
node-releases: 2.0.37
update-browserslist-db: 1.2.3(browserslist@4.28.2)
cac@6.7.14: {}
caniuse-lite@1.0.30001778: {}
caniuse-lite@1.0.30001787: {}
ccount@2.0.1: {}
@@ -3863,7 +3945,7 @@ snapshots:
eastasianwidth@0.2.0: {}
electron-to-chromium@1.5.313: {}
electron-to-chromium@1.5.335: {}
emoji-regex@8.0.0: {}
@@ -3962,6 +4044,10 @@ snapshots:
optionalDependencies:
picomatch: 4.0.3
fdir@6.5.0(picomatch@4.0.4):
optionalDependencies:
picomatch: 4.0.4
flattie@1.1.1: {}
fontace@0.4.1:
@@ -4207,36 +4293,69 @@ snapshots:
lightningcss-android-arm64@1.31.1:
optional: true
lightningcss-android-arm64@1.32.0:
optional: true
lightningcss-darwin-arm64@1.31.1:
optional: true
lightningcss-darwin-arm64@1.32.0:
optional: true
lightningcss-darwin-x64@1.31.1:
optional: true
lightningcss-darwin-x64@1.32.0:
optional: true
lightningcss-freebsd-x64@1.31.1:
optional: true
lightningcss-freebsd-x64@1.32.0:
optional: true
lightningcss-linux-arm-gnueabihf@1.31.1:
optional: true
lightningcss-linux-arm-gnueabihf@1.32.0:
optional: true
lightningcss-linux-arm64-gnu@1.31.1:
optional: true
lightningcss-linux-arm64-gnu@1.32.0:
optional: true
lightningcss-linux-arm64-musl@1.31.1:
optional: true
lightningcss-linux-arm64-musl@1.32.0:
optional: true
lightningcss-linux-x64-gnu@1.31.1:
optional: true
lightningcss-linux-x64-gnu@1.32.0:
optional: true
lightningcss-linux-x64-musl@1.31.1:
optional: true
lightningcss-linux-x64-musl@1.32.0:
optional: true
lightningcss-win32-arm64-msvc@1.31.1:
optional: true
lightningcss-win32-arm64-msvc@1.32.0:
optional: true
lightningcss-win32-x64-msvc@1.31.1:
optional: true
lightningcss-win32-x64-msvc@1.32.0:
optional: true
lightningcss@1.31.1:
dependencies:
detect-libc: 2.1.2
@@ -4253,6 +4372,23 @@ snapshots:
lightningcss-win32-arm64-msvc: 1.31.1
lightningcss-win32-x64-msvc: 1.31.1
lightningcss@1.32.0:
dependencies:
detect-libc: 2.1.2
optionalDependencies:
lightningcss-android-arm64: 1.32.0
lightningcss-darwin-arm64: 1.32.0
lightningcss-darwin-x64: 1.32.0
lightningcss-freebsd-x64: 1.32.0
lightningcss-linux-arm-gnueabihf: 1.32.0
lightningcss-linux-arm64-gnu: 1.32.0
lightningcss-linux-arm64-musl: 1.32.0
lightningcss-linux-x64-gnu: 1.32.0
lightningcss-linux-x64-musl: 1.32.0
lightningcss-win32-arm64-msvc: 1.32.0
lightningcss-win32-x64-msvc: 1.32.0
optional: true
longest-streak@3.1.0: {}
loupe@3.2.1: {}
@@ -4671,7 +4807,7 @@ snapshots:
node-mock-http@1.0.4: {}
node-releases@2.0.36: {}
node-releases@2.0.37: {}
normalize-path@3.0.0: {}
@@ -4754,6 +4890,8 @@ snapshots:
picomatch@4.0.3: {}
picomatch@4.0.4: {}
postcss@8.5.8:
dependencies:
nanoid: 3.3.11
@@ -5190,9 +5328,9 @@ snapshots:
ofetch: 1.5.1
ufo: 1.6.3
update-browserslist-db@1.2.3(browserslist@4.28.1):
update-browserslist-db@1.2.3(browserslist@4.28.2):
dependencies:
browserslist: 4.28.1
browserslist: 4.28.2
escalade: 3.2.0
picocolors: 1.1.1
@@ -5215,13 +5353,13 @@ snapshots:
'@types/unist': 3.0.3
vfile-message: 4.0.3
vite-node@3.2.4(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3):
vite-node@3.2.4(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3):
dependencies:
cac: 6.7.14
debug: 4.4.3
es-module-lexer: 1.7.0
pathe: 2.0.3
vite: 6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)
vite: 6.4.2(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
transitivePeerDependencies:
- '@types/node'
- jiti
@@ -5236,13 +5374,13 @@ snapshots:
- tsx
- yaml
vite-node@3.2.4(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3):
vite-node@3.2.4(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3):
dependencies:
cac: 6.7.14
debug: 4.4.3
es-module-lexer: 1.7.0
pathe: 2.0.3
vite: 6.4.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)
vite: 6.4.2(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
transitivePeerDependencies:
- '@types/node'
- jiti
@@ -5257,11 +5395,11 @@ snapshots:
- tsx
- yaml
vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3):
vite@6.4.2(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3):
dependencies:
esbuild: 0.25.12
fdir: 6.5.0(picomatch@4.0.3)
picomatch: 4.0.3
fdir: 6.5.0(picomatch@4.0.4)
picomatch: 4.0.4
postcss: 8.5.8
rollup: 4.59.0
tinyglobby: 0.2.15
@@ -5269,14 +5407,14 @@ snapshots:
'@types/node': 22.19.15
fsevents: 2.3.3
jiti: 2.6.1
lightningcss: 1.31.1
lightningcss: 1.32.0
yaml: 2.8.3
vite@6.4.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3):
vite@6.4.2(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3):
dependencies:
esbuild: 0.25.12
fdir: 6.5.0(picomatch@4.0.3)
picomatch: 4.0.3
fdir: 6.5.0(picomatch@4.0.4)
picomatch: 4.0.4
postcss: 8.5.8
rollup: 4.59.0
tinyglobby: 0.2.15
@@ -5284,10 +5422,10 @@ snapshots:
'@types/node': 25.5.0
fsevents: 2.3.3
jiti: 2.6.1
lightningcss: 1.31.1
lightningcss: 1.32.0
yaml: 2.8.3
vite@7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3):
vite@7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3):
dependencies:
esbuild: 0.27.4
fdir: 6.5.0(picomatch@4.0.3)
@@ -5299,10 +5437,10 @@ snapshots:
'@types/node': 22.19.15
fsevents: 2.3.3
jiti: 2.6.1
lightningcss: 1.31.1
lightningcss: 1.32.0
yaml: 2.8.3
vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3):
vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3):
dependencies:
esbuild: 0.27.4
fdir: 6.5.0(picomatch@4.0.3)
@@ -5314,18 +5452,18 @@ snapshots:
'@types/node': 25.5.0
fsevents: 2.3.3
jiti: 2.6.1
lightningcss: 1.31.1
lightningcss: 1.32.0
yaml: 2.8.3
vitefu@1.1.2(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)):
vitefu@1.1.2(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)):
optionalDependencies:
vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)
vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3):
vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3):
dependencies:
'@types/chai': 5.2.3
'@vitest/expect': 3.2.4
'@vitest/mocker': 3.2.4(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3))
'@vitest/mocker': 3.2.4(vite@7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3))
'@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.2.4
'@vitest/snapshot': 3.2.4
@@ -5343,8 +5481,8 @@ snapshots:
tinyglobby: 0.2.15
tinypool: 1.1.1
tinyrainbow: 2.0.0
vite: 7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)
vite-node: 3.2.4(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)
vite: 7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
vite-node: 3.2.4(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/debug': 4.1.12
@@ -5363,11 +5501,11 @@ snapshots:
- tsx
- yaml
vitest@3.2.4(@types/debug@4.1.12)(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3):
vitest@3.2.4(@types/debug@4.1.12)(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3):
dependencies:
'@types/chai': 5.2.3
'@vitest/expect': 3.2.4
'@vitest/mocker': 3.2.4(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3))
'@vitest/mocker': 3.2.4(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3))
'@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.2.4
'@vitest/snapshot': 3.2.4
@@ -5385,8 +5523,8 @@ snapshots:
tinyglobby: 0.2.15
tinypool: 1.1.1
tinyrainbow: 2.0.0
vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)
vite-node: 3.2.4(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)
vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
vite-node: 3.2.4(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.3)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/debug': 4.1.12
@@ -35,6 +35,27 @@ interface NonCodeFileAnalysisMeta extends NonCodeFileMeta {
sections?: SectionInfo[];
}
const KIND_TO_NODE_TYPE: Record<string, GraphNode["type"]> = {
table: "table",
view: "table",
index: "table",
message: "schema",
type: "schema",
enum: "schema",
resource: "resource",
module: "resource",
service: "service",
deployment: "service",
job: "pipeline",
stage: "pipeline",
target: "pipeline",
route: "endpoint",
query: "endpoint",
mutation: "endpoint",
variable: "config",
output: "config",
};
const EXTENSION_LANGUAGE: Record<string, string> = {
// Code languages
".ts": "typescript",
@@ -102,27 +123,35 @@ function detectLanguage(filePath: string): string {
}
export class GraphBuilder {
private nodes: GraphNode[] = [];
private edges: GraphEdge[] = [];
private languages = new Set<string>();
private projectName: string;
private gitHash: string;
private readonly nodes: GraphNode[] = [];
private readonly edges: GraphEdge[] = [];
private readonly languages = new Set<string>();
private readonly nodeIds = new Set<string>();
private readonly edgeKeys = new Set<string>();
private readonly projectName: string;
private readonly gitHash: string;
constructor(projectName: string, gitHash: string) {
this.projectName = projectName;
this.gitHash = gitHash;
}
private static basename(filePath: string): string {
return filePath.split("/").pop() ?? filePath;
}
addFile(filePath: string, meta: FileMeta): void {
const lang = detectLanguage(filePath);
if (lang !== "unknown") {
this.languages.add(lang);
}
const name = filePath.split("/").pop() ?? filePath;
const name = GraphBuilder.basename(filePath);
const id = `file:${filePath}`;
this.nodeIds.add(id);
this.nodes.push({
id: `file:${filePath}`,
id,
type: "file",
name,
filePath,
@@ -142,10 +171,11 @@ export class GraphBuilder {
this.languages.add(lang);
}
const fileName = filePath.split("/").pop() ?? filePath;
const fileName = GraphBuilder.basename(filePath);
const fileId = `file:${filePath}`;
// Create the file node
this.nodeIds.add(fileId);
this.nodes.push({
id: fileId,
type: "file",
@@ -159,6 +189,7 @@ export class GraphBuilder {
// Create function nodes with "contains" edges
for (const fn of analysis.functions) {
const funcId = `function:${filePath}:${fn.name}`;
this.nodeIds.add(funcId);
this.nodes.push({
id: funcId,
type: "function",
@@ -182,6 +213,7 @@ export class GraphBuilder {
// Create class nodes with "contains" edges
for (const cls of analysis.classes) {
const classId = `class:${filePath}:${cls.name}`;
this.nodeIds.add(classId);
this.nodes.push({
id: classId,
type: "class",
@@ -204,6 +236,9 @@ export class GraphBuilder {
}
addImportEdge(fromFile: string, toFile: string): void {
const key = `imports|file:${fromFile}|file:${toFile}`;
if (this.edgeKeys.has(key)) return;
this.edgeKeys.add(key);
this.edges.push({
source: `file:${fromFile}`,
target: `file:${toFile}`,
@@ -219,6 +254,9 @@ export class GraphBuilder {
calleeFile: string,
calleeFunc: string,
): void {
const key = `calls|function:${callerFile}:${callerFunc}|function:${calleeFile}:${calleeFunc}`;
if (this.edgeKeys.has(key)) return;
this.edgeKeys.add(key);
this.edges.push({
source: `function:${callerFile}:${callerFunc}`,
target: `function:${calleeFile}:${calleeFunc}`,
@@ -228,12 +266,14 @@ export class GraphBuilder {
});
}
addNonCodeFile(filePath: string, meta: NonCodeFileMeta): void {
addNonCodeFile(filePath: string, meta: NonCodeFileMeta): string {
const lang = detectLanguage(filePath);
if (lang !== "unknown") this.languages.add(lang);
const name = filePath.split("/").pop() ?? filePath;
const name = GraphBuilder.basename(filePath);
const id = `${meta.nodeType ?? "file"}:${filePath}`;
this.nodeIds.add(id);
this.nodes.push({
id: `${meta.nodeType ?? "file"}:${filePath}`,
id,
type: meta.nodeType,
name,
filePath,
@@ -241,24 +281,16 @@ export class GraphBuilder {
tags: meta.tags,
complexity: meta.complexity,
});
return id;
}
addNonCodeFileWithAnalysis(filePath: string, meta: NonCodeFileAnalysisMeta): void {
this.addNonCodeFile(filePath, meta);
const fileId = `${meta.nodeType ?? "file"}:${filePath}`;
const existingIds = new Set(this.nodes.map(n => n.id));
const fileId = this.addNonCodeFile(filePath, meta);
// Create child nodes for definitions (tables, schemas, etc.)
for (const def of meta.definitions ?? []) {
const childId = `${def.kind}:${filePath}:${def.name}`;
if (existingIds.has(childId)) {
console.warn(`[GraphBuilder] Duplicate node ID "${childId}" — skipping`);
continue;
}
existingIds.add(childId);
this.nodes.push({
id: childId,
this.addChildNode({
id: `${def.kind}:${filePath}:${def.name}`,
type: this.mapKindToNodeType(def.kind),
name: def.name,
filePath,
@@ -266,61 +298,41 @@ export class GraphBuilder {
summary: `${def.kind}: ${def.name} (${def.fields.length} fields)`,
tags: [],
complexity: meta.complexity,
});
this.edges.push({ source: fileId, target: childId, type: "contains", direction: "forward", weight: 1 });
}, fileId);
}
// Create child nodes for services
for (const svc of meta.services ?? []) {
const childId = `service:${filePath}:${svc.name}`;
if (existingIds.has(childId)) {
console.warn(`[GraphBuilder] Duplicate node ID "${childId}" — skipping`);
continue;
}
existingIds.add(childId);
this.nodes.push({
id: childId,
this.addChildNode({
id: `service:${filePath}:${svc.name}`,
type: "service",
name: svc.name,
filePath,
summary: `Service ${svc.name}${svc.image ? ` (image: ${svc.image})` : ""}`,
tags: [],
complexity: meta.complexity,
});
this.edges.push({ source: fileId, target: childId, type: "contains", direction: "forward", weight: 1 });
}, fileId);
}
// Create child nodes for endpoints
for (const ep of meta.endpoints ?? []) {
const childId = `endpoint:${filePath}:${ep.path}`;
if (existingIds.has(childId)) {
console.warn(`[GraphBuilder] Duplicate node ID "${childId}" — skipping`);
continue;
}
existingIds.add(childId);
this.nodes.push({
id: childId,
const name = `${ep.method ?? ""} ${ep.path}`.trim();
this.addChildNode({
id: `endpoint:${filePath}:${ep.path}`,
type: "endpoint",
name: `${ep.method ?? ""} ${ep.path}`.trim(),
name,
filePath,
lineRange: ep.lineRange,
summary: `Endpoint: ${ep.method ?? ""} ${ep.path}`.trim(),
summary: `Endpoint: ${name}`,
tags: [],
complexity: meta.complexity,
});
this.edges.push({ source: fileId, target: childId, type: "contains", direction: "forward", weight: 1 });
}, fileId);
}
// Create child nodes for steps (pipeline/makefile targets)
for (const step of meta.steps ?? []) {
const childId = `step:${filePath}:${step.name}`;
if (existingIds.has(childId)) {
console.warn(`[GraphBuilder] Duplicate node ID "${childId}" — skipping`);
continue;
}
existingIds.add(childId);
this.nodes.push({
id: childId,
this.addChildNode({
id: `step:${filePath}:${step.name}`,
type: "pipeline",
name: step.name,
filePath,
@@ -328,20 +340,13 @@ export class GraphBuilder {
summary: `Step: ${step.name}`,
tags: [],
complexity: meta.complexity,
});
this.edges.push({ source: fileId, target: childId, type: "contains", direction: "forward", weight: 1 });
}, fileId);
}
// Create child nodes for resources (Terraform, etc.)
for (const res of meta.resources ?? []) {
const childId = `resource:${filePath}:${res.name}`;
if (existingIds.has(childId)) {
console.warn(`[GraphBuilder] Duplicate node ID "${childId}" — skipping`);
continue;
}
existingIds.add(childId);
this.nodes.push({
id: childId,
this.addChildNode({
id: `resource:${filePath}:${res.name}`,
type: "resource",
name: res.name,
filePath,
@@ -349,33 +354,22 @@ export class GraphBuilder {
summary: `Resource: ${res.name} (${res.kind})`,
tags: [],
complexity: meta.complexity,
});
this.edges.push({ source: fileId, target: childId, type: "contains", direction: "forward", weight: 1 });
}, fileId);
}
}
private addChildNode(node: GraphNode, parentId: string): void {
if (this.nodeIds.has(node.id)) {
console.warn(`[GraphBuilder] Duplicate node ID "${node.id}" — skipping`);
return;
}
this.nodeIds.add(node.id);
this.nodes.push(node);
this.edges.push({ source: parentId, target: node.id, type: "contains", direction: "forward", weight: 1 });
}
private mapKindToNodeType(kind: string): GraphNode["type"] {
const mapping: Record<string, GraphNode["type"]> = {
table: "table",
view: "table",
index: "table",
message: "schema",
type: "schema",
enum: "schema",
resource: "resource",
module: "resource",
service: "service",
deployment: "service",
job: "pipeline",
stage: "pipeline",
target: "pipeline",
route: "endpoint",
query: "endpoint",
mutation: "endpoint",
variable: "config",
output: "config",
};
const mapped = mapping[kind];
const mapped = KIND_TO_NODE_TYPE[kind];
if (!mapped) {
console.warn(`[GraphBuilder] Unknown definition kind "${kind}" — falling back to "concept" node type`);
}
@@ -387,14 +381,14 @@ export class GraphBuilder {
version: "1.0.0",
project: {
name: this.projectName,
languages: [...this.languages].sort(),
languages: [...this.languages].sort((a, b) => a.localeCompare(b)),
frameworks: [],
description: "",
analyzedAt: new Date().toISOString(),
gitCommitHash: this.gitHash,
},
nodes: this.nodes,
edges: this.edges,
nodes: [...this.nodes],
edges: [...this.edges],
layers: [],
tour: [],
};