diff --git a/litegraph b/litegraph index db6a916..cd4f68e 160000 --- a/litegraph +++ b/litegraph @@ -1 +1 @@ -Subproject commit db6a9167575db269524564d5527c512a06c0f8d2 +Subproject commit cd4f68ef42c52e7337009eec81f5e539de8999ad diff --git a/package.json b/package.json index 46c87bb..b4545f6 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "svelte-check": "^3.2.0", "svelte-dnd-action": "^0.9.22", "typescript": "^5.0.3", - "vite": "^4.3.1", + "vite": "^4.3.8", "vite-plugin-glsl": "^1.1.2", "vite-plugin-static-copy": "^0.14.0", "vite-plugin-svelte-console-remover": "^1.0.10", @@ -65,6 +65,7 @@ "@litegraph-ts/tsconfig": "workspace:*", "@sveltejs/vite-plugin-svelte": "^2.1.1", "@tsconfig/svelte": "^4.0.1", + "@zerodevx/svelte-json-view": "^1.0.5", "events": "^3.3.0", "framework7": "^8.0.3", "framework7-svelte": "^8.0.3", @@ -80,6 +81,7 @@ "tailwindcss": "^3.3.1", "typed-emitter": "github:andywer/typed-emitter", "uuid": "^9.0.0", - "vite-plugin-full-reload": "^1.0.5" + "vite-plugin-full-reload": "^1.0.5", + "zod": "^3.21.4" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 06df85c..50abc05 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -69,10 +69,13 @@ importers: version: link:litegraph/packages/tsconfig '@sveltejs/vite-plugin-svelte': specifier: ^2.1.1 - version: 2.1.1(svelte@3.58.0)(vite@4.3.1) + version: 2.1.1(svelte@3.58.0)(vite@4.3.8) '@tsconfig/svelte': specifier: ^4.0.1 version: 4.0.1 + '@zerodevx/svelte-json-view': + specifier: ^1.0.5 + version: 1.0.5(svelte@3.58.0) events: specifier: ^3.3.0 version: 3.3.0 @@ -120,7 +123,10 @@ importers: version: 9.0.0 vite-plugin-full-reload: specifier: ^1.0.5 - version: 1.0.5(vite@4.3.1) + version: 1.0.5(vite@4.3.8) + zod: + specifier: ^3.21.4 + version: 3.21.4 devDependencies: '@floating-ui/core': specifier: ^1.2.6 @@ -168,20 +174,20 @@ importers: specifier: ^5.0.3 version: 5.0.3 vite: - specifier: ^4.3.1 - version: 4.3.1(sass@1.61.0) + specifier: ^4.3.8 + version: 4.3.8(sass@1.61.0) vite-plugin-glsl: specifier: ^1.1.2 - version: 1.1.2(vite@4.3.1) + version: 1.1.2(vite@4.3.8) vite-plugin-static-copy: specifier: ^0.14.0 - version: 0.14.0(vite@4.3.1) + version: 0.14.0(vite@4.3.8) vite-plugin-svelte-console-remover: specifier: ^1.0.10 version: 1.0.10(sass@1.61.0) vite-tsconfig-paths: specifier: ^4.0.8 - version: 4.0.8(typescript@5.0.3)(vite@4.3.1) + version: 4.0.8(typescript@5.0.3)(vite@4.3.8) vitest: specifier: ^0.27.3 version: 0.27.3(happy-dom@9.18.3)(jsdom@22.0.0)(sass@1.61.0) @@ -3038,7 +3044,7 @@ packages: - supports-color dev: true - /@sveltejs/vite-plugin-svelte@2.1.1(svelte@3.58.0)(vite@4.3.1): + /@sveltejs/vite-plugin-svelte@2.1.1(svelte@3.58.0)(vite@4.3.8): resolution: {integrity: sha512-7YeBDt4us0FiIMNsVXxyaP4Hwyn2/v9x3oqStkHU3ZdIc5O22pGwUwH33wUqYo+7Itdmo8zxJ45Qvfm3H7UUjQ==} engines: {node: ^14.18.0 || >= 16} peerDependencies: @@ -3051,8 +3057,8 @@ packages: magic-string: 0.30.0 svelte: 3.58.0 svelte-hmr: 0.15.1(svelte@3.58.0) - vite: 4.3.1(sass@1.61.0) - vitefu: 0.2.4(vite@4.3.1) + vite: 4.3.8(sass@1.61.0) + vitefu: 0.2.4(vite@4.3.8) transitivePeerDependencies: - supports-color dev: false @@ -3060,7 +3066,7 @@ packages: /@swc/helpers@0.4.14: resolution: {integrity: sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==} dependencies: - tslib: 2.5.0 + tslib: 2.5.1 dev: false /@tootallnate/once@2.0.0: @@ -3126,10 +3132,14 @@ packages: /@types/chai-subset@1.3.3: resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} dependencies: - '@types/chai': 4.3.4 + '@types/chai': 4.3.5 /@types/chai@4.3.4: resolution: {integrity: sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==} + dev: false + + /@types/chai@4.3.5: + resolution: {integrity: sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==} /@types/concat-stream@1.6.1: resolution: {integrity: sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==} @@ -3368,6 +3378,14 @@ packages: pretty-format: 27.5.1 dev: false + /@zerodevx/svelte-json-view@1.0.5(svelte@3.58.0): + resolution: {integrity: sha512-oQDI9v0dJEte6PYVDVjLOjU58AOoWLYRXjghKggFpZXrglWJJqoMeDe14Jrd0cs6NPcPogT/aR/LtkuW2Z1GkQ==} + peerDependencies: + svelte: ^3.55.1 + dependencies: + svelte: 3.58.0 + dev: false + /@zerodevx/svelte-toast@0.9.3(svelte@3.58.0): resolution: {integrity: sha512-VPKWR4A9y01fyXRscu9HiTj7tV2hFrpRKZvGwMmaPXfHIXR1D9+NNsz0HXcQ7qZ0C5UaHS3n9uNtPtIcAXT7RQ==} peerDependencies: @@ -3510,7 +3528,7 @@ packages: engines: {node: '>=16.1.0'} dependencies: '@babel/runtime': 7.21.0 - tslib: 2.5.0 + tslib: 2.5.1 dev: false /autoprefixer@10.4.2(postcss@8.4.21): @@ -3682,7 +3700,7 @@ packages: dependencies: '@babel/runtime': 7.21.0 fast-unique-numbers: 8.0.0 - tslib: 2.5.0 + tslib: 2.5.1 worker-factory: 7.0.0 dev: false @@ -3691,8 +3709,8 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001481 - electron-to-chromium: 1.4.371 + caniuse-lite: 1.0.30001488 + electron-to-chromium: 1.4.400 node-releases: 2.0.10 update-browserslist-db: 1.0.11(browserslist@4.21.5) @@ -3753,6 +3771,10 @@ packages: /caniuse-lite@1.0.30001481: resolution: {integrity: sha512-KCqHwRnaa1InZBtqXzP98LPg0ajCVujMKjqKDhZEthIpAsJl/YEIa3YvXjGXPVqzZVguccuu7ga9KOE1J9rKPQ==} + dev: true + + /caniuse-lite@1.0.30001488: + resolution: {integrity: sha512-NORIQuuL4xGpIy6iCCQGN4iFjlBXtfKWIenlUuyZJumLRIindLb7wXM+GO8erEhb7vXfcnf4BAg2PrSDN5TNLQ==} /case@1.6.3: resolution: {integrity: sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==} @@ -3953,7 +3975,7 @@ packages: '@babel/runtime': 7.21.0 dashify: 2.0.0 indefinite-article: 0.0.2 - tslib: 2.5.0 + tslib: 2.5.1 dev: false /compilerr@11.0.0: @@ -3963,7 +3985,7 @@ packages: '@babel/runtime': 7.21.0 dashify: 2.0.0 indefinite-article: 0.0.2 - tslib: 2.5.0 + tslib: 2.5.1 dev: false /concat-map@0.0.1: @@ -4449,8 +4471,8 @@ packages: sigmund: 1.0.1 dev: false - /electron-to-chromium@1.4.371: - resolution: {integrity: sha512-jlBzY4tFcJaiUjzhRTCWAqRvTO/fWzjA3Bls0mykzGZ7zvcMP7h05W6UcgzfT9Ca1SW2xyKDOFRyI0pQeRNZGw==} + /electron-to-chromium@1.4.400: + resolution: {integrity: sha512-Lsvf7cvwbIxCfB8VqbnVtEsjGi3+48ejDiQZfWo5gkT+1vQ2DHQI5pl0nUvPD6z1IQk6JgFeMC5ZQJqVhalEHg==} /emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} @@ -4950,14 +4972,14 @@ packages: '@babel/runtime': 7.21.0 broker-factory: 3.0.76 extendable-media-recorder-wav-encoder-worker: 8.0.77 - tslib: 2.5.0 + tslib: 2.5.1 dev: false /extendable-media-recorder-wav-encoder-worker@8.0.77: resolution: {integrity: sha512-9g9Q7fhOxPY7RALHVTK9Wjnc8RPYjJ9XCBP1TaNtDraIAFxvhBRax9QUOmFqHM2MvRM6hQhNav7jn23yy6tcVQ==} dependencies: '@babel/runtime': 7.21.0 - tslib: 2.5.0 + tslib: 2.5.1 worker-factory: 7.0.0 dev: false @@ -5020,7 +5042,7 @@ packages: engines: {node: '>=14.15.4'} dependencies: '@babel/runtime': 7.21.0 - tslib: 2.5.0 + tslib: 2.5.1 dev: false /fast-unique-numbers@8.0.0: @@ -5028,7 +5050,7 @@ packages: engines: {node: '>=16.1.0'} dependencies: '@babel/runtime': 7.21.0 - tslib: 2.5.0 + tslib: 2.5.1 dev: false /fastq@1.15.0: @@ -6624,7 +6646,7 @@ packages: broker-factory: 3.0.76 fast-unique-numbers: 8.0.0 media-encoder-host-worker: 9.1.1 - tslib: 2.5.0 + tslib: 2.5.1 dev: false /media-encoder-host-worker@9.1.1: @@ -6632,7 +6654,7 @@ packages: dependencies: '@babel/runtime': 7.21.0 extendable-media-recorder-wav-encoder-broker: 7.0.78 - tslib: 2.5.0 + tslib: 2.5.1 worker-factory: 7.0.0 dev: false @@ -6642,7 +6664,7 @@ packages: '@babel/runtime': 7.21.0 media-encoder-host-broker: 7.0.79 media-encoder-host-worker: 9.1.1 - tslib: 2.5.0 + tslib: 2.5.1 dev: false /merge-stream@2.0.0: @@ -6760,7 +6782,7 @@ packages: engines: {node: '>=12.20.1'} dependencies: '@babel/runtime': 7.21.0 - tslib: 2.5.0 + tslib: 2.5.1 dev: false /murmurhash-js@1.0.0: @@ -7176,6 +7198,14 @@ packages: picocolors: 1.0.0 source-map-js: 1.0.2 + /postcss@8.4.23: + resolution: {integrity: sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.6 + picocolors: 1.0.0 + source-map-js: 1.0.2 + /posthtml-parser@0.10.2: resolution: {integrity: sha512-PId6zZ/2lyJi9LiKfe+i2xv57oEjJgWbsHGGANwos5AvdQp98i6AtamAl8gzSVFGfQ43Glb5D614cvZf012VKg==} engines: {node: '>=12'} @@ -7360,7 +7390,7 @@ packages: resolution: {integrity: sha512-oiiS2sp6eMxkvjt13yetSYUJvnAxBZk60mIxz0Vf/2lDWa/4svCyMLHIDzYKbHahkISd0UYyqLS9dI7xDlUOCA==} dependencies: '@babel/runtime': 7.21.0 - tslib: 2.5.0 + tslib: 2.5.1 dev: false /recorder-audio-worklet@5.1.39: @@ -7372,7 +7402,7 @@ packages: recorder-audio-worklet-processor: 4.2.21 standardized-audio-context: 25.3.45 subscribable-things: 2.1.14 - tslib: 2.5.0 + tslib: 2.5.1 worker-factory: 6.0.76 dev: false @@ -7513,11 +7543,11 @@ packages: resolution: {integrity: sha512-ASEq9atUw7lualXB+knvgtvwkCEvGWV2gDD/8qnASzBkzEARZck9JAyxmY8OS6Nc1pCPEgDTKNcx+YqqYfzArw==} dev: false - /rxjs@7.8.0: - resolution: {integrity: sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==} + /rxjs@7.8.1: + resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} requiresBuild: true dependencies: - tslib: 2.5.0 + tslib: 2.5.1 dev: false optional: true @@ -7755,7 +7785,7 @@ packages: dependencies: '@babel/runtime': 7.21.0 automation-events: 6.0.0 - tslib: 2.5.0 + tslib: 2.5.1 dev: false /std-env@3.3.3: @@ -7839,7 +7869,7 @@ packages: dependencies: '@babel/runtime': 7.21.0 rxjs-interop: 2.0.0 - tslib: 2.5.0 + tslib: 2.5.1 dev: false /sucrase@3.32.0: @@ -8314,6 +8344,11 @@ packages: /tinybench@2.4.0: resolution: {integrity: sha512-iyziEiyFxX4kyxSp+MtY1oCH/lvjH3PxFN8PGCDeqcZWAJ/i+9y+nL85w99PxVzrIvew/GSkSbDYtiGVa85Afg==} + dev: false + + /tinybench@2.5.0: + resolution: {integrity: sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==} + dev: true /tinypool@0.3.1: resolution: {integrity: sha512-zLA1ZXlstbU2rlpA4CIeVaqvWq41MTWqLY3FfsAXgC8+f7Pk7zroaJQxDgxn1xNudKW6Kmj4808rPFShUlIRmQ==} @@ -8420,6 +8455,10 @@ packages: /tslib@2.5.0: resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} + /tslib@2.5.1: + resolution: {integrity: sha512-KaI6gPil5m9vF7DKaoXxx1ia9fxS4qG5YveErRRVknPDXXriu5M8h48YRjB6h5ZUOKuAKlSJYb0GaDe8I39fRw==} + dev: false + /tsutils@3.21.0(typescript@5.0.3): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} @@ -8597,7 +8636,7 @@ packages: fast-json-patch: 3.1.1 json-stringify-pretty-compact: 3.0.0 semver: 7.4.0 - tslib: 2.5.0 + tslib: 2.5.1 vega: 5.22.1 vega-interpreter: 1.0.5 vega-lite: 0.6.7 @@ -8975,7 +9014,7 @@ packages: picocolors: 1.0.0 source-map: 0.6.1 source-map-support: 0.5.21 - vite: 4.3.1(@types/node@18.16.0)(sass@1.61.0) + vite: 4.3.8(@types/node@18.16.0)(sass@1.61.0) transitivePeerDependencies: - '@types/node' - less @@ -8996,7 +9035,7 @@ packages: mlly: 1.2.1 pathe: 1.1.0 picocolors: 1.0.0 - vite: 4.3.1(@types/node@18.16.0) + vite: 4.3.8(@types/node@18.16.0) transitivePeerDependencies: - '@types/node' - less @@ -9082,29 +9121,29 @@ packages: - supports-color dev: false - /vite-plugin-full-reload@1.0.5(vite@4.3.1): + /vite-plugin-full-reload@1.0.5(vite@4.3.8): resolution: {integrity: sha512-kVZFDFWr0DxiHn6MuDVTQf7gnWIdETGlZh0hvTiMXzRN80vgF4PKbONSq8U1d0WtHsKaFODTQgJeakLacoPZEQ==} peerDependencies: vite: ^2 || ^3 || ^4 dependencies: picocolors: 1.0.0 picomatch: 2.3.1 - vite: 4.3.1(sass@1.61.0) + vite: 4.3.8(sass@1.61.0) dev: false - /vite-plugin-glsl@1.1.2(vite@4.3.1): + /vite-plugin-glsl@1.1.2(vite@4.3.8): resolution: {integrity: sha512-zmXsfc1vn2MlYve9t3FAoWuhLyoCkNS1TuQL+TkXZL7tGmBjRErp10eNYxcse5tK9oUC5MyJpNc4ElpQnx8DoA==} engines: {node: '>= 16.15.1', npm: '>= 8.11.0'} peerDependencies: vite: ^3.0.0 || ^4.0.0 dependencies: '@rollup/pluginutils': 5.0.2 - vite: 4.3.1(sass@1.61.0) + vite: 4.3.8(sass@1.61.0) transitivePeerDependencies: - rollup dev: true - /vite-plugin-static-copy@0.14.0(vite@4.3.1): + /vite-plugin-static-copy@0.14.0(vite@4.3.8): resolution: {integrity: sha512-RMFmb4czomcrsbQBiUZs9HcDGN3kxGvF+OrtkfTVocp12CuoUCuJQhcY26RK35A6KS4WasGzEwcYZqHMjkAvVw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -9114,7 +9153,7 @@ packages: fast-glob: 3.2.12 fs-extra: 11.1.1 picocolors: 1.0.0 - vite: 4.3.1(sass@1.61.0) + vite: 4.3.8(sass@1.61.0) dev: true /vite-plugin-svelte-console-remover@1.0.10(sass@1.61.0): @@ -9130,7 +9169,7 @@ packages: - supports-color dev: true - /vite-tsconfig-paths@4.0.8(typescript@5.0.3)(vite@4.3.1): + /vite-tsconfig-paths@4.0.8(typescript@5.0.3)(vite@4.3.8): resolution: {integrity: sha512-p04zH+Ey+NT78571x0pdX7nVRIJSlmKVvYryFglSWOK3Hc72eDL0+JJfbyQiugaIBApJkaEqbBQvqpsFZOSVGg==} peerDependencies: vite: '*' @@ -9141,7 +9180,7 @@ packages: debug: 4.3.4 globrex: 0.1.2 tsconfck: 2.1.1(typescript@5.0.3) - vite: 4.3.1(sass@1.61.0) + vite: 4.3.8(sass@1.61.0) transitivePeerDependencies: - supports-color - typescript @@ -9293,8 +9332,8 @@ packages: fsevents: 2.3.2 dev: false - /vite@4.3.1(@types/node@18.16.0)(sass@1.61.0): - resolution: {integrity: sha512-EPmfPLAI79Z/RofuMvkIS0Yr091T2ReUoXQqc5ppBX/sjFRhHKiPPF/R46cTdoci/XgeQpB23diiJxq5w30vdg==} + /vite@4.3.8(@types/node@18.16.0): + resolution: {integrity: sha512-uYB8PwN7hbMrf4j1xzGDk/lqjsZvCDbt/JC5dyfxc19Pg8kRm14LinK/uq+HSLNswZEoKmweGdtpbnxRtrAXiQ==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true peerDependencies: @@ -9320,15 +9359,48 @@ packages: dependencies: '@types/node': 18.16.0 esbuild: 0.17.18 - postcss: 8.4.21 + postcss: 8.4.23 + rollup: 3.21.0 + optionalDependencies: + fsevents: 2.3.2 + dev: false + + /vite@4.3.8(@types/node@18.16.0)(sass@1.61.0): + resolution: {integrity: sha512-uYB8PwN7hbMrf4j1xzGDk/lqjsZvCDbt/JC5dyfxc19Pg8kRm14LinK/uq+HSLNswZEoKmweGdtpbnxRtrAXiQ==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 18.16.0 + esbuild: 0.17.18 + postcss: 8.4.23 rollup: 3.21.0 sass: 1.61.0 optionalDependencies: fsevents: 2.3.2 dev: true - /vite@4.3.1(sass@1.61.0): - resolution: {integrity: sha512-EPmfPLAI79Z/RofuMvkIS0Yr091T2ReUoXQqc5ppBX/sjFRhHKiPPF/R46cTdoci/XgeQpB23diiJxq5w30vdg==} + /vite@4.3.8(sass@1.61.0): + resolution: {integrity: sha512-uYB8PwN7hbMrf4j1xzGDk/lqjsZvCDbt/JC5dyfxc19Pg8kRm14LinK/uq+HSLNswZEoKmweGdtpbnxRtrAXiQ==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true peerDependencies: @@ -9353,7 +9425,7 @@ packages: optional: true dependencies: esbuild: 0.17.18 - postcss: 8.4.21 + postcss: 8.4.23 rollup: 3.21.0 sass: 1.61.0 optionalDependencies: @@ -9368,7 +9440,7 @@ packages: optional: true dev: true - /vitefu@0.2.4(vite@4.3.1): + /vitefu@0.2.4(vite@4.3.8): resolution: {integrity: sha512-fanAXjSaf9xXtOOeno8wZXIhgia+CZury481LsDaV++lSvcU2R9Ch2bPh3PYFyoHW+w9LqAeYRISVQjUIew14g==} peerDependencies: vite: ^3.0.0 || ^4.0.0 @@ -9376,7 +9448,7 @@ packages: vite: optional: true dependencies: - vite: 4.3.1(sass@1.61.0) + vite: 4.3.8(sass@1.61.0) dev: false /vitest@0.27.3(happy-dom@9.18.3)(jsdom@22.0.0)(sass@1.61.0): @@ -9401,7 +9473,7 @@ packages: jsdom: optional: true dependencies: - '@types/chai': 4.3.4 + '@types/chai': 4.3.5 '@types/chai-subset': 1.3.3 '@types/node': 18.16.0 acorn: 8.8.2 @@ -9416,10 +9488,10 @@ packages: source-map: 0.6.1 std-env: 3.3.3 strip-literal: 1.0.1 - tinybench: 2.4.0 + tinybench: 2.5.0 tinypool: 0.3.1 tinyspy: 1.1.1 - vite: 4.3.1(@types/node@18.16.0)(sass@1.61.0) + vite: 4.3.8(@types/node@18.16.0)(sass@1.61.0) vite-node: 0.27.3(@types/node@18.16.0)(sass@1.61.0) why-is-node-running: 2.2.2 transitivePeerDependencies: @@ -9625,7 +9697,7 @@ packages: '@babel/runtime': 7.21.0 compilerr: 10.0.2 fast-unique-numbers: 7.0.2 - tslib: 2.5.0 + tslib: 2.5.1 dev: false /worker-factory@7.0.0: @@ -9634,7 +9706,7 @@ packages: '@babel/runtime': 7.21.0 compilerr: 11.0.0 fast-unique-numbers: 8.0.0 - tslib: 2.5.0 + tslib: 2.5.1 dev: false /wrap-ansi@7.0.0: @@ -9752,10 +9824,14 @@ packages: commander: 9.5.0 dev: false + /zod@3.21.4: + resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==} + dev: false + github.com/andywer/typed-emitter/9a139b6fa0ec6b0db6141b5b756b784e4f7ef4e4: resolution: {tarball: https://codeload.github.com/andywer/typed-emitter/tar.gz/9a139b6fa0ec6b0db6141b5b756b784e4f7ef4e4} name: typed-emitter version: 2.1.0 optionalDependencies: - rxjs: 7.8.0 + rxjs: 7.8.1 dev: false diff --git a/src/lib/ComfyBoxStdPrompt.ts b/src/lib/ComfyBoxStdPrompt.ts new file mode 100644 index 0000000..61833a0 --- /dev/null +++ b/src/lib/ComfyBoxStdPrompt.ts @@ -0,0 +1,263 @@ +import { z, type ZodTypeAny } from "zod" + +/* + * This metadata can be attached to each entry in a group to assist in + * identifying the correct nodes to apply it to. + * + * As an example, positive and negative conditioning are deployed as two + * separate nodes in ComfyUI. This makes bundling them into a { positive, + * negative } entry difficult as either one can be missing. So instead they're + * tagged like + * + * { + * conditioning: [ + * { text: "masterpiece", "$meta": { types: ["positive"] } }, + * { text: "worst quality", "$meta": { types: ["negative"] } }, + * ] + * } + * + * The reasoning is the "types" information isn't required to reinstantiate + * the node, it's only semantic information describing how the node is used in + * the encompassing workflow. When the prompt is loaded the workflow can be + * searched for a node with the compatible type to attach the information to. + */ +const GroupMetadata = z.object({ + types: z.array(z.string()).nonempty().optional() +}) +export type ComfyBoxStdGroupMetadata = z.infer + +const group = (obj: Record): ZodTypeAny => { + const meta = z.object({ "$meta": GroupMetadata.optional() }) + return z.object(obj).and(meta) +} + +const ModelHashes = z.object({ + a1111_shorthash: z.string().optional(), + sha256: z.string().optional(), +}).refine(({ a1111_shorthash, sha256 }) => + a1111_shorthash !== undefined || sha256 !== undefined, + { message: "At least one model hash must be specified" }) + +const GroupConditioning = group({ + text: z.string(), +}) +export type ComfyBoxStdGroupConditioning = z.infer + +const GroupCheckpoint = group({ + model_name: z.string().optional(), + model_hashes: ModelHashes.optional(), +}).refine(({ model_name, model_hashes }) => + model_name !== undefined || model_hashes !== undefined, + { message: "Must include either model name or model hash" } +) +export type ComfyBoxStdGroupCheckpoint = z.infer + +const GroupVAE = group({ + model_name: z.string().optional(), + model_hashes: ModelHashes.optional(), + type: z.enum(["internal", "external"]) +}).refine(({ model_name, model_hashes }) => + model_name !== undefined || model_hashes !== undefined, + { message: "Must include either model name or model hashes" } +) +export type ComfyBoxStdGroupVAE = z.infer + +const GroupKSampler = group({ + cfg_scale: z.number(), + seed: z.number(), + steps: z.number(), + sampler_name: z.string(), + scheduler: z.string(), + denoise: z.number().default(1.0), + type: z.enum(["empty", "image", "upscale"]).optional() +}) +export type ComfyBoxStdGroupKSampler = z.infer + +const GroupLatentImage = group({ + width: z.number(), + height: z.number(), + mask_blur: z.number().optional(), + batch_count: z.number().default(1).optional(), + batch_pos: z.number().default(0).optional() +}) +export type ComfyBoxStdGroupLatentImage = z.infer + +const GroupLatentUpscale = group({ + width: z.number(), + height: z.number(), + upscale_method: z.string().optional(), + upscale_by: z.number().optional(), + crop: z.string().optional() +}) +export type ComfyBoxStdGroupLatentUpscale = z.infer + +const GroupSDUpscale = group({ + upscaler: z.string(), + overlap: z.number(), +}) +export type ComfyBoxStdGroupSDUpscale = z.infer + +const GroupSelfAttentionGuidance = group({ + guidance_scale: z.number(), + mask_threshold: z.number(), +}) +export type ComfyBoxStdGroupSelfAttentionGuidance = z.infer + +const GroupHypernetwork = group({ + model_name: z.string(), + model_hashes: ModelHashes.optional(), + strength: z.number() +}) +export type ComfyBoxStdGroupHypernetwork = z.infer + +const LoRAModelHashes = z.object({ + addnet_shorthash: z.string().optional(), + addnet_shorthash_legacy: z.string().optional(), + sha256: z.string().optional(), +}).refine(({ addnet_shorthash, addnet_shorthash_legacy, sha256 }) => + addnet_shorthash !== undefined || addnet_shorthash_legacy !== undefined || sha256 !== undefined, + { message: "At least one model hash must be specified" }) + +const GroupLoRA = group({ + model_name: z.string(), + module_name: z.string().optional(), + model_hashes: LoRAModelHashes.optional(), + strength_unet: z.number(), + strength_tenc: z.number() +}) +export type ComfyBoxStdGroupLoRA = z.infer + +const GroupControlNet = group({ + model: z.string(), + model_hashes: ModelHashes.optional(), + strength: z.number(), +}) +export type ComfyBoxStdGroupControlNet = z.infer + +const GroupCLIP = group({ + clip_skip: z.number().optional() +}) +export type ComfyBoxStdGroupCLIP = z.infer + +const GroupDynamicThresholding = group({ + mimic_scale: z.number(), + threshold_percentile: z.number(), + mimic_mode: z.string(), + mimic_scale_minimum: z.number(), + cfg_mode: z.string(), + cfg_scale_minimum: z.number() +}) +export type ComfyBoxStdGroupDynamicThresholding = z.infer + +const GroupAestheticEmbedding = group({ + model_name: z.string(), + lr: z.number(), + slerp: z.boolean(), + slerp_angle: z.number().optional(), + steps: z.number(), + text: z.string(), + text_negative: z.boolean(), + weight: z.number(), +}) +export type ComfyBoxStdGroupAestheticEmbedding = z.infer + +const GroupDDetailer = group({ + positive_prompt: z.string(), + negative_prompt: z.string(), + bitwise: z.string(), + model: z.string().optional(), + model_hashes: ModelHashes.optional(), + conf: z.number(), + mask_blur: z.number(), + denoise: z.number(), + dilation: z.number(), + offset_x: z.number(), + offset_y: z.number(), + preprocess: z.boolean(), + inpaint_full: z.boolean(), + inpaint_padding: z.number(), + cfg: z.number() +}) +export type ComfyBoxStdGroupDDetailer = z.infer + +const groupArray = (entry: ZodTypeAny) => { + return z.optional(z.array(entry).nonempty()); +} + +const Parameters = z.object({ + conditioning: groupArray(GroupConditioning), + checkpoint: groupArray(GroupCheckpoint), + vae: groupArray(GroupVAE), + k_sampler: groupArray(GroupKSampler), + clip: groupArray(GroupCLIP), + latent_image: groupArray(GroupLatentImage), + latent_upscale: groupArray(GroupLatentUpscale), + sd_upscale: groupArray(GroupSDUpscale), + hypernetwork: groupArray(GroupHypernetwork), + lora: groupArray(GroupLoRA), + control_net: groupArray(GroupControlNet), + dynamic_thresholding: groupArray(GroupDynamicThresholding), + aesthetic_embedding: groupArray(GroupAestheticEmbedding), + self_attention_guidance: groupArray(GroupSelfAttentionGuidance), + ddetailer: groupArray(GroupDDetailer) +}).partial() +export type ComfyBoxStdParameters = z.infer + +const ComfyBoxExtraData = z.object({ + workflows: z.array(z.string()) +}) + +const A1111ExtraData = z.object({ + params: z.any() +}) + +const ExtraData = z.object({ + comfybox: ComfyBoxExtraData.optional(), + a1111: A1111ExtraData.optional() +}) + +const Metadata = z.object({ + created_with: z.string(), + author: z.string().optional(), + app_version: z.string().optional(), + commit_hash: z.string().optional(), + extra_data: ExtraData +}) + +const ComfyBoxStdPrompt = z.object({ + version: z.number(), + metadata: Metadata, + parameters: Parameters +}) + +export default ComfyBoxStdPrompt + +/* + * A standardized Stable Diffusion parameter format that should be used with an + * encompassing workflow. Aims to encompass an arbitrary number of parameter + * counts and types, so that most ComfyUI workflows can have parts of their + * prompts transferred between each other. + * + * This format does *not* describe how the information should be used in the + * underlying workflow, i.e. it does not specify the structure of a ComfyUI + * execution graph. It only gives hints via tagged input types on each input + * entry as to where the data should be inserted. To recreate a ComfyBox + * workflow with the exact state of the UI intact, the `SerializedAppState` type + * should be used instead. It suffices to embed data of that type in the output + * PNGs for recreating their workflows. This type is meant as an interchange + * format *between* workflows so their inputs can be copied to and from each + * other in a sane-enough manner. (In ComfyBox, copying workflow outputs like + * images to other workflows is handled separately, since this type does not + * retain the actual image data.) + * + * In contrast with a serialized workflow, which is concerned with the + * connections between nodes and the state of the frontend's UI, this format + * concerns itself with the exact values that the execution backend receives, + * after the data in the UI have finished processing. + * + * (Take for example a "scale by" slider that adjusts the width and height of an + * img2img input image of 512 x 512 resolution by 2x. The backend will only + * "see" width 1024 and height 1024, even though the only parameter exposed from + * the frontend was the scale of 2.) + */ +export type ComfyBoxStdPrompt = z.infer diff --git a/src/lib/ComfyBoxStdPromptSerializer.ts b/src/lib/ComfyBoxStdPromptSerializer.ts new file mode 100644 index 0000000..86f9714 --- /dev/null +++ b/src/lib/ComfyBoxStdPromptSerializer.ts @@ -0,0 +1,55 @@ +import type { ComfyBoxStdGroupLoRA, ComfyBoxStdPrompt } from "$lib/ComfyBoxStdPrompt"; +import type { SerializedPrompt, SerializedPromptInputs } from "./components/ComfyApp"; + +export type ComfyPromptConverter = (stdPrompt: ComfyBoxStdPrompt, inputs: SerializedPromptInputs, nodeID: ComfyNodeID) => void; + +function LoraLoader(stdPrompt: ComfyBoxStdPrompt, inputs: SerializedPromptInputs) { + const params = stdPrompt.parameters + + const lora: ComfyBoxStdGroupLoRA = { + model_name: inputs["lora_name"], + strength_unet: inputs["strength_model"], + strength_tenc: inputs["strength_clip"] + } + + if (params.lora) + params.lora.push(lora) + else + params.lora = [lora] +} + +const ALL_CONVERTERS: Record = { + LoraLoader +} + +const COMMIT_HASH: string = __GIT_COMMIT_HASH__; + +export default class ComfyBoxStdPromptSerializer { + serialize(prompt: SerializedPrompt): ComfyBoxStdPrompt { + const stdPrompt: ComfyBoxStdPrompt = { + version: 1, + metadata: { + created_with: "ComfyBox", + commit_hash: COMMIT_HASH, + extra_data: { + comfybox: { + } + } + }, + parameters: {} + } + + for (const [nodeID, inputs] of Object.entries(prompt.output)) { + const classType = inputs.class_type + const converter = ALL_CONVERTERS[classType] + if (converter) { + converter(stdPrompt, inputs.inputs, nodeID) + } + else { + console.warn("No StdPrompt type converter for comfy class!", classType) + } + } + + return stdPrompt + } +} diff --git a/src/lib/ComfyGraphCanvas.ts b/src/lib/ComfyGraphCanvas.ts index 02c12d9..f09953e 100644 --- a/src/lib/ComfyGraphCanvas.ts +++ b/src/lib/ComfyGraphCanvas.ts @@ -98,7 +98,7 @@ export default class ComfyGraphCanvas extends LGraphCanvas { } if (color) { - this.drawNodeOutline(node, ctx, size, fgColor, bgColor, color, thickness) + this.drawNodeOutline(node, ctx, size, mouseOver, fgColor, bgColor, color, thickness) } if (isRunningNode && state.progress) { @@ -108,27 +108,36 @@ export default class ComfyGraphCanvas extends LGraphCanvas { } } - private drawNodeOutline(node: LGraphNode, ctx: CanvasRenderingContext2D, size: Vector2, fgColor: string, bgColor: string, outlineColor: string, outlineThickness: number) { + private drawNodeOutline(node: LGraphNode, ctx: CanvasRenderingContext2D, size: Vector2, mouseOver: boolean, fgColor: string, bgColor: string, outlineColor: string, outlineThickness: number) { const shape = node.shape || BuiltInSlotShape.ROUND_SHAPE; + + var render_title = true; + if (node.titleMode == TitleMode.TRANSPARENT_TITLE || node.titleMode == TitleMode.NO_TITLE) { + render_title = false; + } else if (node.titleMode == TitleMode.AUTOHIDE_TITLE && mouseOver) { + render_title = true; + } + const titleHeight = render_title ? LiteGraph.NODE_TITLE_HEIGHT : 0; + ctx.lineWidth = outlineThickness; ctx.globalAlpha = 0.8; ctx.beginPath(); if (shape == BuiltInSlotShape.BOX_SHAPE) - ctx.rect(-6, -6 + LiteGraph.NODE_TITLE_HEIGHT, 12 + size[0] + 1, 12 + size[1] + LiteGraph.NODE_TITLE_HEIGHT); + ctx.rect(-6, -6 + titleHeight, 12 + size[0] + 1, 12 + size[1] + titleHeight); else if (shape == BuiltInSlotShape.ROUND_SHAPE || (shape == BuiltInSlotShape.CARD_SHAPE && node.flags.collapsed)) ctx.roundRect( -6, - -6 - LiteGraph.NODE_TITLE_HEIGHT, + -6 - titleHeight, 12 + size[0] + 1, - 12 + size[1] + LiteGraph.NODE_TITLE_HEIGHT, + 12 + size[1] + titleHeight, this.round_radius * 2 ); else if (shape == BuiltInSlotShape.CARD_SHAPE) ctx.roundRect( -6, - -6 + LiteGraph.NODE_TITLE_HEIGHT, + -6 + titleHeight, 12 + size[0] + 1, - 12 + size[1] + LiteGraph.NODE_TITLE_HEIGHT, + 12 + size[1] + titleHeight, this.round_radius * 2, 2 ); diff --git a/src/lib/api.ts b/src/lib/api.ts index 8e5097c..78ea676 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -1,4 +1,4 @@ -import type { Progress, SerializedPrompt, SerializedPromptInputs, SerializedPromptInputsAll, SerializedPromptOutputs } from "./components/ComfyApp"; +import type { Progress, SerializedPrompt, SerializedPromptInputsForNode, SerializedPromptInputsAll, SerializedPromptOutputs } from "./components/ComfyApp"; import type TypedEmitter from "typed-emitter"; import EventEmitter from "events"; import type { ComfyImageLocation } from "$lib/utils"; diff --git a/src/lib/components/A1111PromptDisplay.svelte b/src/lib/components/A1111PromptDisplay.svelte new file mode 100644 index 0000000..134ff5b --- /dev/null +++ b/src/lib/components/A1111PromptDisplay.svelte @@ -0,0 +1,114 @@ + + +{#if prompt != null} +
+
+ + + +
+ {#if a1111} + {#if Object.keys(a1111.extraParams).length > 0} + + Unused Parameters +
+ +
+
+ {/if} + {/if} + + Converted Prompt +
+ +
+
+
+
+ + + +
+{/if} + + diff --git a/src/lib/components/AccordionContainer.svelte b/src/lib/components/AccordionContainer.svelte index ca86d8f..279aafe 100644 --- a/src/lib/components/AccordionContainer.svelte +++ b/src/lib/components/AccordionContainer.svelte @@ -25,7 +25,7 @@ export let isMobile: boolean = false; let isOpen: Writable | null = null; - let children: IDragItem[] | null = null; + let children: IDragItem[] = []; const flipDurationMs = 100; let selectedIndex: number = 0; @@ -61,7 +61,7 @@ } -{#if container && Array.isArray(children)} +{#if container} {@const selected = $uiState.uiUnlocked && $selectionState.currentSelection.includes(container.id)}
| null = null; - let children: IDragItem[] | null = null; + let children: IDragItem[] = []; const flipDurationMs = 100; $: if (container) { @@ -35,12 +35,12 @@ } else { container = null; - children = null; + children = []; attrsChanged = null; } } else { - children = null; + children = []; attrsChanged = null } @@ -55,7 +55,7 @@ }; -{#if container && Array.isArray(children)} +{#if container} {@const selected = $uiState.uiUnlocked && $selectionState.currentSelection.includes(container.id)}
= writable(false); + let a1111Prompt: Writable = writable(null); let mainElem: HTMLDivElement; - let uiPane: ComfyUIPane = undefined; let props: ComfyProperties = undefined; let containerElem: HTMLDivElement; let resizeTimeout: NodeJS.Timeout | null; @@ -44,6 +47,11 @@ } } + $: if(app) { + alreadySetup = app.alreadySetup; + a1111Prompt = app.a1111Prompt; + } + function refreshView(event?: Event) { clearTimeout(resizeTimeout); resizeTimeout = setTimeout(app.resizeCanvas.bind(app), 250); @@ -188,6 +196,10 @@ else { document.getElementById("app-root").classList.remove("dark") } + + let showModal: boolean = false; + + $: showModal = $a1111Prompt != null @@ -196,8 +208,19 @@ {/if} + ($a1111Prompt = null)}> +
+

A1111 Prompt Details

+
+ +
+ +
+
+
-
@@ -208,7 +231,7 @@ - + @@ -217,7 +240,7 @@ @@ -225,35 +248,35 @@
{#if $layoutState.attrs.queuePromptButtonName != ""} - {/if} - - - - - - - - -