mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-07 08:30:06 +00:00
feat: Enhanced import map with circular dependency detection
- Added circular dependency detection using DFS algorithm - Nodes in circular deps show red borders - Links in circular deps show in red color - Hover tooltips display complete circular import chains - Added circular dependency counter to stats panel - Reorganized all import map files to scripts/map/ - Deployed visualization to https://comfyui-frontend-import-map.pages.dev/ Found 140 circular dependencies in the codebase, primarily in: - litegraph library modules - Store and service modules - Widget composables 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
47925
dist-import-map/import-map.json
Normal file
47925
dist-import-map/import-map.json
Normal file
File diff suppressed because it is too large
Load Diff
48347
dist-import-map/index.html
Normal file
48347
dist-import-map/index.html
Normal file
File diff suppressed because it is too large
Load Diff
24353
docs/import-map.html
24353
docs/import-map.html
File diff suppressed because it is too large
Load Diff
23978
docs/import-map.json
23978
docs/import-map.json
File diff suppressed because it is too large
Load Diff
155
pnpm-lock.yaml
generated
155
pnpm-lock.yaml
generated
@@ -243,6 +243,9 @@ importers:
|
||||
'@vue/test-utils':
|
||||
specifier: ^2.4.6
|
||||
version: 2.4.6
|
||||
dependency-cruiser:
|
||||
specifier: ^17.0.1
|
||||
version: 17.0.1
|
||||
eslint:
|
||||
specifier: ^9.34.0
|
||||
version: 9.35.0(jiti@2.4.2)
|
||||
@@ -2903,11 +2906,22 @@ packages:
|
||||
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
|
||||
engines: {node: '>=6.5'}
|
||||
|
||||
acorn-jsx-walk@2.0.0:
|
||||
resolution: {integrity: sha512-uuo6iJj4D4ygkdzd6jPtcxs8vZgDX9YFIkqczGImoypX2fQ4dVImmu3UzA4ynixCIMTrEOWW+95M2HuBaCEOVA==}
|
||||
|
||||
acorn-jsx@5.3.2:
|
||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||
peerDependencies:
|
||||
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
|
||||
acorn-loose@8.5.2:
|
||||
resolution: {integrity: sha512-PPvV6g8UGMGgjrMu+n/f9E/tCSkNQ2Y97eFvuVdJfG11+xdIeDcLyNdC8SHcrHbRqkfwLASdplyR6B6sKM1U4A==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
||||
acorn-walk@8.3.4:
|
||||
resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
||||
acorn@7.4.1:
|
||||
resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
@@ -3309,6 +3323,10 @@ packages:
|
||||
resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
commander@14.0.1:
|
||||
resolution: {integrity: sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
commander@2.20.3:
|
||||
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
|
||||
|
||||
@@ -3492,6 +3510,11 @@ packages:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
||||
dependency-cruiser@17.0.1:
|
||||
resolution: {integrity: sha512-4clZ8EPsOVoxGA8NMjaE95aJEO118Cd9D7gT5rysx5azij9cPiCSrnjYlZtV+90PFazlD2lZvjzBHkD1ZqGqlw==}
|
||||
engines: {node: ^20.12||^22||>=24}
|
||||
hasBin: true
|
||||
|
||||
dequal@2.0.3:
|
||||
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -4245,6 +4268,10 @@ packages:
|
||||
react-devtools-core:
|
||||
optional: true
|
||||
|
||||
interpret@3.1.1:
|
||||
resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
|
||||
is-arrayish@0.2.1:
|
||||
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
|
||||
|
||||
@@ -4541,6 +4568,10 @@ packages:
|
||||
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
kleur@3.0.3:
|
||||
resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
knip@5.62.0:
|
||||
resolution: {integrity: sha512-hfTUVzmrMNMT1khlZfAYmBABeehwWUUrizLQoLamoRhSFkygsGIXWx31kaWKBgEaIVL77T3Uz7IxGvSw+CvQ6A==}
|
||||
engines: {node: '>=18.18.0'}
|
||||
@@ -4823,6 +4854,10 @@ packages:
|
||||
media-encoder-host@9.0.20:
|
||||
resolution: {integrity: sha512-IyEYxw6az97RNuETOAZV4YZqNAPOiF9GKIp5mVZb4HOyWd6mhkWQ34ydOzhqAWogMyc4W05kjN/VCgTtgyFmsw==}
|
||||
|
||||
memoize@10.1.0:
|
||||
resolution: {integrity: sha512-MMbFhJzh4Jlg/poq1si90XRlTZRDHVqdlz2mPyGJ6kqMpyHUyVpDd5gpFAvVehW64+RA1eKE9Yt8aSLY7w2Kgg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
merge-stream@2.0.0:
|
||||
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
|
||||
|
||||
@@ -5354,6 +5389,10 @@ packages:
|
||||
promise@7.3.1:
|
||||
resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==}
|
||||
|
||||
prompts@2.4.2:
|
||||
resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
prosemirror-changeset@2.2.1:
|
||||
resolution: {integrity: sha512-J7msc6wbxB4ekDFj+n9gTW/jav/p53kdlivvuppHsrZXCaQdVgRghoZbSS3kwrRyAstRVQ4/+u5k7YfLgkkQvQ==}
|
||||
|
||||
@@ -5519,6 +5558,10 @@ packages:
|
||||
resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==}
|
||||
engines: {node: '>= 4'}
|
||||
|
||||
rechoir@0.8.0:
|
||||
resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==}
|
||||
engines: {node: '>= 10.13.0'}
|
||||
|
||||
recorder-audio-worklet-processor@5.0.35:
|
||||
resolution: {integrity: sha512-5Nzbk/6QzC3QFQ1EG2SE34c1ygLE22lIOvLyjy7N6XxE/jpAZrL4e7xR+yihiTaG3ajiWy6UjqL4XEBMM9ahFQ==}
|
||||
|
||||
@@ -5536,6 +5579,10 @@ packages:
|
||||
regenerate@1.4.2:
|
||||
resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==}
|
||||
|
||||
regexp-tree@0.1.27:
|
||||
resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==}
|
||||
hasBin: true
|
||||
|
||||
regexpu-core@6.2.0:
|
||||
resolution: {integrity: sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -5641,6 +5688,9 @@ packages:
|
||||
safe-buffer@5.2.1:
|
||||
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
|
||||
|
||||
safe-regex@2.1.1:
|
||||
resolution: {integrity: sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==}
|
||||
|
||||
safer-buffer@2.1.2:
|
||||
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
||||
|
||||
@@ -5698,6 +5748,9 @@ packages:
|
||||
resolution: {integrity: sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
sisteransi@1.0.5:
|
||||
resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
|
||||
|
||||
slice-ansi@5.0.0:
|
||||
resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -5977,6 +6030,10 @@ packages:
|
||||
ts-map@1.0.3:
|
||||
resolution: {integrity: sha512-vDWbsl26LIcPGmDpoVzjEP6+hvHZkBkLW7JpvwbCv/5IYPJlsbzCVXY3wsCeAxAUeTclNOUZxnLdGh3VBD/J6w==}
|
||||
|
||||
tsconfig-paths-webpack-plugin@4.2.0:
|
||||
resolution: {integrity: sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
|
||||
tsconfig-paths@4.2.0:
|
||||
resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -6291,8 +6348,8 @@ packages:
|
||||
vue-component-type-helpers@2.2.12:
|
||||
resolution: {integrity: sha512-YbGqHZ5/eW4SnkPNR44mKVc6ZKQoRs/Rux1sxC6rdwXb4qpbOSYfDr9DsTHolOTGmIKgM9j141mZbBeg05R1pw==}
|
||||
|
||||
vue-component-type-helpers@3.0.6:
|
||||
resolution: {integrity: sha512-6CRM8X7EJqWCJOiKPvSLQG+hJPb/Oy2gyJx3pLjUEhY7PuaCthQu3e0zAGI1lqUBobrrk9IT0K8sG2GsCluxoQ==}
|
||||
vue-component-type-helpers@3.0.7:
|
||||
resolution: {integrity: sha512-TvyUcFXmjZcXUvU+r1MOyn4/vv4iF+tPwg5Ig33l/FJ3myZkxeQpzzQMLMFWcQAjr6Xs7BRwVy/TwbmNZUA/4w==}
|
||||
|
||||
vue-demi@0.14.10:
|
||||
resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==}
|
||||
@@ -6373,6 +6430,11 @@ packages:
|
||||
resolution: {integrity: sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==}
|
||||
engines: {node: 20 || >=22}
|
||||
|
||||
watskeburt@4.2.3:
|
||||
resolution: {integrity: sha512-uG9qtQYoHqAsnT711nG5iZc/8M5inSmkGCOp7pFaytKG2aTfIca7p//CjiVzAE4P7hzaYuCozMjNNaLgmhbK5g==}
|
||||
engines: {node: ^18||>=20}
|
||||
hasBin: true
|
||||
|
||||
wcwidth@1.0.1:
|
||||
resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
|
||||
|
||||
@@ -8832,7 +8894,7 @@ snapshots:
|
||||
storybook: 9.1.1(@testing-library/dom@10.4.1)(prettier@3.3.2)(vite@5.4.19(@types/node@20.14.10)(lightningcss@1.30.1)(terser@5.39.2))
|
||||
type-fest: 2.19.0
|
||||
vue: 3.5.13(typescript@5.9.2)
|
||||
vue-component-type-helpers: 3.0.6
|
||||
vue-component-type-helpers: 3.0.7
|
||||
|
||||
'@tailwindcss/node@4.1.12':
|
||||
dependencies:
|
||||
@@ -9658,14 +9720,20 @@ snapshots:
|
||||
dependencies:
|
||||
event-target-shim: 5.0.1
|
||||
|
||||
acorn-jsx@5.3.2(acorn@8.14.1):
|
||||
dependencies:
|
||||
acorn: 8.14.1
|
||||
acorn-jsx-walk@2.0.0: {}
|
||||
|
||||
acorn-jsx@5.3.2(acorn@8.15.0):
|
||||
dependencies:
|
||||
acorn: 8.15.0
|
||||
|
||||
acorn-loose@8.5.2:
|
||||
dependencies:
|
||||
acorn: 8.15.0
|
||||
|
||||
acorn-walk@8.3.4:
|
||||
dependencies:
|
||||
acorn: 8.15.0
|
||||
|
||||
acorn@7.4.1: {}
|
||||
|
||||
acorn@8.14.1: {}
|
||||
@@ -9899,7 +9967,7 @@ snapshots:
|
||||
dependencies:
|
||||
ansi-align: 3.0.1
|
||||
camelcase: 8.0.0
|
||||
chalk: 5.3.0
|
||||
chalk: 5.6.0
|
||||
cli-boxes: 3.0.0
|
||||
string-width: 7.2.0
|
||||
type-fest: 4.41.0
|
||||
@@ -10081,6 +10149,8 @@ snapshots:
|
||||
|
||||
commander@13.1.0: {}
|
||||
|
||||
commander@14.0.1: {}
|
||||
|
||||
commander@2.20.3: {}
|
||||
|
||||
commander@8.3.0: {}
|
||||
@@ -10246,6 +10316,29 @@ snapshots:
|
||||
|
||||
delayed-stream@1.0.0: {}
|
||||
|
||||
dependency-cruiser@17.0.1:
|
||||
dependencies:
|
||||
acorn: 8.15.0
|
||||
acorn-jsx: 5.3.2(acorn@8.15.0)
|
||||
acorn-jsx-walk: 2.0.0
|
||||
acorn-loose: 8.5.2
|
||||
acorn-walk: 8.3.4
|
||||
ajv: 8.17.1
|
||||
commander: 14.0.1
|
||||
enhanced-resolve: 5.18.3
|
||||
ignore: 7.0.5
|
||||
interpret: 3.1.1
|
||||
is-installed-globally: 1.0.0
|
||||
json5: 2.2.3
|
||||
memoize: 10.1.0
|
||||
picomatch: 4.0.3
|
||||
prompts: 2.4.2
|
||||
rechoir: 0.8.0
|
||||
safe-regex: 2.1.1
|
||||
semver: 7.7.2
|
||||
tsconfig-paths-webpack-plugin: 4.2.0
|
||||
watskeburt: 4.2.3
|
||||
|
||||
dequal@2.0.3: {}
|
||||
|
||||
detect-libc@2.0.4: {}
|
||||
@@ -10575,8 +10668,8 @@ snapshots:
|
||||
|
||||
espree@10.2.0:
|
||||
dependencies:
|
||||
acorn: 8.14.1
|
||||
acorn-jsx: 5.3.2(acorn@8.14.1)
|
||||
acorn: 8.15.0
|
||||
acorn-jsx: 5.3.2(acorn@8.15.0)
|
||||
eslint-visitor-keys: 4.2.1
|
||||
|
||||
espree@10.4.0:
|
||||
@@ -10587,8 +10680,8 @@ snapshots:
|
||||
|
||||
espree@9.6.1:
|
||||
dependencies:
|
||||
acorn: 8.14.1
|
||||
acorn-jsx: 5.3.2(acorn@8.14.1)
|
||||
acorn: 8.15.0
|
||||
acorn-jsx: 5.3.2(acorn@8.15.0)
|
||||
eslint-visitor-keys: 3.4.3
|
||||
|
||||
esprima@4.0.1: {}
|
||||
@@ -11100,6 +11193,8 @@ snapshots:
|
||||
- bufferutil
|
||||
- utf-8-validate
|
||||
|
||||
interpret@3.1.1: {}
|
||||
|
||||
is-arrayish@0.2.1: {}
|
||||
|
||||
is-binary-path@2.1.0:
|
||||
@@ -11377,6 +11472,8 @@ snapshots:
|
||||
|
||||
kind-of@6.0.3: {}
|
||||
|
||||
kleur@3.0.3: {}
|
||||
|
||||
knip@5.62.0(@types/node@20.14.10)(typescript@5.9.2):
|
||||
dependencies:
|
||||
'@nodelib/fs.walk': 1.2.8
|
||||
@@ -11739,6 +11836,10 @@ snapshots:
|
||||
media-encoder-host-worker: 10.0.19
|
||||
tslib: 2.8.1
|
||||
|
||||
memoize@10.1.0:
|
||||
dependencies:
|
||||
mimic-function: 5.0.1
|
||||
|
||||
merge-stream@2.0.0: {}
|
||||
|
||||
merge2@1.4.1: {}
|
||||
@@ -12407,6 +12508,11 @@ snapshots:
|
||||
dependencies:
|
||||
asap: 2.0.6
|
||||
|
||||
prompts@2.4.2:
|
||||
dependencies:
|
||||
kleur: 3.0.3
|
||||
sisteransi: 1.0.5
|
||||
|
||||
prosemirror-changeset@2.2.1:
|
||||
dependencies:
|
||||
prosemirror-transform: 1.10.2
|
||||
@@ -12661,6 +12767,10 @@ snapshots:
|
||||
tiny-invariant: 1.3.3
|
||||
tslib: 2.8.1
|
||||
|
||||
rechoir@0.8.0:
|
||||
dependencies:
|
||||
resolve: 1.22.10
|
||||
|
||||
recorder-audio-worklet-processor@5.0.35:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
@@ -12688,6 +12798,8 @@ snapshots:
|
||||
|
||||
regenerate@1.4.2: {}
|
||||
|
||||
regexp-tree@0.1.27: {}
|
||||
|
||||
regexpu-core@6.2.0:
|
||||
dependencies:
|
||||
regenerate: 1.4.2
|
||||
@@ -12822,6 +12934,10 @@ snapshots:
|
||||
|
||||
safe-buffer@5.2.1: {}
|
||||
|
||||
safe-regex@2.1.1:
|
||||
dependencies:
|
||||
regexp-tree: 0.1.27
|
||||
|
||||
safer-buffer@2.1.2: {}
|
||||
|
||||
saxes@6.0.0:
|
||||
@@ -12872,6 +12988,8 @@ snapshots:
|
||||
mrmime: 2.0.1
|
||||
totalist: 3.0.1
|
||||
|
||||
sisteransi@1.0.5: {}
|
||||
|
||||
slice-ansi@5.0.0:
|
||||
dependencies:
|
||||
ansi-styles: 6.2.1
|
||||
@@ -13066,7 +13184,7 @@ snapshots:
|
||||
terser@5.39.2:
|
||||
dependencies:
|
||||
'@jridgewell/source-map': 0.3.6
|
||||
acorn: 8.14.1
|
||||
acorn: 8.15.0
|
||||
commander: 2.20.3
|
||||
source-map-support: 0.5.21
|
||||
|
||||
@@ -13143,6 +13261,13 @@ snapshots:
|
||||
|
||||
ts-map@1.0.3: {}
|
||||
|
||||
tsconfig-paths-webpack-plugin@4.2.0:
|
||||
dependencies:
|
||||
chalk: 4.1.2
|
||||
enhanced-resolve: 5.18.3
|
||||
tapable: 2.2.3
|
||||
tsconfig-paths: 4.2.0
|
||||
|
||||
tsconfig-paths@4.2.0:
|
||||
dependencies:
|
||||
json5: 2.2.3
|
||||
@@ -13278,7 +13403,7 @@ snapshots:
|
||||
|
||||
unplugin@1.16.1:
|
||||
dependencies:
|
||||
acorn: 8.14.1
|
||||
acorn: 8.15.0
|
||||
webpack-virtual-modules: 0.6.2
|
||||
|
||||
unplugin@2.3.5:
|
||||
@@ -13504,7 +13629,7 @@ snapshots:
|
||||
|
||||
vue-component-type-helpers@2.2.12: {}
|
||||
|
||||
vue-component-type-helpers@3.0.6: {}
|
||||
vue-component-type-helpers@3.0.7: {}
|
||||
|
||||
vue-demi@0.14.10(vue@3.5.13(typescript@5.9.2)):
|
||||
dependencies:
|
||||
@@ -13588,6 +13713,8 @@ snapshots:
|
||||
|
||||
walk-up-path@4.0.0: {}
|
||||
|
||||
watskeburt@4.2.3: {}
|
||||
|
||||
wcwidth@1.0.1:
|
||||
dependencies:
|
||||
defaults: 1.0.4
|
||||
|
||||
12972
scripts/map/dependency-graph.svg
Normal file
12972
scripts/map/dependency-graph.svg
Normal file
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 1.1 MiB |
@@ -1,8 +1,7 @@
|
||||
#!/usr/bin/env tsx
|
||||
|
||||
import glob from 'fast-glob'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import glob from 'fast-glob'
|
||||
|
||||
interface ImportInfo {
|
||||
source: string
|
||||
@@ -15,11 +14,18 @@ interface DependencyGraph {
|
||||
label: string
|
||||
group: string
|
||||
size: number
|
||||
inCircularDep?: boolean
|
||||
circularChains?: string[][]
|
||||
}>
|
||||
links: Array<{
|
||||
source: string
|
||||
target: string
|
||||
value: number
|
||||
isCircular?: boolean
|
||||
}>
|
||||
circularDependencies?: Array<{
|
||||
chain: string[]
|
||||
edges: Array<{ source: string; target: string }>
|
||||
}>
|
||||
}
|
||||
|
||||
@@ -27,21 +33,22 @@ interface DependencyGraph {
|
||||
function extractImports(filePath: string): ImportInfo {
|
||||
const content = fs.readFileSync(filePath, 'utf-8')
|
||||
const imports: string[] = []
|
||||
|
||||
|
||||
// Match ES6 import statements
|
||||
const importRegex = /import\s+(?:(?:\{[^}]*\}|\*\s+as\s+\w+|\w+)\s+from\s+)?['"]([^'"]+)['"]/g
|
||||
const importRegex =
|
||||
/import\s+(?:(?:\{[^}]*\}|\*\s+as\s+\w+|\w+)\s+from\s+)?['"]([^'"]+)['"]/g
|
||||
let match
|
||||
|
||||
|
||||
while ((match = importRegex.exec(content)) !== null) {
|
||||
imports.push(match[1])
|
||||
}
|
||||
|
||||
|
||||
// Also match dynamic imports
|
||||
const dynamicImportRegex = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g
|
||||
while ((match = dynamicImportRegex.exec(content)) !== null) {
|
||||
imports.push(match[1])
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
source: filePath,
|
||||
imports: [...new Set(imports)] // Remove duplicates
|
||||
@@ -51,7 +58,7 @@ function extractImports(filePath: string): ImportInfo {
|
||||
// Categorize file by its path
|
||||
function getFileGroup(filePath: string): string {
|
||||
const relativePath = path.relative(process.cwd(), filePath)
|
||||
|
||||
|
||||
if (relativePath.includes('node_modules')) return 'external'
|
||||
if (relativePath.startsWith('src/components')) return 'components'
|
||||
if (relativePath.startsWith('src/stores')) return 'stores'
|
||||
@@ -65,7 +72,7 @@ function getFileGroup(filePath: string): string {
|
||||
if (relativePath.startsWith('src/scripts')) return 'scripts'
|
||||
if (relativePath.startsWith('tests')) return 'tests'
|
||||
if (relativePath.startsWith('browser_tests')) return 'browser_tests'
|
||||
|
||||
|
||||
return 'other'
|
||||
}
|
||||
|
||||
@@ -75,31 +82,127 @@ function resolveImportPath(importPath: string, sourceFile: string): string {
|
||||
if (importPath.startsWith('@/')) {
|
||||
return path.join(process.cwd(), 'src', importPath.slice(2))
|
||||
}
|
||||
|
||||
|
||||
// Handle relative paths
|
||||
if (importPath.startsWith('.')) {
|
||||
const sourceDir = path.dirname(sourceFile)
|
||||
return path.resolve(sourceDir, importPath)
|
||||
}
|
||||
|
||||
|
||||
// External module
|
||||
return importPath
|
||||
}
|
||||
|
||||
// Detect circular dependencies using DFS
|
||||
function detectCircularDependencies(
|
||||
nodes: Map<string, any>,
|
||||
links: Map<string, any>
|
||||
): Array<{
|
||||
chain: string[]
|
||||
edges: Array<{ source: string; target: string }>
|
||||
}> {
|
||||
const adjacencyList = new Map<string, Set<string>>()
|
||||
const circularDeps: Array<{
|
||||
chain: string[]
|
||||
edges: Array<{ source: string; target: string }>
|
||||
}> = []
|
||||
|
||||
// Build adjacency list
|
||||
for (const link of links.values()) {
|
||||
if (!adjacencyList.has(link.source)) {
|
||||
adjacencyList.set(link.source, new Set())
|
||||
}
|
||||
adjacencyList.get(link.source)!.add(link.target)
|
||||
}
|
||||
|
||||
// DFS to find cycles
|
||||
const visited = new Set<string>()
|
||||
const recStack = new Set<string>()
|
||||
const parent = new Map<string, string>()
|
||||
|
||||
function findCycle(node: string, path: string[] = []): void {
|
||||
visited.add(node)
|
||||
recStack.add(node)
|
||||
path.push(node)
|
||||
|
||||
const neighbors = adjacencyList.get(node) || new Set()
|
||||
for (const neighbor of neighbors) {
|
||||
if (!visited.has(neighbor)) {
|
||||
parent.set(neighbor, node)
|
||||
findCycle(neighbor, [...path])
|
||||
} else if (recStack.has(neighbor)) {
|
||||
// Found a cycle
|
||||
const cycleStartIndex = path.indexOf(neighbor)
|
||||
if (cycleStartIndex !== -1) {
|
||||
const chain = path.slice(cycleStartIndex)
|
||||
chain.push(neighbor) // Complete the cycle
|
||||
|
||||
// Create edges for the circular dependency
|
||||
const edges: Array<{ source: string; target: string }> = []
|
||||
for (let i = 0; i < chain.length - 1; i++) {
|
||||
edges.push({ source: chain[i], target: chain[i + 1] })
|
||||
}
|
||||
|
||||
// Check if this cycle is already recorded (avoid duplicates)
|
||||
const chainStr = [...chain].sort().join('->')
|
||||
const isNew = !circularDeps.some((dep) => {
|
||||
const existingChainStr = [...dep.chain].sort().join('->')
|
||||
return existingChainStr === chainStr
|
||||
})
|
||||
|
||||
if (isNew) {
|
||||
circularDeps.push({ chain, edges })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recStack.delete(node)
|
||||
}
|
||||
|
||||
// Run DFS from each unvisited node
|
||||
for (const node of nodes.keys()) {
|
||||
if (!visited.has(node) && !node.startsWith('external:')) {
|
||||
findCycle(node)
|
||||
}
|
||||
}
|
||||
|
||||
return circularDeps
|
||||
}
|
||||
|
||||
// Generate dependency graph
|
||||
async function generateDependencyGraph(): Promise<DependencyGraph> {
|
||||
const sourceFiles = await glob('src/**/*.{ts,tsx,vue,mts}', {
|
||||
ignore: ['**/node_modules/**', '**/*.d.ts', '**/*.spec.ts', '**/*.test.ts', '**/*.stories.ts']
|
||||
ignore: [
|
||||
'**/node_modules/**',
|
||||
'**/*.d.ts',
|
||||
'**/*.spec.ts',
|
||||
'**/*.test.ts',
|
||||
'**/*.stories.ts'
|
||||
]
|
||||
})
|
||||
|
||||
const nodes = new Map<string, { id: string; label: string; group: string; size: number }>()
|
||||
const links = new Map<string, { source: string; target: string; value: number }>()
|
||||
|
||||
|
||||
const nodes = new Map<
|
||||
string,
|
||||
{
|
||||
id: string
|
||||
label: string
|
||||
group: string
|
||||
size: number
|
||||
inCircularDep?: boolean
|
||||
circularChains?: string[][]
|
||||
}
|
||||
>()
|
||||
const links = new Map<
|
||||
string,
|
||||
{ source: string; target: string; value: number; isCircular?: boolean }
|
||||
>()
|
||||
|
||||
// Process each file
|
||||
for (const file of sourceFiles) {
|
||||
const importInfo = extractImports(file)
|
||||
const sourceId = path.relative(process.cwd(), file)
|
||||
|
||||
|
||||
// Add source node
|
||||
if (!nodes.has(sourceId)) {
|
||||
nodes.set(sourceId, {
|
||||
@@ -109,12 +212,12 @@ async function generateDependencyGraph(): Promise<DependencyGraph> {
|
||||
size: 1
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// Process imports
|
||||
for (const importPath of importInfo.imports) {
|
||||
const resolvedPath = resolveImportPath(importPath, file)
|
||||
let targetId: string
|
||||
|
||||
|
||||
// Check if it's an external module
|
||||
if (!resolvedPath.startsWith('/') && !resolvedPath.startsWith('.')) {
|
||||
targetId = `external:${importPath}`
|
||||
@@ -128,16 +231,25 @@ async function generateDependencyGraph(): Promise<DependencyGraph> {
|
||||
}
|
||||
} else {
|
||||
// Try to find the actual file
|
||||
const possibleExtensions = ['.ts', '.tsx', '.vue', '.mts', '.js', '.json', '/index.ts', '/index.js']
|
||||
const possibleExtensions = [
|
||||
'.ts',
|
||||
'.tsx',
|
||||
'.vue',
|
||||
'.mts',
|
||||
'.js',
|
||||
'.json',
|
||||
'/index.ts',
|
||||
'/index.js'
|
||||
]
|
||||
let actualFile = resolvedPath
|
||||
|
||||
|
||||
for (const ext of possibleExtensions) {
|
||||
if (fs.existsSync(resolvedPath + ext)) {
|
||||
actualFile = resolvedPath + ext
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (fs.existsSync(actualFile)) {
|
||||
targetId = path.relative(process.cwd(), actualFile)
|
||||
if (!nodes.has(targetId)) {
|
||||
@@ -152,7 +264,7 @@ async function generateDependencyGraph(): Promise<DependencyGraph> {
|
||||
continue // Skip unresolved imports
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add link
|
||||
const linkKey = `${sourceId}->${targetId}`
|
||||
if (links.has(linkKey)) {
|
||||
@@ -164,7 +276,7 @@ async function generateDependencyGraph(): Promise<DependencyGraph> {
|
||||
value: 1
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// Increase target node size
|
||||
const targetNode = nodes.get(targetId)
|
||||
if (targetNode) {
|
||||
@@ -172,10 +284,48 @@ async function generateDependencyGraph(): Promise<DependencyGraph> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Detect circular dependencies
|
||||
const circularDeps = detectCircularDependencies(nodes, links)
|
||||
|
||||
// Mark nodes and links involved in circular dependencies
|
||||
const nodesInCircularDeps = new Set<string>()
|
||||
const circularLinkKeys = new Set<string>()
|
||||
|
||||
for (const dep of circularDeps) {
|
||||
// Mark all nodes in the chain
|
||||
for (const nodeId of dep.chain) {
|
||||
nodesInCircularDeps.add(nodeId)
|
||||
const node = nodes.get(nodeId)
|
||||
if (node) {
|
||||
node.inCircularDep = true
|
||||
if (!node.circularChains) {
|
||||
node.circularChains = []
|
||||
}
|
||||
node.circularChains.push(dep.chain)
|
||||
}
|
||||
}
|
||||
|
||||
// Mark all edges in the chain
|
||||
for (const edge of dep.edges) {
|
||||
const linkKey = `${edge.source}->${edge.target}`
|
||||
circularLinkKeys.add(linkKey)
|
||||
const link = links.get(linkKey)
|
||||
if (link) {
|
||||
link.isCircular = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Found ${circularDeps.length} circular dependencies:`)
|
||||
circularDeps.forEach((dep, index) => {
|
||||
console.log(` ${index + 1}. ${dep.chain.join(' → ')}`)
|
||||
})
|
||||
|
||||
return {
|
||||
nodes: Array.from(nodes.values()),
|
||||
links: Array.from(links.values())
|
||||
links: Array.from(links.values()),
|
||||
circularDependencies: circularDeps
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,7 +432,22 @@ function generateHTML(graph: DependencyGraph): string {
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
z-index: 1000;
|
||||
max-width: 300px;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.circular-dep-warning {
|
||||
color: #ff6b6b;
|
||||
font-weight: bold;
|
||||
margin-top: 5px;
|
||||
padding-top: 5px;
|
||||
border-top: 1px solid #444;
|
||||
}
|
||||
|
||||
.circular-chain {
|
||||
color: #ffa500;
|
||||
font-family: monospace;
|
||||
font-size: 11px;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
@@ -320,6 +485,10 @@ function generateHTML(graph: DependencyGraph): string {
|
||||
<span>Total Dependencies:</span>
|
||||
<span id="total-links">${graph.links.length}</span>
|
||||
</div>
|
||||
<div class="stat-item" style="color: #ff6b6b;">
|
||||
<span>Circular Dependencies:</span>
|
||||
<span id="circular-deps">${graph.circularDependencies?.length || 0}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="text" class="search-box" placeholder="Search files..." id="search">
|
||||
@@ -362,6 +531,10 @@ function generateHTML(graph: DependencyGraph): string {
|
||||
<div class="legend-color" style="background: #636e72;"></div>
|
||||
<span>Other</span>
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<div class="legend-color" style="background: none; border: 2px solid #ff0000;"></div>
|
||||
<span>Has Circular Dep</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="controls">
|
||||
@@ -413,9 +586,9 @@ function generateHTML(graph: DependencyGraph): string {
|
||||
.selectAll('line')
|
||||
.data(graphData.links)
|
||||
.enter().append('line')
|
||||
.attr('stroke', '#999')
|
||||
.attr('stroke-opacity', 0.6)
|
||||
.attr('stroke-width', d => Math.sqrt(d.value));
|
||||
.attr('stroke', d => d.isCircular ? '#ff6666' : '#999')
|
||||
.attr('stroke-opacity', d => d.isCircular ? 0.8 : 0.6)
|
||||
.attr('stroke-width', d => d.isCircular ? Math.sqrt(d.value) * 1.5 : Math.sqrt(d.value));
|
||||
|
||||
// Create nodes
|
||||
const node = g.append('g')
|
||||
@@ -424,8 +597,8 @@ function generateHTML(graph: DependencyGraph): string {
|
||||
.enter().append('circle')
|
||||
.attr('r', d => Math.sqrt(d.size) * 3 + 3)
|
||||
.attr('fill', d => colorScale(d.group))
|
||||
.attr('stroke', '#fff')
|
||||
.attr('stroke-width', 1.5)
|
||||
.attr('stroke', d => d.inCircularDep ? '#ff0000' : '#fff')
|
||||
.attr('stroke-width', d => d.inCircularDep ? 3 : 1.5)
|
||||
.call(drag(simulation));
|
||||
|
||||
// Add labels for important nodes
|
||||
@@ -444,16 +617,40 @@ function generateHTML(graph: DependencyGraph): string {
|
||||
|
||||
node.on('mouseover', (event, d) => {
|
||||
const connections = graphData.links.filter(l => l.source.id === d.id || l.target.id === d.id);
|
||||
|
||||
let tooltipContent = \`
|
||||
<strong>\${d.label}</strong><br>
|
||||
Type: \${d.group}<br>
|
||||
Connections: \${connections.length}<br>
|
||||
Path: \${d.id}
|
||||
\`;
|
||||
|
||||
// Add circular dependency information if applicable
|
||||
if (d.inCircularDep && d.circularChains) {
|
||||
tooltipContent += '<div class="circular-dep-warning">⚠️ Circular Dependency Detected!</div>';
|
||||
d.circularChains.forEach((chain, index) => {
|
||||
// Only show chains that include this node
|
||||
if (chain.includes(d.id)) {
|
||||
// Format the chain to show the cycle clearly
|
||||
const nodeIndex = chain.indexOf(d.id);
|
||||
const formattedChain = chain.map((node, i) => {
|
||||
const basename = node.split('/').pop();
|
||||
if (i === nodeIndex) {
|
||||
return \`<strong>\${basename}</strong>\`;
|
||||
}
|
||||
return basename;
|
||||
}).join(' → ');
|
||||
|
||||
tooltipContent += \`<div class="circular-chain">Chain \${index + 1}: \${formattedChain}</div>\`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
tooltip
|
||||
.style('opacity', 1)
|
||||
.style('left', (event.pageX + 10) + 'px')
|
||||
.style('top', (event.pageY - 10) + 'px')
|
||||
.html(\`
|
||||
<strong>\${d.label}</strong><br>
|
||||
Type: \${d.group}<br>
|
||||
Connections: \${connections.length}<br>
|
||||
Path: \${d.id}
|
||||
\`);
|
||||
.html(tooltipContent);
|
||||
})
|
||||
.on('mouseout', () => {
|
||||
tooltip.style('opacity', 0);
|
||||
@@ -562,29 +759,49 @@ function generateHTML(graph: DependencyGraph): string {
|
||||
// Main function
|
||||
async function main() {
|
||||
console.log('Generating import map...')
|
||||
|
||||
|
||||
try {
|
||||
const graph = await generateDependencyGraph()
|
||||
console.log(`Found ${graph.nodes.length} nodes and ${graph.links.length} dependencies`)
|
||||
|
||||
console.log(
|
||||
`Found ${graph.nodes.length} nodes and ${graph.links.length} dependencies`
|
||||
)
|
||||
|
||||
if (graph.circularDependencies && graph.circularDependencies.length > 0) {
|
||||
console.log(
|
||||
`\n⚠️ Warning: Found ${graph.circularDependencies.length} circular dependencies!`
|
||||
)
|
||||
}
|
||||
|
||||
// Save JSON data
|
||||
const jsonPath = path.join(process.cwd(), 'docs', 'import-map.json')
|
||||
const jsonPath = path.join(
|
||||
process.cwd(),
|
||||
'scripts',
|
||||
'map',
|
||||
'import-map.json'
|
||||
)
|
||||
fs.mkdirSync(path.dirname(jsonPath), { recursive: true })
|
||||
fs.writeFileSync(jsonPath, JSON.stringify(graph, null, 2))
|
||||
console.log(`Saved JSON data to ${jsonPath}`)
|
||||
|
||||
|
||||
// Generate and save HTML visualization
|
||||
const html = generateHTML(graph)
|
||||
const htmlPath = path.join(process.cwd(), 'docs', 'import-map.html')
|
||||
const htmlPath = path.join(
|
||||
process.cwd(),
|
||||
'scripts',
|
||||
'map',
|
||||
'import-map.html'
|
||||
)
|
||||
fs.writeFileSync(htmlPath, html)
|
||||
console.log(`Saved HTML visualization to ${htmlPath}`)
|
||||
|
||||
|
||||
console.log('✅ Import map generation complete!')
|
||||
console.log('Open docs/import-map.html in a browser to view the visualization')
|
||||
console.log(
|
||||
'Open scripts/map/import-map.html in a browser to view the visualization'
|
||||
)
|
||||
} catch (error) {
|
||||
console.error('Error generating import map:', error)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
void main()
|
||||
48347
scripts/map/import-map.html
Normal file
48347
scripts/map/import-map.html
Normal file
File diff suppressed because it is too large
Load Diff
47925
scripts/map/import-map.json
Normal file
47925
scripts/map/import-map.json
Normal file
File diff suppressed because it is too large
Load Diff
3
wrangler.toml
Normal file
3
wrangler.toml
Normal file
@@ -0,0 +1,3 @@
|
||||
name = "comfyui-frontend-import-map"
|
||||
compatibility_date = "2024-09-16"
|
||||
pages_build_output_dir = "./dist-import-map"
|
||||
Reference in New Issue
Block a user