diff --git a/package-lock.json b/package-lock.json index 411c0fbd..3762235f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,8 +16,8 @@ "@ai-sdk/openai": "^3.0.49", "@ai-sdk/openai-compatible": "^2.0.49", "@anthropic-ai/sdk": "^0.60.0", - "@aws-sdk/client-s3": "^3.846.0", - "@aws-sdk/s3-request-presigner": "^3.846.0", + "@aws-sdk/client-s3": "3.1138.0", + "@aws-sdk/s3-request-presigner": "3.1138.0", "@azure/storage-blob": "^12.27.0", "@electron/notarize": "^2.3.2", "@emotion/react": "^11.14.0", @@ -75,7 +75,7 @@ "rehype-sanitize": "^6.0.0", "remark-gfm": "^4.0.1", "simple-git": "^3.27.0", - "snowflake-sdk": "^2.0.3", + "snowflake-sdk": "^3.3.0", "split-pane-react": "^0.1.3", "tar": "^7.4.3", "uuid": "^11.1.0", @@ -411,10 +411,10 @@ "anthropic-ai-sdk": "bin/cli" } }, - "node_modules/@aws-crypto/crc32": { + "node_modules/@aws-crypto/sha256-js": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", - "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/util": "^5.2.0", @@ -425,31 +425,17 @@ "node": ">=16.0.0" } }, - "node_modules/@aws-crypto/crc32c": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", - "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/util": "^5.2.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@aws-crypto/sha1-browser": { + "node_modules/@aws-crypto/util": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz", - "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", "dependencies": { - "@aws-crypto/supports-web-crypto": "^5.2.0", - "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-locate-window": "^3.0.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, - "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/is-array-buffer": { + "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", @@ -460,7 +446,7 @@ "node": ">=14.0.0" } }, - "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-buffer-from": { + "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", @@ -472,7 +458,7 @@ "node": ">=14.0.0" } }, - "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-utf8": { + "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", @@ -484,1223 +470,1035 @@ "node": ">=14.0.0" } }, - "node_modules/@aws-crypto/sha256-browser": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", - "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "node_modules/@aws-sdk/checksums": { + "version": "3.1001.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/checksums/-/checksums-3.1001.1.tgz", + "integrity": "sha512-x12Q17KYlJAd3nKf8LV5LV0vt8sh8/6YfQLGPtrGnQf/tW4jqxPGq5GPpuVitpQYM3eUR4XB7CbxZf751NMbLw==", "license": "Apache-2.0", "dependencies": { - "@aws-crypto/sha256-js": "^5.2.0", - "@aws-crypto/supports-web-crypto": "^5.2.0", - "@aws-crypto/util": "^5.2.0", - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-locate-window": "^3.0.0", - "@smithy/util-utf8": "^2.0.0", + "@aws-sdk/core": "^3.978.1", + "@aws-sdk/types": "^3.974.6", + "@smithy/core": "^3.35.0", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", - "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "node_modules/@aws-sdk/client-s3": { + "version": "3.1138.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.1138.0.tgz", + "integrity": "sha512-U7+dA10/2mk9PCoZ4JknQhGaw0atZfEtxMHT+vRGFS8z7fO8bb+Grvq5B4XkiL5epyrWImv8KwLclYWMq/4znA==", "license": "Apache-2.0", "dependencies": { + "@aws-sdk/checksums": "^3.1001.1", + "@aws-sdk/core": "^3.978.1", + "@aws-sdk/credential-provider-node": "^3.972.84", + "@aws-sdk/middleware-sdk-s3": "^3.972.77", + "@aws-sdk/signature-v4-multi-region": "^3.996.47", + "@aws-sdk/types": "^3.974.6", + "@smithy/core": "^3.35.0", + "@smithy/fetch-http-handler": "^5.8.0", + "@smithy/node-http-handler": "^4.12.1", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", - "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.972.77", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.77.tgz", + "integrity": "sha512-E7W2UOeUoc+lg3uIfR/dM7ZwusHwhBQrKMnlkRv4EXRR+C0YtV1pg25xC7GdZIhXH+NAMgZPCbE7o5to2cjFiw==", "license": "Apache-2.0", "dependencies": { - "@smithy/is-array-buffer": "^2.2.0", + "@aws-sdk/core": "^3.978.1", + "@aws-sdk/signature-v4-multi-region": "^3.996.47", + "@aws-sdk/types": "^3.974.6", + "@smithy/core": "^3.35.0", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", - "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "node_modules/@aws-sdk/client-sts": { + "version": "3.1138.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.1138.0.tgz", + "integrity": "sha512-bgLbxtF/GBSTDJtl+WweClwoQkNd9TxmoGikHCs+c16rvvCs0sFOsmEZ0AT5DLIxGvRZOO/NT9d3FBQNsIs9cg==", "license": "Apache-2.0", "dependencies": { - "@smithy/util-buffer-from": "^2.2.0", + "@aws-sdk/core": "^3.978.1", + "@aws-sdk/credential-provider-node": "^3.972.84", + "@aws-sdk/signature-v4-multi-region": "^3.996.47", + "@aws-sdk/types": "^3.974.6", + "@smithy/core": "^3.35.0", + "@smithy/fetch-http-handler": "^5.8.0", + "@smithy/node-http-handler": "^4.12.1", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-crypto/sha256-js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", - "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "node_modules/@aws-sdk/core": { + "version": "3.978.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.978.1.tgz", + "integrity": "sha512-LbY9aGsEiznDWmUc30Nwv3aIX/+dbwTx8KfS0yOC3NPYMO+O91e6jkT1azf34FwjOndq8/Q+RcVVZz5xnerwdg==", "license": "Apache-2.0", "dependencies": { - "@aws-crypto/util": "^5.2.0", - "@aws-sdk/types": "^3.222.0", + "@aws-sdk/types": "^3.974.6", + "@aws-sdk/xml-builder": "^3.972.41", + "@aws/lambda-invoke-store": "^0.3.0", + "@smithy/core": "^3.35.0", + "@smithy/signature-v4": "^5.7.3", + "@smithy/types": "^4.19.0", + "bowser": "^2.11.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-crypto/supports-web-crypto": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", - "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.972.72", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.72.tgz", + "integrity": "sha512-xTKO/FWJPozTIXbozVnVGoNBhaGba8TBcx+KyUjRVeOlXE+dUc7GTR1cLvu0uTdIdmemzaFbqqCshXeZA1fZew==", + "license": "Apache-2.0", "dependencies": { + "@aws-sdk/core": "^3.978.1", + "@aws-sdk/types": "^3.974.6", + "@smithy/core": "^3.35.0", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@aws-crypto/util": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", - "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.972.74", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.74.tgz", + "integrity": "sha512-u91E/hT8f4d1xy0Jl7VG4nVKJ3lxbrZkoBTeSVoJdWBiSEUMwMS/9+e0H/aJVQV//Lt5wuzP+E69v4aRSsNTmw==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.222.0", - "@smithy/util-utf8": "^2.0.0", + "@aws-sdk/core": "^3.978.1", + "@aws-sdk/types": "^3.974.6", + "@smithy/core": "^3.35.0", + "@smithy/fetch-http-handler": "^5.8.0", + "@smithy/node-http-handler": "^4.12.1", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", - "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.973.17", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.973.17.tgz", + "integrity": "sha512-ged4KXdBkvIC81bLvNHHuQKdKak/VXhQTR1NWYTTqW0474nlmsxy9O/vlgTIohDDWH3xpBdtVMZRyjb+DnocDA==", + "license": "Apache-2.0", "dependencies": { + "@aws-sdk/core": "^3.978.1", + "@aws-sdk/credential-provider-env": "^3.972.72", + "@aws-sdk/credential-provider-http": "^3.972.74", + "@aws-sdk/credential-provider-login": "^3.972.79", + "@aws-sdk/credential-provider-process": "^3.972.72", + "@aws-sdk/credential-provider-sso": "^3.973.16", + "@aws-sdk/credential-provider-web-identity": "^3.972.78", + "@aws-sdk/nested-clients": "^3.997.46", + "@aws-sdk/types": "^3.974.6", + "@smithy/core": "^3.35.0", + "@smithy/credential-provider-imds": "^4.5.2", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", - "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "node_modules/@aws-sdk/credential-provider-login": { + "version": "3.972.79", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.79.tgz", + "integrity": "sha512-L+Z85anONJd8MaiuraO4wRxATCdEejBZ3K3eymzWI5JPXa9sOS9CkIm72PBKqXKX+Z9p9NGMX5AIMXm0LEflgw==", + "license": "Apache-2.0", "dependencies": { - "@smithy/is-array-buffer": "^2.2.0", + "@aws-sdk/core": "^3.978.1", + "@aws-sdk/nested-clients": "^3.997.46", + "@aws-sdk/types": "^3.974.6", + "@smithy/core": "^3.35.0", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", - "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.972.84", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.84.tgz", + "integrity": "sha512-oHt854odINVwzwsh+c5x69j0ajm4DbqqqVJ+O1ECsCIZeMDAbzFpXItaqP7UZstJj/ATdTk/KFSH0LaNAgV+kA==", + "license": "Apache-2.0", "dependencies": { - "@smithy/util-buffer-from": "^2.2.0", + "@aws-sdk/credential-provider-env": "^3.972.72", + "@aws-sdk/credential-provider-http": "^3.972.74", + "@aws-sdk/credential-provider-ini": "^3.973.17", + "@aws-sdk/credential-provider-process": "^3.972.72", + "@aws-sdk/credential-provider-sso": "^3.973.16", + "@aws-sdk/credential-provider-web-identity": "^3.972.78", + "@aws-sdk/types": "^3.974.6", + "@smithy/core": "^3.35.0", + "@smithy/credential-provider-imds": "^4.5.2", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/client-s3": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.846.0.tgz", - "integrity": "sha512-+C9qRJ7SFN+Bi2DJqfJ73Aj4ORpic9Jk5boosiOZj+TZi6qYHW6TCUqxheiC6JT/0xtE5C7VFIhW/UP/CAh0Tw==", + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.972.72", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.72.tgz", + "integrity": "sha512-rLIp2xbMjX/k9/od7APpqq1ZgXXnV0pOL1Th3ZsL8Wu0TRtBsDTVS8iPqcfRFcHakFxPvR04OSTv2ka2qOb/2A==", "license": "Apache-2.0", "dependencies": { - "@aws-crypto/sha1-browser": "5.2.0", - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.846.0", - "@aws-sdk/credential-provider-node": "3.846.0", - "@aws-sdk/middleware-bucket-endpoint": "3.840.0", - "@aws-sdk/middleware-expect-continue": "3.840.0", - "@aws-sdk/middleware-flexible-checksums": "3.846.0", - "@aws-sdk/middleware-host-header": "3.840.0", - "@aws-sdk/middleware-location-constraint": "3.840.0", - "@aws-sdk/middleware-logger": "3.840.0", - "@aws-sdk/middleware-recursion-detection": "3.840.0", - "@aws-sdk/middleware-sdk-s3": "3.846.0", - "@aws-sdk/middleware-ssec": "3.840.0", - "@aws-sdk/middleware-user-agent": "3.846.0", - "@aws-sdk/region-config-resolver": "3.840.0", - "@aws-sdk/signature-v4-multi-region": "3.846.0", - "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.845.0", - "@aws-sdk/util-user-agent-browser": "3.840.0", - "@aws-sdk/util-user-agent-node": "3.846.0", - "@aws-sdk/xml-builder": "3.821.0", - "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.7.0", - "@smithy/eventstream-serde-browser": "^4.0.4", - "@smithy/eventstream-serde-config-resolver": "^4.1.2", - "@smithy/eventstream-serde-node": "^4.0.4", - "@smithy/fetch-http-handler": "^5.1.0", - "@smithy/hash-blob-browser": "^4.0.4", - "@smithy/hash-node": "^4.0.4", - "@smithy/hash-stream-node": "^4.0.4", - "@smithy/invalid-dependency": "^4.0.4", - "@smithy/md5-js": "^4.0.4", - "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.15", - "@smithy/middleware-retry": "^4.1.16", - "@smithy/middleware-serde": "^4.0.8", - "@smithy/middleware-stack": "^4.0.4", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.1.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.7", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.23", - "@smithy/util-defaults-mode-node": "^4.0.23", - "@smithy/util-endpoints": "^3.0.6", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-retry": "^4.0.6", - "@smithy/util-stream": "^4.2.3", - "@smithy/util-utf8": "^4.0.0", - "@smithy/util-waiter": "^4.0.6", - "@types/uuid": "^9.0.1", - "tslib": "^2.6.2", - "uuid": "^9.0.1" + "@aws-sdk/core": "^3.978.1", + "@aws-sdk/types": "^3.974.6", + "@smithy/core": "^3.35.0", + "@smithy/types": "^4.19.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-s3/node_modules/@types/uuid": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", - "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", - "license": "MIT" - }, - "node_modules/@aws-sdk/client-s3/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" + "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/client-sso": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.846.0.tgz", - "integrity": "sha512-7MgMl3nlwf2ixad5Xe8pFHtcwFchkx37MEvGuB00tn5jyBp3AQQ4dK3iHtj2HjhXcXD0G67zVPvH4/QNOL7/gw==", + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.973.16", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.973.16.tgz", + "integrity": "sha512-IGihaJfFZYacJJr/odqILCoK7W/mvrZ7cuK7ECn3sAu4vLC6u0V8bS7mCGbdugJ8Aum2tnvqmx0F2MRFp2rn9g==", "license": "Apache-2.0", "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.846.0", - "@aws-sdk/middleware-host-header": "3.840.0", - "@aws-sdk/middleware-logger": "3.840.0", - "@aws-sdk/middleware-recursion-detection": "3.840.0", - "@aws-sdk/middleware-user-agent": "3.846.0", - "@aws-sdk/region-config-resolver": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.845.0", - "@aws-sdk/util-user-agent-browser": "3.840.0", - "@aws-sdk/util-user-agent-node": "3.846.0", - "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.7.0", - "@smithy/fetch-http-handler": "^5.1.0", - "@smithy/hash-node": "^4.0.4", - "@smithy/invalid-dependency": "^4.0.4", - "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.15", - "@smithy/middleware-retry": "^4.1.16", - "@smithy/middleware-serde": "^4.0.8", - "@smithy/middleware-stack": "^4.0.4", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.1.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.7", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.23", - "@smithy/util-defaults-mode-node": "^4.0.23", - "@smithy/util-endpoints": "^3.0.6", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-retry": "^4.0.6", - "@smithy/util-utf8": "^4.0.0", + "@aws-sdk/core": "^3.978.1", + "@aws-sdk/nested-clients": "^3.997.46", + "@aws-sdk/token-providers": "3.1138.0", + "@aws-sdk/types": "^3.974.6", + "@smithy/core": "^3.35.0", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/core": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.846.0.tgz", - "integrity": "sha512-7CX0pM906r4WSS68fCTNMTtBCSkTtf3Wggssmx13gD40gcWEZXsU00KzPp1bYheNRyPlAq3rE22xt4wLPXbuxA==", + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.972.78", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.78.tgz", + "integrity": "sha512-/y9WvNtlcPBGLR0qc1a+9J/xtYZfVczvLUOuXaVWylzttH7ewsxwHtjmiJSolNrVSDorIxHGHMU61CbonRkmwA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@aws-sdk/xml-builder": "3.821.0", - "@smithy/core": "^3.7.0", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/property-provider": "^4.0.4", - "@smithy/protocol-http": "^5.1.2", - "@smithy/signature-v4": "^5.1.2", - "@smithy/smithy-client": "^4.4.7", - "@smithy/types": "^4.3.1", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-utf8": "^4.0.0", - "fast-xml-parser": "5.2.5", + "@aws-sdk/core": "^3.978.1", + "@aws-sdk/nested-clients": "^3.997.46", + "@aws-sdk/types": "^3.974.6", + "@smithy/core": "^3.35.0", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/core/node_modules/fast-xml-parser": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz", - "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT", + "node_modules/@aws-sdk/ec2-metadata-service": { + "version": "3.1138.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/ec2-metadata-service/-/ec2-metadata-service-3.1138.0.tgz", + "integrity": "sha512-rkhfA5opZaUsHgdm3BTqrWYu0NQyBhbEVvySGgVTUgaiFdrTDqFMyOizg3OhTpdVhAlJOgARMjX6O9HDnmrTMQ==", + "license": "Apache-2.0", "dependencies": { - "strnum": "^2.1.0" + "@aws-sdk/types": "^3.974.6", + "@smithy/core": "^3.35.0", + "@smithy/node-http-handler": "^4.12.1", + "@smithy/types": "^4.19.0", + "tslib": "^2.6.2" }, - "bin": { - "fxparser": "src/cli/cli.js" + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/core/node_modules/strnum": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz", - "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT" - }, - "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.846.0.tgz", - "integrity": "sha512-QuCQZET9enja7AWVISY+mpFrEIeHzvkx/JEEbHYzHhUkxcnC2Kq2c0bB7hDihGD0AZd3Xsm653hk1O97qu69zg==", + "node_modules/@aws-sdk/nested-clients": { + "version": "3.997.46", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.46.tgz", + "integrity": "sha512-oRxtBcka/JGHGs9l9p9IVajGoTP8vTPmoAzdHGy4Qcy9P5vPnDf6nhIeM/COQNY9k/OahImTRaLkHftoXvfcmQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.846.0", - "@aws-sdk/types": "3.840.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/types": "^4.3.1", + "@aws-sdk/core": "^3.978.1", + "@aws-sdk/signature-v4-multi-region": "^3.996.47", + "@aws-sdk/types": "^3.974.6", + "@smithy/core": "^3.35.0", + "@smithy/fetch-http-handler": "^5.8.0", + "@smithy/node-http-handler": "^4.12.1", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.846.0.tgz", - "integrity": "sha512-Jh1iKUuepdmtreMYozV2ePsPcOF5W9p3U4tWhi3v6nDvz0GsBjzjAROW+BW8XMz9vAD3I9R+8VC3/aq63p5nlw==", + "node_modules/@aws-sdk/s3-request-presigner": { + "version": "3.1138.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.1138.0.tgz", + "integrity": "sha512-dm9Os1QCbqbZGDuAP3LW8G2b9y0yHh9BYdOfRut988XJObJYDEc5JyLk5qvjTQpho/B23KSHUeHVIFqvLgxLrA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.846.0", - "@aws-sdk/types": "3.840.0", - "@smithy/fetch-http-handler": "^5.1.0", - "@smithy/node-http-handler": "^4.1.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.7", - "@smithy/types": "^4.3.1", - "@smithy/util-stream": "^4.2.3", + "@aws-sdk/core": "^3.978.1", + "@aws-sdk/signature-v4-multi-region": "^3.996.47", + "@aws-sdk/types": "^3.974.6", + "@smithy/core": "^3.35.0", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.846.0.tgz", - "integrity": "sha512-GUxaBBKsYx1kOlRbcs77l6BVyG9K70zekJX+5hdwTEgJq7AoHl/XYoWiDxPf6zQ7J4euixPJoyRhpNbJjAXdFw==", + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.996.47", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.47.tgz", + "integrity": "sha512-Zk08macMvQTHzQJCLJVkOlviVoqwYMrpXv4lmLN7b7sAbiMoOK7Go0NYdR5UeF+MW8LIbRmwrNy9u/5VvX1U5g==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.846.0", - "@aws-sdk/credential-provider-env": "3.846.0", - "@aws-sdk/credential-provider-http": "3.846.0", - "@aws-sdk/credential-provider-process": "3.846.0", - "@aws-sdk/credential-provider-sso": "3.846.0", - "@aws-sdk/credential-provider-web-identity": "3.846.0", - "@aws-sdk/nested-clients": "3.846.0", - "@aws-sdk/types": "3.840.0", - "@smithy/credential-provider-imds": "^4.0.6", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", + "@aws-sdk/types": "^3.974.6", + "@smithy/signature-v4": "^5.7.3", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.846.0.tgz", - "integrity": "sha512-du2DsXYRfQ8VIt/gXGThhT8KdUEt2j9W91W87Bl9IA5DINt4nSZv+gzh8LqHBYsTSqoUpKb+qIfP1RjZM/8r0A==", + "node_modules/@aws-sdk/token-providers": { + "version": "3.1138.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1138.0.tgz", + "integrity": "sha512-GpyAr0DD63YOEmYFM6Df+gJuIgC92MMTiBK4FTKfxii5MJ9ge20epR7LyroulscYlG89J+ZB2ivFDPjvfQhzdw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "3.846.0", - "@aws-sdk/credential-provider-http": "3.846.0", - "@aws-sdk/credential-provider-ini": "3.846.0", - "@aws-sdk/credential-provider-process": "3.846.0", - "@aws-sdk/credential-provider-sso": "3.846.0", - "@aws-sdk/credential-provider-web-identity": "3.846.0", - "@aws-sdk/types": "3.840.0", - "@smithy/credential-provider-imds": "^4.0.6", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", + "@aws-sdk/core": "^3.978.1", + "@aws-sdk/nested-clients": "^3.997.46", + "@aws-sdk/types": "^3.974.6", + "@smithy/core": "^3.35.0", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.846.0.tgz", - "integrity": "sha512-mEpwDYarJSH+CIXnnHN0QOe0MXI+HuPStD6gsv3z/7Q6ESl8KRWon3weFZCDnqpiJMUVavlDR0PPlAFg2MQoPg==", + "node_modules/@aws-sdk/types": { + "version": "3.974.6", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.974.6.tgz", + "integrity": "sha512-v/clNZzZnDxGyvpHMOGpJKVXFAExJzUNAAjaWGdcx8QAcXLGwTaOkw33p5SHAi0YAioK32xB3hWwOekRVfmfKg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.846.0", - "@aws-sdk/types": "3.840.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.846.0.tgz", - "integrity": "sha512-Dxz9dpdjfxUsSfW92SAldu9wy8wgEbskn4BNWBFHslQHTmqurmR0ci4P1SMxJJKd498AUEoIAzZOtjGOC38irQ==", + "node_modules/@aws-sdk/xml-builder": { + "version": "3.972.41", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.41.tgz", + "integrity": "sha512-ctjVSyCMegrWfXlx6VqzSBFI6UqmQ5ZlnfMhdLIiWmhoH8UAQxSCP5N3OpG7X3k4LnS7ou74C4mt20+bfTW2aQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.846.0", - "@aws-sdk/core": "3.846.0", - "@aws-sdk/token-providers": "3.846.0", - "@aws-sdk/types": "3.840.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.846.0.tgz", - "integrity": "sha512-j6zOd+kynPQJzmVwSKSUTpsLXAf7vKkr7hCPbQyqC8ZqkIuExsRqu2vRQjX2iH/MKhwZ+qEWMxPMhfDoyv7Gag==", + "node_modules/@aws/lambda-invoke-store": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.3.0.tgz", + "integrity": "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==", "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.846.0", - "@aws-sdk/nested-clients": "3.846.0", - "@aws-sdk/types": "3.840.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-bucket-endpoint": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.840.0.tgz", - "integrity": "sha512-+gkQNtPwcSMmlwBHFd4saVVS11In6ID1HczNzpM3MXKXRBfSlbZJbCt6wN//AZ8HMklZEik4tcEOG0qa9UY8SQ==", - "license": "Apache-2.0", + "node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-arn-parser": "3.804.0", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "@smithy/util-config-provider": "^4.0.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-expect-continue": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.840.0.tgz", - "integrity": "sha512-iJg2r6FKsKKvdiU4oCOuCf7Ro/YE0Q2BT/QyEZN3/Rt8Nr4SAZiQOlcBXOCpGvuIKOEAhvDOUnW3aDHL01PdVw==", - "license": "Apache-2.0", + "node_modules/@azure/core-auth": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.9.0.tgz", + "integrity": "sha512-FPwHpZywuyasDSLMqJ6fhbOK3TqUdviZNF8OqRGA4W5Ewib2lEEZ+pBsYcBa88B2NGO/SEnYPGhyBqNlE8ilSw==", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", + "@azure/abort-controller": "^2.0.0", + "@azure/core-util": "^1.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-flexible-checksums": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.846.0.tgz", - "integrity": "sha512-CdkeVfkwt3+bDLhmOwBxvkUf6oY9iUhvosaUnqkoPsOqIiUEN54yTGOnO8A0wLz6mMsZ6aBlfFrQhFnxt3c+yw==", - "license": "Apache-2.0", + "node_modules/@azure/core-client": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.9.3.tgz", + "integrity": "sha512-/wGw8fJ4mdpJ1Cum7s1S+VQyXt1ihwKLzfabS1O/RDADnmzVc01dHn44qD0BvGH6KlZNzOMW95tEpKqhkCChPA==", "dependencies": { - "@aws-crypto/crc32": "5.2.0", - "@aws-crypto/crc32c": "5.2.0", - "@aws-crypto/util": "5.2.0", - "@aws-sdk/core": "3.846.0", - "@aws-sdk/types": "3.840.0", - "@smithy/is-array-buffer": "^4.0.0", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-stream": "^4.2.3", - "@smithy/util-utf8": "^4.0.0", + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.4.0", + "@azure/core-rest-pipeline": "^1.9.1", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.6.1", + "@azure/logger": "^1.0.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.840.0.tgz", - "integrity": "sha512-ub+hXJAbAje94+Ya6c6eL7sYujoE8D4Bumu1NUI8TXjUhVVn0HzVWQjpRLshdLsUp1AW7XyeJaxyajRaJQ8+Xg==", - "license": "Apache-2.0", + "node_modules/@azure/core-http-compat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@azure/core-http-compat/-/core-http-compat-2.2.0.tgz", + "integrity": "sha512-1kW8ZhN0CfbNOG6C688z5uh2yrzALE7dDXHiR9dY4vt+EbhGZQSbjDa5bQd2rf3X2pdWMsXbqbArxUyeNdvtmg==", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" + "@azure/abort-controller": "^2.0.0", + "@azure/core-client": "^1.3.0", + "@azure/core-rest-pipeline": "^1.19.0" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-location-constraint": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.840.0.tgz", - "integrity": "sha512-KVLD0u0YMF3aQkVF8bdyHAGWSUY6N1Du89htTLgqCcIhSxxAJ9qifrosVZ9jkAzqRW99hcufyt2LylcVU2yoKQ==", - "license": "Apache-2.0", + "node_modules/@azure/core-lro": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.7.2.tgz", + "integrity": "sha512-0YIpccoX8m/k00O7mDDMdJpbr6mf1yWo2dfmxt5A8XVZVVMz2SSKaEbMCeJRvgQ0IaSlqhjT47p4hVIRRy90xw==", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/types": "^4.3.1", + "@azure/abort-controller": "^2.0.0", + "@azure/core-util": "^1.2.0", + "@azure/logger": "^1.0.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-logger": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.840.0.tgz", - "integrity": "sha512-lSV8FvjpdllpGaRspywss4CtXV8M7NNNH+2/j86vMH+YCOZ6fu2T/TyFd/tHwZ92vDfHctWkRbQxg0bagqwovA==", - "license": "Apache-2.0", + "node_modules/@azure/core-paging": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.6.2.tgz", + "integrity": "sha512-YKWi9YuCU04B55h25cnOYZHxXYtEvQEbKST5vqRga7hWY9ydd3FZHdeQF8pyh+acWZvppw13M/LMGx0LABUVMA==", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.840.0.tgz", - "integrity": "sha512-Gu7lGDyfddyhIkj1Z1JtrY5NHb5+x/CRiB87GjaSrKxkDaydtX2CU977JIABtt69l9wLbcGDIQ+W0uJ5xPof7g==", - "license": "Apache-2.0", + "node_modules/@azure/core-process": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@azure/core-process/-/core-process-1.0.0.tgz", + "integrity": "sha512-/shnJ+ooO8WPxDhPEeI/2oRQuubn16gZ6CvlbpWbEswZfzwI9tI/sMAHmF3x1LuQ9yZYXfLW3TjzGMLEC5blKg==", + "license": "MIT", + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.19.1.tgz", + "integrity": "sha512-zHeoI3NCs53lLBbWNzQycjnYKsA1CVKlnzSNuSFcUDwBp8HHVObePxrM7HaX+Ha5Ks639H7chNC9HOaIhNS03w==", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.8.0", + "@azure/core-tracing": "^1.0.1", + "@azure/core-util": "^1.11.0", + "@azure/logger": "^1.0.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.846.0.tgz", - "integrity": "sha512-jP9x+2Q87J5l8FOP+jlAd7vGLn0cC6G9QGmf386e5OslBPqxXKcl3RjqGLIOKKos2mVItY3ApP5xdXQx7jGTVA==", - "license": "Apache-2.0", + "node_modules/@azure/core-rest-pipeline/node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/@azure/core-rest-pipeline/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dependencies": { - "@aws-sdk/core": "3.846.0", - "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-arn-parser": "3.804.0", - "@smithy/core": "^3.7.0", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/protocol-http": "^5.1.2", - "@smithy/signature-v4": "^5.1.2", - "@smithy/smithy-client": "^4.4.7", - "@smithy/types": "^4.3.1", - "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-stream": "^4.2.3", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": ">=18.0.0" + "node": ">= 14" } }, - "node_modules/@aws-sdk/middleware-ssec": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.840.0.tgz", - "integrity": "sha512-CBZP9t1QbjDFGOrtnUEHL1oAvmnCUUm7p0aPNbIdSzNtH42TNKjPRN3TuEIJDGjkrqpL3MXyDSmNayDcw/XW7Q==", - "license": "Apache-2.0", + "node_modules/@azure/core-rest-pipeline/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" + "agent-base": "^7.1.2", + "debug": "4" }, "engines": { - "node": ">=18.0.0" + "node": ">= 14" } }, - "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.846.0.tgz", - "integrity": "sha512-85/oUc2jMXqQWo+HHH7WwrdqqArzhMmTmBCpXZwklBHG+ZMzTS5Wug2B0HhGDVWo9aYRMeikSq4lsrpHFVd2MQ==", - "license": "Apache-2.0", + "node_modules/@azure/core-tracing": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.2.0.tgz", + "integrity": "sha512-UKTiEJPkWcESPYJz3X5uKRYyOcJD+4nYph+KpfdPRnQJVrZfk0KJgdnaAWKfhsBBtAf/D58Az4AvCJEmWgIBAg==", "dependencies": { - "@aws-sdk/core": "3.846.0", - "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.845.0", - "@smithy/core": "^3.7.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/nested-clients": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.846.0.tgz", - "integrity": "sha512-LCXPVtNQnkTuE8inPCtpfWN2raE/ndFBKf5OIbuHnC/0XYGOUl5q7VsJz471zJuN9FX3WMfopaFwmNc7cQNMpQ==", - "license": "Apache-2.0", + "node_modules/@azure/core-util": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.11.0.tgz", + "integrity": "sha512-DxOSLua+NdpWoSqULhjDyAZTXFdP/LKkqtYuxxz1SCN289zk3OG8UOpnCQAz/tygyACBtWp/BoO72ptK7msY8g==", "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.846.0", - "@aws-sdk/middleware-host-header": "3.840.0", - "@aws-sdk/middleware-logger": "3.840.0", - "@aws-sdk/middleware-recursion-detection": "3.840.0", - "@aws-sdk/middleware-user-agent": "3.846.0", - "@aws-sdk/region-config-resolver": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.845.0", - "@aws-sdk/util-user-agent-browser": "3.840.0", - "@aws-sdk/util-user-agent-node": "3.846.0", - "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.7.0", - "@smithy/fetch-http-handler": "^5.1.0", - "@smithy/hash-node": "^4.0.4", - "@smithy/invalid-dependency": "^4.0.4", - "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.15", - "@smithy/middleware-retry": "^4.1.16", - "@smithy/middleware-serde": "^4.0.8", - "@smithy/middleware-stack": "^4.0.4", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.1.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.7", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.23", - "@smithy/util-defaults-mode-node": "^4.0.23", - "@smithy/util-endpoints": "^3.0.6", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-retry": "^4.0.6", - "@smithy/util-utf8": "^4.0.0", + "@azure/abort-controller": "^2.0.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.840.0.tgz", - "integrity": "sha512-Qjnxd/yDv9KpIMWr90ZDPtRj0v75AqGC92Lm9+oHXZ8p1MjG5JE2CW0HL8JRgK9iKzgKBL7pPQRXI8FkvEVfrA==", - "license": "Apache-2.0", + "node_modules/@azure/core-xml": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@azure/core-xml/-/core-xml-1.4.5.tgz", + "integrity": "sha512-gT4H8mTaSXRz7eGTuQyq1aIJnJqeXzpOe9Ay7Z3FrCouer14CbV3VzjnJrNrQfbBpGBLO9oy8BmrY75A0p53cA==", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/types": "^4.3.1", - "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", - "tslib": "^2.6.2" + "fast-xml-parser": "^5.0.7", + "tslib": "^2.8.1" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/s3-request-presigner": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.846.0.tgz", - "integrity": "sha512-R2I3bdYSvncieucQiGGfSo3Xu8kV424uyu5tZZQk3zEH7ZNshJlE8YcYAGkN9caqlnYZ4V+CK6+71ufTc8I/XQ==", - "license": "Apache-2.0", + "node_modules/@azure/core-xml/node_modules/fast-xml-parser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.0.tgz", + "integrity": "sha512-Uw9+Mjt4SBRud1IcaYuW/O0lW8SKKdMl5g7g24HiIuyH5fQSD+AVLybSlJtqLYEbytVFjWQa5DMGcNgeksdRBg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], "dependencies": { - "@aws-sdk/signature-v4-multi-region": "3.846.0", - "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-format-url": "3.840.0", - "@smithy/middleware-endpoint": "^4.1.15", - "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.7", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" + "strnum": "^2.0.5" }, - "engines": { - "node": ">=18.0.0" + "bin": { + "fxparser": "src/cli/cli.js" } }, - "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.846.0.tgz", - "integrity": "sha512-ZMfIMxUljqZzPJGOcraC6erwq/z1puNMU35cO1a/WdhB+LdYknMn1lr7SJuH754QwNzzIlZbEgg4hoHw50+DpQ==", - "license": "Apache-2.0", + "node_modules/@azure/core-xml/node_modules/strnum": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.0.5.tgz", + "integrity": "sha512-YAT3K/sgpCUxhxNMrrdhtod3jckkpYwH6JAuwmUdXZsmzH1wUyzTMrrK2wYCEEqlKwrWDd35NeuUkbBy/1iK+Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ] + }, + "node_modules/@azure/identity": { + "version": "4.13.3", + "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.13.3.tgz", + "integrity": "sha512-zGQPtqvXPgSA8yfV2CkIQ1qirqk0p9AIVpC5uEkdXQYcKl07QHvyaGYRnZOk0AsQUmxNb4wfkcwY5di8Z5xa9A==", + "license": "MIT", "dependencies": { - "@aws-sdk/middleware-sdk-s3": "3.846.0", - "@aws-sdk/types": "3.840.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/signature-v4": "^5.1.2", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.2", + "@azure/core-process": "^1.0.0", + "@azure/core-rest-pipeline": "^1.17.0", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.11.0", + "@azure/logger": "^1.0.0", + "@azure/msal-browser": "^5.5.0", + "@azure/msal-node": "^6.0.0", + "open": "^10.1.0", + "tslib": "^2.2.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=22.0.0" } }, - "node_modules/@aws-sdk/token-providers": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.846.0.tgz", - "integrity": "sha512-sGNk3xclK7xx+rIJZDJC4FNFqaSSqN0nSr+AdVdQ+/iKQKaUA6hixRbXaQ7I7M5mhqS6fMW1AsqVRywQq2BSMw==", - "license": "Apache-2.0", + "node_modules/@azure/logger": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.1.4.tgz", + "integrity": "sha512-4IXXzcCdLdlXuCG+8UKEwLA1T1NHqUfanhXYHiQTn+6sfWCZXduqbtXDGceg3Ce5QxTGo7EqmbV6Bi+aqKuClQ==", "dependencies": { - "@aws-sdk/core": "3.846.0", - "@aws-sdk/nested-clients": "3.846.0", - "@aws-sdk/types": "3.840.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/types": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.840.0.tgz", - "integrity": "sha512-xliuHaUFZxEx1NSXeLLZ9Dyu6+EJVQKEoD+yM+zqUo3YDZ7medKJWY6fIOKiPX/N7XbLdBYwajb15Q7IL8KkeA==", - "license": "Apache-2.0", + "node_modules/@azure/msal-browser": { + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-5.22.0.tgz", + "integrity": "sha512-5kgu9xeEKgGc2JeidxAtU15NJTqiH/CMCRRQAJ4Rac56kB7KVg91vbNmn+z3RO1vNomPN69UvjKG9h1Pghx6dQ==", + "license": "MIT", "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" + "@azure/msal-common": "16.14.1" }, "engines": { - "node": ">=18.0.0" + "node": ">=0.8.0" } }, - "node_modules/@aws-sdk/util-arn-parser": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.804.0.tgz", - "integrity": "sha512-wmBJqn1DRXnZu3b4EkE6CWnoWMo1ZMvlfkqU5zPz67xx1GMaXlDCchFvKAXMjk4jn/L1O3tKnoFDNsoLV1kgNQ==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, + "node_modules/@azure/msal-common": { + "version": "16.14.1", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-16.14.1.tgz", + "integrity": "sha512-Or6xhPNyi4zHW25158yxBoyxuCqNSPa5YBVqfF1J5Ks4MJWBo/USXdp05DQIPu1Zli00YZu6t0+h6KvHJealxQ==", + "license": "MIT", "engines": { - "node": ">=18.0.0" + "node": ">=0.8.0" } }, - "node_modules/@aws-sdk/util-endpoints": { - "version": "3.845.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.845.0.tgz", - "integrity": "sha512-MBmOf0Pb4q6xs9V7jXT1+qciW2965yvaoZUlUUnxUEoX6zxWROeIu/gttASc4vSjOHr/+64hmFkxjeBUF37FJA==", - "license": "Apache-2.0", + "node_modules/@azure/msal-node": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-6.0.1.tgz", + "integrity": "sha512-ixSO1Y/kCVRthRs+hSx/5qkwaunX1/RAePhlMN0wIpIQ4WEZ6AREGGnGd1AP0qspHVsAwzWQKGubpjh50JyJIQ==", + "license": "MIT", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "@smithy/util-endpoints": "^3.0.6", - "tslib": "^2.6.2" + "@azure/msal-common": "16.14.1", + "jsonwebtoken": "^9.0.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=20" } }, - "node_modules/@aws-sdk/util-format-url": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.840.0.tgz", - "integrity": "sha512-VB1PWyI1TQPiPvg4w7tgUGGQER1xxXPNUqfh3baxUSFi1Oh8wHrDnFywkxLm3NMmgDmnLnSZ5Q326qAoyqKLSg==", - "license": "Apache-2.0", + "node_modules/@azure/storage-blob": { + "version": "12.27.0", + "resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.27.0.tgz", + "integrity": "sha512-IQjj9RIzAKatmNca3D6bT0qJ+Pkox1WZGOg2esJF2YLHb45pQKOwGPIAV+w3rfgkj7zV3RMxpn/c6iftzSOZJQ==", + "license": "MIT", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/querystring-builder": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.4.0", + "@azure/core-client": "^1.6.2", + "@azure/core-http-compat": "^2.0.0", + "@azure/core-lro": "^2.2.0", + "@azure/core-paging": "^1.1.1", + "@azure/core-rest-pipeline": "^1.10.1", + "@azure/core-tracing": "^1.1.2", + "@azure/core-util": "^1.6.1", + "@azure/core-xml": "^1.4.3", + "@azure/logger": "^1.0.0", + "events": "^3.0.0", + "tslib": "^2.2.0" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/util-locate-window": { - "version": "3.723.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.723.0.tgz", - "integrity": "sha512-Yf2CS10BqK688DRsrKI/EO6B8ff5J86NXe4C+VCysK7UOgN0l1zOTeTukZ3H8Q9tYYX3oaF1961o8vRkFm7Nmw==", + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dependencies": { - "tslib": "^2.6.2" + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.840.0.tgz", - "integrity": "sha512-JdyZM3EhhL4PqwFpttZu1afDpPJCCc3eyZOLi+srpX11LsGj6sThf47TYQN75HT1CarZ7cCdQHGzP2uy3/xHfQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/types": "^4.3.1", - "bowser": "^2.11.0", - "tslib": "^2.6.2" + "node_modules/@babel/compat-data": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", + "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.846.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.846.0.tgz", - "integrity": "sha512-MXYXCplw76xe8A9ejVaIru6Carum/2LQbVtNHsIa4h0TlafLdfulywsoMWL1F53Y9XxQSeOKyyqDKLNOgRVimw==", - "license": "Apache-2.0", + "node_modules/@babel/core": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", + "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", + "dev": true, "dependencies": { - "@aws-sdk/middleware-user-agent": "3.846.0", - "@aws-sdk/types": "3.840.0", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "aws-crt": ">=1.0.0" + "node": ">=6.9.0" }, - "peerDependenciesMeta": { - "aws-crt": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@aws-sdk/xml-builder": { - "version": "3.821.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.821.0.tgz", - "integrity": "sha512-DIIotRnefVL6DiaHtO6/21DhJ4JZnnIwdNbpwiAhdt/AVbttcE4yw925gsjur0OGv5BTYXQXU3YnANBYnZjuQA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@azure/abort-controller": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", - "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "node_modules/@babel/generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", + "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", "dependencies": { - "tslib": "^2.6.2" + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@azure/core-auth": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.9.0.tgz", - "integrity": "sha512-FPwHpZywuyasDSLMqJ6fhbOK3TqUdviZNF8OqRGA4W5Ewib2lEEZ+pBsYcBa88B2NGO/SEnYPGhyBqNlE8ilSw==", + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", + "dev": true, "dependencies": { - "@azure/abort-controller": "^2.0.0", - "@azure/core-util": "^1.11.0", - "tslib": "^2.6.2" + "@babel/types": "^7.25.9" }, "engines": { - "node": ">=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@azure/core-client": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.9.3.tgz", - "integrity": "sha512-/wGw8fJ4mdpJ1Cum7s1S+VQyXt1ihwKLzfabS1O/RDADnmzVc01dHn44qD0BvGH6KlZNzOMW95tEpKqhkCChPA==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", + "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", + "dev": true, "dependencies": { - "@azure/abort-controller": "^2.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-rest-pipeline": "^1.9.1", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.6.1", - "@azure/logger": "^1.0.0", - "tslib": "^2.6.2" + "@babel/compat-data": "^7.26.8", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { - "node": ">=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@azure/core-http-compat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@azure/core-http-compat/-/core-http-compat-2.2.0.tgz", - "integrity": "sha512-1kW8ZhN0CfbNOG6C688z5uh2yrzALE7dDXHiR9dY4vt+EbhGZQSbjDa5bQd2rf3X2pdWMsXbqbArxUyeNdvtmg==", + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.0.tgz", + "integrity": "sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==", + "dev": true, "dependencies": { - "@azure/abort-controller": "^2.0.0", - "@azure/core-client": "^1.3.0", - "@azure/core-rest-pipeline": "^1.19.0" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.27.0", + "semver": "^6.3.1" }, "engines": { - "node": ">=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@azure/core-lro": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.7.2.tgz", - "integrity": "sha512-0YIpccoX8m/k00O7mDDMdJpbr6mf1yWo2dfmxt5A8XVZVVMz2SSKaEbMCeJRvgQ0IaSlqhjT47p4hVIRRy90xw==", - "dependencies": { - "@azure/abort-controller": "^2.0.0", - "@azure/core-util": "^1.2.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@azure/core-paging": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.6.2.tgz", - "integrity": "sha512-YKWi9YuCU04B55h25cnOYZHxXYtEvQEbKST5vqRga7hWY9ydd3FZHdeQF8pyh+acWZvppw13M/LMGx0LABUVMA==", + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.0.tgz", + "integrity": "sha512-fO8l08T76v48BhpNRW/nQ0MxfnSdoSKUJBMjubOAYffsVuGG5qOfMq7N6Es7UJvi7Y8goXXo07EfcHZXDPuELQ==", + "dev": true, "dependencies": { - "tslib": "^2.6.2" + "@babel/helper-annotate-as-pure": "^7.25.9", + "regexpu-core": "^6.2.0", + "semver": "^6.3.1" }, "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@azure/core-rest-pipeline": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.19.1.tgz", - "integrity": "sha512-zHeoI3NCs53lLBbWNzQycjnYKsA1CVKlnzSNuSFcUDwBp8HHVObePxrM7HaX+Ha5Ks639H7chNC9HOaIhNS03w==", - "dependencies": { - "@azure/abort-controller": "^2.0.0", - "@azure/core-auth": "^1.8.0", - "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.11.0", - "@azure/logger": "^1.0.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.0", - "tslib": "^2.6.2" + "node": ">=6.9.0" }, - "engines": { - "node": ">=18.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@azure/core-rest-pipeline/node_modules/agent-base": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", - "engines": { - "node": ">= 14" + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@azure/core-rest-pipeline/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.4.tgz", + "integrity": "sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==", + "dev": true, "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" }, - "engines": { - "node": ">= 14" + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@azure/core-rest-pipeline/node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", + "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", + "dev": true, "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { - "node": ">= 14" + "node": ">=6.9.0" } }, - "node_modules/@azure/core-tracing": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.2.0.tgz", - "integrity": "sha512-UKTiEJPkWcESPYJz3X5uKRYyOcJD+4nYph+KpfdPRnQJVrZfk0KJgdnaAWKfhsBBtAf/D58Az4AvCJEmWgIBAg==", + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dependencies": { - "tslib": "^2.6.2" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { - "node": ">=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@azure/core-util": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.11.0.tgz", - "integrity": "sha512-DxOSLua+NdpWoSqULhjDyAZTXFdP/LKkqtYuxxz1SCN289zk3OG8UOpnCQAz/tygyACBtWp/BoO72ptK7msY8g==", + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "dev": true, "dependencies": { - "@azure/abort-controller": "^2.0.0", - "tslib": "^2.6.2" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { - "node": ">=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@azure/core-xml": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/@azure/core-xml/-/core-xml-1.4.5.tgz", - "integrity": "sha512-gT4H8mTaSXRz7eGTuQyq1aIJnJqeXzpOe9Ay7Z3FrCouer14CbV3VzjnJrNrQfbBpGBLO9oy8BmrY75A0p53cA==", + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", + "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", + "dev": true, "dependencies": { - "fast-xml-parser": "^5.0.7", - "tslib": "^2.8.1" + "@babel/types": "^7.25.9" }, "engines": { - "node": ">=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@azure/core-xml/node_modules/fast-xml-parser": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.0.tgz", - "integrity": "sha512-Uw9+Mjt4SBRud1IcaYuW/O0lW8SKKdMl5g7g24HiIuyH5fQSD+AVLybSlJtqLYEbytVFjWQa5DMGcNgeksdRBg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "dependencies": { - "strnum": "^2.0.5" - }, - "bin": { - "fxparser": "src/cli/cli.js" + "node_modules/@babel/helper-plugin-utils": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "dev": true, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@azure/core-xml/node_modules/strnum": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.0.5.tgz", - "integrity": "sha512-YAT3K/sgpCUxhxNMrrdhtod3jckkpYwH6JAuwmUdXZsmzH1wUyzTMrrK2wYCEEqlKwrWDd35NeuUkbBy/1iK+Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ] - }, - "node_modules/@azure/logger": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.1.4.tgz", - "integrity": "sha512-4IXXzcCdLdlXuCG+8UKEwLA1T1NHqUfanhXYHiQTn+6sfWCZXduqbtXDGceg3Ce5QxTGo7EqmbV6Bi+aqKuClQ==", + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", + "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", + "dev": true, "dependencies": { - "tslib": "^2.6.2" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-wrap-function": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { - "node": ">=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@azure/storage-blob": { - "version": "12.27.0", - "resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.27.0.tgz", - "integrity": "sha512-IQjj9RIzAKatmNca3D6bT0qJ+Pkox1WZGOg2esJF2YLHb45pQKOwGPIAV+w3rfgkj7zV3RMxpn/c6iftzSOZJQ==", - "license": "MIT", + "node_modules/@babel/helper-replace-supers": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz", + "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==", + "dev": true, "dependencies": { - "@azure/abort-controller": "^2.1.2", - "@azure/core-auth": "^1.4.0", - "@azure/core-client": "^1.6.2", - "@azure/core-http-compat": "^2.0.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.1.1", - "@azure/core-rest-pipeline": "^1.10.1", - "@azure/core-tracing": "^1.1.2", - "@azure/core-util": "^1.6.1", - "@azure/core-xml": "^1.4.3", - "@azure/logger": "^1.0.0", - "events": "^3.0.0", - "tslib": "^2.2.0" + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.26.5" }, "engines": { - "node": ">=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", + "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", + "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/compat-data": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", - "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", - "dev": true, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/core": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", - "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.10", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.10", - "@babel/parser": "^7.26.10", - "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.10", - "@babel/types": "^7.26.10", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "engines": { "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", - "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", - "dependencies": { - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-annotate-as-pure": { + "node_modules/@babel/helper-wrap-function": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", + "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", "dev": true, "dependencies": { + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-compilation-targets": { + "node_modules/@babel/helpers": { "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", - "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", + "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.26.8", - "@babel/helper-validator-option": "^7.25.9", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, + "node_modules/@babel/parser": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", + "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "dependencies": { + "@babel/types": "^7.27.0" + }, "bin": { - "semver": "bin/semver.js" + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.0.tgz", - "integrity": "sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==", + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", + "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-member-expression-to-functions": "^7.25.9", - "@babel/helper-optimise-call-expression": "^7.25.9", - "@babel/helper-replace-supers": "^7.26.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/traverse": "^7.27.0", - "semver": "^6.3.1" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1709,24 +1507,13 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.0.tgz", - "integrity": "sha512-fO8l08T76v48BhpNRW/nQ0MxfnSdoSKUJBMjubOAYffsVuGG5qOfMq7N6Es7UJvi7Y8goXXo07EfcHZXDPuELQ==", + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", + "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "regexpu-core": "^6.2.0", - "semver": "^6.3.1" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1735,341 +1522,109 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.4.tgz", - "integrity": "sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==", + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", + "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", "dev": true, "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-member-expression-to-functions": { + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", - "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", "dev": true, "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" } }, - "node_modules/@babel/helper-module-imports": { + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", + "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", + "dev": true, "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", - "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, "dependencies": { - "@babel/types": "^7.25.9" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, - "engines": { - "node": ">=6.9.0" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", - "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-wrap-function": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" + "@babel/helper-plugin-utils": "^7.12.13" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz", - "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==", + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", "dev": true, "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.25.9", - "@babel/helper-optimise-call-expression": "^7.25.9", - "@babel/traverse": "^7.26.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", - "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", - "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", - "dev": true, - "dependencies": { - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", - "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", - "dev": true, - "dependencies": { - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", - "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", - "dependencies": { - "@babel/types": "^7.27.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", - "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", - "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", - "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", - "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/plugin-transform-optional-chaining": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", - "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { "node": ">=6.9.0" @@ -7208,6 +6763,18 @@ "@tybys/wasm-util": "^0.9.0" } }, + "node_modules/@nodable/entities": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-3.0.0.tgz", + "integrity": "sha512-8L9xFeTYKhm49xfIypoe2W5wV1m/3Z58kT+7kR9A8OyFxcPduI4VmxaUMQyKYrRjUoLLSXv6EKKID5Tvj9cUVw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nodable" + } + ], + "license": "MIT" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -7859,923 +7426,285 @@ "license": "MIT" }, "node_modules/@react-dnd/shallowequal": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-2.0.0.tgz", - "integrity": "sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg==", - "license": "MIT" - }, - "node_modules/@reactflow/background": { - "version": "11.3.14", - "resolved": "https://registry.npmjs.org/@reactflow/background/-/background-11.3.14.tgz", - "integrity": "sha512-Gewd7blEVT5Lh6jqrvOgd4G6Qk17eGKQfsDXgyRSqM+CTwDqRldG2LsWN4sNeno6sbqVIC2fZ+rAUBFA9ZEUDA==", - "license": "MIT", - "dependencies": { - "@reactflow/core": "11.11.4", - "classcat": "^5.0.3", - "zustand": "^4.4.1" - }, - "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" - } - }, - "node_modules/@reactflow/controls": { - "version": "11.2.14", - "resolved": "https://registry.npmjs.org/@reactflow/controls/-/controls-11.2.14.tgz", - "integrity": "sha512-MiJp5VldFD7FrqaBNIrQ85dxChrG6ivuZ+dcFhPQUwOK3HfYgX2RHdBua+gx+40p5Vw5It3dVNp/my4Z3jF0dw==", - "license": "MIT", - "dependencies": { - "@reactflow/core": "11.11.4", - "classcat": "^5.0.3", - "zustand": "^4.4.1" - }, - "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" - } - }, - "node_modules/@reactflow/core": { - "version": "11.11.4", - "resolved": "https://registry.npmjs.org/@reactflow/core/-/core-11.11.4.tgz", - "integrity": "sha512-H4vODklsjAq3AMq6Np4LE12i1I4Ta9PrDHuBR9GmL8uzTt2l2jh4CiQbEMpvMDcp7xi4be0hgXj+Ysodde/i7Q==", - "license": "MIT", - "dependencies": { - "@types/d3": "^7.4.0", - "@types/d3-drag": "^3.0.1", - "@types/d3-selection": "^3.0.3", - "@types/d3-zoom": "^3.0.1", - "classcat": "^5.0.3", - "d3-drag": "^3.0.0", - "d3-selection": "^3.0.0", - "d3-zoom": "^3.0.0", - "zustand": "^4.4.1" - }, - "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" - } - }, - "node_modules/@reactflow/minimap": { - "version": "11.7.14", - "resolved": "https://registry.npmjs.org/@reactflow/minimap/-/minimap-11.7.14.tgz", - "integrity": "sha512-mpwLKKrEAofgFJdkhwR5UQ1JYWlcAAL/ZU/bctBkuNTT1yqV+y0buoNVImsRehVYhJwffSWeSHaBR5/GJjlCSQ==", - "license": "MIT", - "dependencies": { - "@reactflow/core": "11.11.4", - "@types/d3-selection": "^3.0.3", - "@types/d3-zoom": "^3.0.1", - "classcat": "^5.0.3", - "d3-selection": "^3.0.0", - "d3-zoom": "^3.0.0", - "zustand": "^4.4.1" - }, - "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" - } - }, - "node_modules/@reactflow/node-resizer": { - "version": "2.2.14", - "resolved": "https://registry.npmjs.org/@reactflow/node-resizer/-/node-resizer-2.2.14.tgz", - "integrity": "sha512-fwqnks83jUlYr6OHcdFEedumWKChTHRGw/kbCxj0oqBd+ekfs+SIp4ddyNU0pdx96JIm5iNFS0oNrmEiJbbSaA==", - "license": "MIT", - "dependencies": { - "@reactflow/core": "11.11.4", - "classcat": "^5.0.4", - "d3-drag": "^3.0.0", - "d3-selection": "^3.0.0", - "zustand": "^4.4.1" - }, - "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" - } - }, - "node_modules/@reactflow/node-toolbar": { - "version": "1.3.14", - "resolved": "https://registry.npmjs.org/@reactflow/node-toolbar/-/node-toolbar-1.3.14.tgz", - "integrity": "sha512-rbynXQnH/xFNu4P9H+hVqlEUafDCkEoCy0Dg9mG22Sg+rY/0ck6KkrAQrYrTgXusd+cEJOMK0uOOFCK2/5rSGQ==", - "license": "MIT", - "dependencies": { - "@reactflow/core": "11.11.4", - "classcat": "^5.0.3", - "zustand": "^4.4.1" - }, - "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" - } - }, - "node_modules/@remirror/core-constants": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz", - "integrity": "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==", - "license": "MIT" - }, - "node_modules/@remix-run/router": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz", - "integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@rtsao/scc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", - "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", - "dev": true - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.3.tgz", - "integrity": "sha512-hw6HbX+GyVZzmaYNh82Ecj1vdGZrqVIn/keDTg63IgAwiQPO+xCz99uG6Woqgb4tM0mUiFENKZ4cqd7IX94AXQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "type-detect": "^4.1.0" - } - }, - "node_modules/@sinonjs/samsam/node_modules/type-detect": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", - "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", - "dev": true, - "license": "(Unlicense OR Apache-2.0)" - }, - "node_modules/@smithy/abort-controller": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.4.tgz", - "integrity": "sha512-gJnEjZMvigPDQWHrW3oPrFhQtkrgqBkyjj3pCIdF3A5M6vsZODG93KNlfJprv6bp4245bdT32fsHK4kkH3KYDA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/chunked-blob-reader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.0.0.tgz", - "integrity": "sha512-+sKqDBQqb036hh4NPaUiEkYFkTUGYzRsn3EuFhyfQfMy6oGHEUJDurLP9Ufb5dasr/XiAmPNMr6wa9afjQB+Gw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/chunked-blob-reader-native": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.0.0.tgz", - "integrity": "sha512-R9wM2yPmfEMsUmlMlIgSzOyICs0x9uu7UTHoccMyt7BWw8shcGM8HqB355+BZCPBcySvbTYMs62EgEQkNxz2ig==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-base64": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/config-resolver": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.1.4.tgz", - "integrity": "sha512-prmU+rDddxHOH0oNcwemL+SwnzcG65sBF2yXRO7aeXIn/xTlq2pX7JLVbkBnVLowHLg4/OL4+jBmv9hVrVGS+w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/types": "^4.3.1", - "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/core": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.7.0.tgz", - "integrity": "sha512-7ov8hu/4j0uPZv8b27oeOFtIBtlFmM3ibrPv/Omx1uUdoXvcpJ00U+H/OWWC/keAguLlcqwtyL2/jTlSnApgNQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/middleware-serde": "^4.0.8", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-stream": "^4.2.3", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/credential-provider-imds": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.6.tgz", - "integrity": "sha512-hKMWcANhUiNbCJouYkZ9V3+/Qf9pteR1dnwgdyzR09R4ODEYx8BbUysHwRSyex4rZ9zapddZhLFTnT4ZijR4pw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/property-provider": "^4.0.4", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/eventstream-codec": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.0.4.tgz", - "integrity": "sha512-7XoWfZqWb/QoR/rAU4VSi0mWnO2vu9/ltS6JZ5ZSZv0eovLVfDfu0/AX4ub33RsJTOth3TiFWSHS5YdztvFnig==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/crc32": "5.2.0", - "@smithy/types": "^4.3.1", - "@smithy/util-hex-encoding": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-browser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.0.4.tgz", - "integrity": "sha512-3fb/9SYaYqbpy/z/H3yIi0bYKyAa89y6xPmIqwr2vQiUT2St+avRt8UKwsWt9fEdEasc5d/V+QjrviRaX1JRFA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/eventstream-serde-universal": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.1.2.tgz", - "integrity": "sha512-JGtambizrWP50xHgbzZI04IWU7LdI0nh/wGbqH3sJesYToMi2j/DcoElqyOcqEIG/D4tNyxgRuaqBXWE3zOFhQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-node": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.0.4.tgz", - "integrity": "sha512-RD6UwNZ5zISpOWPuhVgRz60GkSIp0dy1fuZmj4RYmqLVRtejFqQ16WmfYDdoSoAjlp1LX+FnZo+/hkdmyyGZ1w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/eventstream-serde-universal": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-universal": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.0.4.tgz", - "integrity": "sha512-UeJpOmLGhq1SLox79QWw/0n2PFX+oPRE1ZyRMxPIaFEfCqWaqpB7BU9C8kpPOGEhLF7AwEqfFbtwNxGy4ReENA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/eventstream-codec": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/fetch-http-handler": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.1.0.tgz", - "integrity": "sha512-mADw7MS0bYe2OGKkHYMaqarOXuDwRbO6ArD91XhHcl2ynjGCFF+hvqf0LyQcYxkA1zaWjefSkU7Ne9mqgApSgQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/protocol-http": "^5.1.2", - "@smithy/querystring-builder": "^4.0.4", - "@smithy/types": "^4.3.1", - "@smithy/util-base64": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/hash-blob-browser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.0.4.tgz", - "integrity": "sha512-WszRiACJiQV3QG6XMV44i5YWlkrlsM5Yxgz4jvsksuu7LDXA6wAtypfPajtNTadzpJy3KyJPoWehYpmZGKUFIQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/chunked-blob-reader": "^5.0.0", - "@smithy/chunked-blob-reader-native": "^4.0.0", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/hash-node": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.4.tgz", - "integrity": "sha512-qnbTPUhCVnCgBp4z4BUJUhOEkVwxiEi1cyFM+Zj6o+aY8OFGxUQleKWq8ltgp3dujuhXojIvJWdoqpm6dVO3lQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "@smithy/util-buffer-from": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/hash-stream-node": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.0.4.tgz", - "integrity": "sha512-wHo0d8GXyVmpmMh/qOR0R7Y46/G1y6OR8U+bSTB4ppEzRxd1xVAQ9xOE9hOc0bSjhz0ujCPAbfNLkLrpa6cevg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/invalid-dependency": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.4.tgz", - "integrity": "sha512-bNYMi7WKTJHu0gn26wg8OscncTt1t2b8KcsZxvOv56XA6cyXtOAAAaNP7+m45xfppXfOatXF3Sb1MNsLUgVLTw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/is-array-buffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.0.0.tgz", - "integrity": "sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/md5-js": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.0.4.tgz", - "integrity": "sha512-uGLBVqcOwrLvGh/v/jw423yWHq/ofUGK1W31M2TNspLQbUV1Va0F5kTxtirkoHawODAZcjXTSGi7JwbnPcDPJg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-content-length": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.4.tgz", - "integrity": "sha512-F7gDyfI2BB1Kc+4M6rpuOLne5LOcEknH1n6UQB69qv+HucXBR1rkzXBnQTB2q46sFy1PM/zuSJOB532yc8bg3w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-endpoint": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.15.tgz", - "integrity": "sha512-L2M0oz+r6Wv0KZ90MgClXmWkV7G72519Hd5/+K5i3gQMu4WNQykh7ERr58WT3q60dd9NqHSMc3/bAK0FsFg3Fw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.7.0", - "@smithy/middleware-serde": "^4.0.8", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "@smithy/util-middleware": "^4.0.4", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-retry": { - "version": "4.1.16", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.16.tgz", - "integrity": "sha512-PpPhMpC6U1fLW0evKnC8gJtmobBYn0oi4RrIKGhN1a86t6XgVEK+Vb9C8dh5PPXb3YDr8lE6aYKh1hd3OikmWw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/protocol-http": "^5.1.2", - "@smithy/service-error-classification": "^4.0.6", - "@smithy/smithy-client": "^4.4.7", - "@smithy/types": "^4.3.1", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-retry": "^4.0.6", - "tslib": "^2.6.2", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-retry/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@smithy/middleware-serde": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.8.tgz", - "integrity": "sha512-iSSl7HJoJaGyMIoNn2B7czghOVwJ9nD7TMvLhMWeSB5vt0TnEYyRRqPJu/TqW76WScaNvYYB8nRoiBHR9S1Ddw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-stack": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.4.tgz", - "integrity": "sha512-kagK5ggDrBUCCzI93ft6DjteNSfY8Ulr83UtySog/h09lTIOAJ/xUSObutanlPT0nhoHAkpmW9V5K8oPyLh+QA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/node-config-provider": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.1.3.tgz", - "integrity": "sha512-HGHQr2s59qaU1lrVH6MbLlmOBxadtzTsoO4c+bF5asdgVik3I8o7JIOzoeqWc5MjVa+vD36/LWE0iXKpNqooRw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/node-http-handler": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.1.0.tgz", - "integrity": "sha512-vqfSiHz2v8b3TTTrdXi03vNz1KLYYS3bhHCDv36FYDqxT7jvTll1mMnCrkD+gOvgwybuunh/2VmvOMqwBegxEg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/abort-controller": "^4.0.4", - "@smithy/protocol-http": "^5.1.2", - "@smithy/querystring-builder": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/property-provider": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.4.tgz", - "integrity": "sha512-qHJ2sSgu4FqF4U/5UUp4DhXNmdTrgmoAai6oQiM+c5RZ/sbDwJ12qxB1M6FnP+Tn/ggkPZf9ccn4jqKSINaquw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/protocol-http": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.1.2.tgz", - "integrity": "sha512-rOG5cNLBXovxIrICSBm95dLqzfvxjEmuZx4KK3hWwPFHGdW3lxY0fZNXfv2zebfRO7sJZ5pKJYHScsqopeIWtQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/querystring-builder": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.4.tgz", - "integrity": "sha512-SwREZcDnEYoh9tLNgMbpop+UTGq44Hl9tdj3rf+yeLcfH7+J8OXEBaMc2kDxtyRHu8BhSg9ADEx0gFHvpJgU8w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "@smithy/util-uri-escape": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-2.0.0.tgz", + "integrity": "sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg==", + "license": "MIT" }, - "node_modules/@smithy/querystring-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.4.tgz", - "integrity": "sha512-6yZf53i/qB8gRHH/l2ZwUG5xgkPgQF15/KxH0DdXMDHjesA9MeZje/853ifkSY0x4m5S+dfDZ+c4x439PF0M2w==", - "license": "Apache-2.0", + "node_modules/@reactflow/background": { + "version": "11.3.14", + "resolved": "https://registry.npmjs.org/@reactflow/background/-/background-11.3.14.tgz", + "integrity": "sha512-Gewd7blEVT5Lh6jqrvOgd4G6Qk17eGKQfsDXgyRSqM+CTwDqRldG2LsWN4sNeno6sbqVIC2fZ+rAUBFA9ZEUDA==", + "license": "MIT", "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" + "@reactflow/core": "11.11.4", + "classcat": "^5.0.3", + "zustand": "^4.4.1" }, - "engines": { - "node": ">=18.0.0" + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" } }, - "node_modules/@smithy/service-error-classification": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.6.tgz", - "integrity": "sha512-RRoTDL//7xi4tn5FrN2NzH17jbgmnKidUqd4KvquT0954/i6CXXkh1884jBiunq24g9cGtPBEXlU40W6EpNOOg==", - "license": "Apache-2.0", + "node_modules/@reactflow/controls": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@reactflow/controls/-/controls-11.2.14.tgz", + "integrity": "sha512-MiJp5VldFD7FrqaBNIrQ85dxChrG6ivuZ+dcFhPQUwOK3HfYgX2RHdBua+gx+40p5Vw5It3dVNp/my4Z3jF0dw==", + "license": "MIT", "dependencies": { - "@smithy/types": "^4.3.1" + "@reactflow/core": "11.11.4", + "classcat": "^5.0.3", + "zustand": "^4.4.1" }, - "engines": { - "node": ">=18.0.0" + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" } }, - "node_modules/@smithy/shared-ini-file-loader": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.4.tgz", - "integrity": "sha512-63X0260LoFBjrHifPDs+nM9tV0VMkOTl4JRMYNuKh/f5PauSjowTfvF3LogfkWdcPoxsA9UjqEOgjeYIbhb7Nw==", - "license": "Apache-2.0", + "node_modules/@reactflow/core": { + "version": "11.11.4", + "resolved": "https://registry.npmjs.org/@reactflow/core/-/core-11.11.4.tgz", + "integrity": "sha512-H4vODklsjAq3AMq6Np4LE12i1I4Ta9PrDHuBR9GmL8uzTt2l2jh4CiQbEMpvMDcp7xi4be0hgXj+Ysodde/i7Q==", + "license": "MIT", "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" + "@types/d3": "^7.4.0", + "@types/d3-drag": "^3.0.1", + "@types/d3-selection": "^3.0.3", + "@types/d3-zoom": "^3.0.1", + "classcat": "^5.0.3", + "d3-drag": "^3.0.0", + "d3-selection": "^3.0.0", + "d3-zoom": "^3.0.0", + "zustand": "^4.4.1" }, - "engines": { - "node": ">=18.0.0" + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" } }, - "node_modules/@smithy/signature-v4": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.1.2.tgz", - "integrity": "sha512-d3+U/VpX7a60seHziWnVZOHuEgJlclufjkS6zhXvxcJgkJq4UWdH5eOBLzHRMx6gXjsdT9h6lfpmLzbrdupHgQ==", - "license": "Apache-2.0", + "node_modules/@reactflow/minimap": { + "version": "11.7.14", + "resolved": "https://registry.npmjs.org/@reactflow/minimap/-/minimap-11.7.14.tgz", + "integrity": "sha512-mpwLKKrEAofgFJdkhwR5UQ1JYWlcAAL/ZU/bctBkuNTT1yqV+y0buoNVImsRehVYhJwffSWeSHaBR5/GJjlCSQ==", + "license": "MIT", "dependencies": { - "@smithy/is-array-buffer": "^4.0.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "@smithy/util-hex-encoding": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-uri-escape": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" + "@reactflow/core": "11.11.4", + "@types/d3-selection": "^3.0.3", + "@types/d3-zoom": "^3.0.1", + "classcat": "^5.0.3", + "d3-selection": "^3.0.0", + "d3-zoom": "^3.0.0", + "zustand": "^4.4.1" }, - "engines": { - "node": ">=18.0.0" + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" } }, - "node_modules/@smithy/smithy-client": { - "version": "4.4.7", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.4.7.tgz", - "integrity": "sha512-x+MxBNOcG7rY9i5QsbdgvvRJngKKvUJrbU5R5bT66PTH3e6htSupJ4Q+kJ3E7t6q854jyl57acjpPi6qG1OY5g==", - "license": "Apache-2.0", + "node_modules/@reactflow/node-resizer": { + "version": "2.2.14", + "resolved": "https://registry.npmjs.org/@reactflow/node-resizer/-/node-resizer-2.2.14.tgz", + "integrity": "sha512-fwqnks83jUlYr6OHcdFEedumWKChTHRGw/kbCxj0oqBd+ekfs+SIp4ddyNU0pdx96JIm5iNFS0oNrmEiJbbSaA==", + "license": "MIT", "dependencies": { - "@smithy/core": "^3.7.0", - "@smithy/middleware-endpoint": "^4.1.15", - "@smithy/middleware-stack": "^4.0.4", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "@smithy/util-stream": "^4.2.3", - "tslib": "^2.6.2" + "@reactflow/core": "11.11.4", + "classcat": "^5.0.4", + "d3-drag": "^3.0.0", + "d3-selection": "^3.0.0", + "zustand": "^4.4.1" }, - "engines": { - "node": ">=18.0.0" + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" } }, - "node_modules/@smithy/types": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.3.1.tgz", - "integrity": "sha512-UqKOQBL2x6+HWl3P+3QqFD4ncKq0I8Nuz9QItGv5WuKuMHuuwlhvqcZCoXGfc+P1QmfJE7VieykoYYmrOoFJxA==", - "license": "Apache-2.0", + "node_modules/@reactflow/node-toolbar": { + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@reactflow/node-toolbar/-/node-toolbar-1.3.14.tgz", + "integrity": "sha512-rbynXQnH/xFNu4P9H+hVqlEUafDCkEoCy0Dg9mG22Sg+rY/0ck6KkrAQrYrTgXusd+cEJOMK0uOOFCK2/5rSGQ==", + "license": "MIT", "dependencies": { - "tslib": "^2.6.2" + "@reactflow/core": "11.11.4", + "classcat": "^5.0.3", + "zustand": "^4.4.1" }, - "engines": { - "node": ">=18.0.0" + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" } }, - "node_modules/@smithy/url-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.4.tgz", - "integrity": "sha512-eMkc144MuN7B0TDA4U2fKs+BqczVbk3W+qIvcoCY6D1JY3hnAdCuhCZODC+GAeaxj0p6Jroz4+XMUn3PCxQQeQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/querystring-parser": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } + "node_modules/@remirror/core-constants": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz", + "integrity": "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==", + "license": "MIT" }, - "node_modules/@smithy/util-base64": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.0.0.tgz", - "integrity": "sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, + "node_modules/@remix-run/router": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz", + "integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==", "engines": { - "node": ">=18.0.0" + "node": ">=14.0.0" } }, - "node_modules/@smithy/util-body-length-browser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.0.0.tgz", - "integrity": "sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true }, - "node_modules/@smithy/util-body-length-node": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.0.0.tgz", - "integrity": "sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true }, - "node_modules/@smithy/util-buffer-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz", - "integrity": "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^4.0.0", - "tslib": "^2.6.2" - }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, "engines": { - "node": ">=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" } }, - "node_modules/@smithy/util-config-provider": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.0.0.tgz", - "integrity": "sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==", - "license": "Apache-2.0", + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" + "type-detect": "4.0.8" } }, - "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.0.23", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.23.tgz", - "integrity": "sha512-NqRi6VvEIwpJ+KSdqI85+HH46H7uVoNqVTs2QO7p1YKnS7k8VZnunJj8R5KdmmVnTojkaL1OMPyZC8uR5F7fSg==", - "license": "Apache-2.0", + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, "dependencies": { - "@smithy/property-provider": "^4.0.4", - "@smithy/smithy-client": "^4.4.7", - "@smithy/types": "^4.3.1", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" + "@sinonjs/commons": "^3.0.0" } }, - "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.0.23", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.23.tgz", - "integrity": "sha512-NE9NtEVigFa+HHJ5bBeQT7KF3KiltW880CLN9TnWWL55akeou3ziRAHO22QSUPgPZ/nqMfPXi/LGMQ6xQvXPNQ==", - "license": "Apache-2.0", + "node_modules/@sinonjs/samsam": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.3.tgz", + "integrity": "sha512-hw6HbX+GyVZzmaYNh82Ecj1vdGZrqVIn/keDTg63IgAwiQPO+xCz99uG6Woqgb4tM0mUiFENKZ4cqd7IX94AXQ==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@smithy/config-resolver": "^4.1.4", - "@smithy/credential-provider-imds": "^4.0.6", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/property-provider": "^4.0.4", - "@smithy/smithy-client": "^4.4.7", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" + "@sinonjs/commons": "^3.0.1", + "type-detect": "^4.1.0" } }, - "node_modules/@smithy/util-endpoints": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.6.tgz", - "integrity": "sha512-YARl3tFL3WgPuLzljRUnrS2ngLiUtkwhQtj8PAL13XZSyUiNLQxwG3fBBq3QXFqGFUXepIN73pINp3y8c2nBmA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, + "node_modules/@sinonjs/samsam/node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=18.0.0" + "node": ">=4" } }, - "node_modules/@smithy/util-hex-encoding": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.0.0.tgz", - "integrity": "sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==", + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", + "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", + "dev": true, + "license": "(Unlicense OR Apache-2.0)" + }, + "node_modules/@smithy/core": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.35.0.tgz", + "integrity": "sha512-zRMhfkByhT2snNdr1si24vJitU6Cr9ix2MikUfWmkAgp4jrNP0GcKSP5YvwQ+TlI8AZXER5QOGJn3JsVtSD9/A==", "license": "Apache-2.0", "dependencies": { + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@smithy/util-middleware": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.4.tgz", - "integrity": "sha512-9MLKmkBmf4PRb0ONJikCbCwORACcil6gUWojwARCClT7RmLzF04hUR4WdRprIXal7XVyrddadYNfp2eF3nrvtQ==", + "node_modules/@smithy/credential-provider-imds": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.5.2.tgz", + "integrity": "sha512-A9uSdn72ozbRUSit0eib0TW7nXuNPlaeM0zcGkJ+nE6tFcSDbnmtwoxbTCFBukVQcszDAyvsd7+rTduPTXpygg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/core": "^3.33.2", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@smithy/util-retry": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.6.tgz", - "integrity": "sha512-+YekoF2CaSMv6zKrA6iI/N9yva3Gzn4L6n35Luydweu5MMPYpiGZlWqehPHDHyNbnyaYlz/WJyYAZnC+loBDZg==", + "node_modules/@smithy/fetch-http-handler": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.8.0.tgz", + "integrity": "sha512-ycSJu3tFAQ4v04CBB0agqFMVsSQ1iG3yw+SpgxRqKfaURpQD4CZ8Wn0zPMmSnOuTpTh65Vz+EA0rMrw089wvkA==", "license": "Apache-2.0", "dependencies": { - "@smithy/service-error-classification": "^4.0.6", - "@smithy/types": "^4.3.1", + "@smithy/core": "^3.33.3", + "@smithy/types": "^4.18.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@smithy/util-stream": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.3.tgz", - "integrity": "sha512-cQn412DWHHFNKrQfbHY8vSFI3nTROY1aIKji9N0tpp8gUABRilr7wdf8fqBbSlXresobM+tQFNk6I+0LXK/YZg==", + "node_modules/@smithy/node-http-handler": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.12.1.tgz", + "integrity": "sha512-ThMkboGeONWXAelq9FvGsuJC4rOi+qyC4/zhUF58xYpxUg5sQKx2VXZYJmtNjr4dSuBJ1HeJXETQILCz3wOHvw==", "license": "Apache-2.0", "dependencies": { - "@smithy/fetch-http-handler": "^5.1.0", - "@smithy/node-http-handler": "^4.1.0", - "@smithy/types": "^4.3.1", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-buffer-from": "^4.0.0", - "@smithy/util-hex-encoding": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", + "@smithy/core": "^3.33.3", + "@smithy/types": "^4.18.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@smithy/util-uri-escape": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", - "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==", + "node_modules/@smithy/protocol-http": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.6.2.tgz", + "integrity": "sha512-Asd04MaxODN6FNY8EPTeCAM4kPNi3jDUAjZU0Y4F9rHvpLUrrUo7KLcxFgSthywFr6dZfIyDLIJda6jxmVTk5w==", "license": "Apache-2.0", "dependencies": { + "@smithy/core": "^3.33.2", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@smithy/util-utf8": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz", - "integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==", + "node_modules/@smithy/signature-v4": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.7.3.tgz", + "integrity": "sha512-7ImGm+FkHRLcBaRttIAMZ6bzJZWb2cJGoYjq46F2UjycujWzrL9GEN9h4w7eQyXJYnltrUhxbbieBAIRrdqpow==", "license": "Apache-2.0", "dependencies": { - "@smithy/util-buffer-from": "^4.0.0", + "@smithy/core": "^3.33.3", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@smithy/util-waiter": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.0.6.tgz", - "integrity": "sha512-slcr1wdRbX7NFphXZOxtxRNA7hXAAtJAXJDE/wdoMAos27SIquVCKiSqfB6/28YzQ8FCsB5NKkhdM5gMADbqxg==", + "node_modules/@smithy/types": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", + "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^4.0.4", - "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -11799,6 +10728,18 @@ "node": ">= 8" } }, + "node_modules/anynum": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/anynum/-/anynum-1.0.1.tgz", + "integrity": "sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, "node_modules/app-builder-bin": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz", @@ -12399,13 +11340,15 @@ } }, "node_modules/axios": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", - "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.20.0.tgz", + "integrity": "sha512-r8aOh8j9cGKpgQAqpzrUHnSIc6a59Y3Xf/cv8sy1DrHCkZHzQGEuoq1tARk6qSyDdtQGSDgpb9kFlruzPvrgwg==", + "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" + "follow-redirects": "^1.16.0", + "form-data": "^4.0.6", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" } }, "node_modules/axobject-query": { @@ -12808,11 +11751,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/binascii": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/binascii/-/binascii-0.0.2.tgz", - "integrity": "sha512-rA2CrUl1+6yKrn+XgLs8Hdy18OER1UW146nM+ixzhQXDY+Bd3ySkyIJGwF2a4I45JwbvF1mDL/nWkqBwpOcdBA==" - }, "node_modules/bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", @@ -12940,9 +11878,9 @@ "optional": true }, "node_modules/bowser": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", - "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz", + "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==", "license": "MIT" }, "node_modules/brace-expansion": { @@ -13035,14 +11973,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/browser-request": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/browser-request/-/browser-request-0.3.3.tgz", - "integrity": "sha512-YyNI4qJJ+piQG6MMEuo7J3Bzaqssufx04zpEKYfSrl/1Op59HWali9zMtBpXnkmqMcOuWJPZvudrm9wISmnCbg==", - "engines": [ - "node" - ] - }, "node_modules/browserslist": { "version": "4.24.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", @@ -13152,7 +12082,8 @@ "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" }, "node_modules/buffer-from": { "version": "1.1.2", @@ -13225,7 +12156,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", - "dev": true, "dependencies": { "run-applescript": "^7.0.0" }, @@ -14378,14 +13308,6 @@ "yarn": ">=1" } }, - "node_modules/cross-fetch": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", - "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", - "dependencies": { - "node-fetch": "^2.7.0" - } - }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -15161,7 +14083,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", - "dev": true, "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" @@ -15177,7 +14098,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", - "dev": true, "engines": { "node": ">=18" }, @@ -15227,7 +14147,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, "engines": { "node": ">=12" }, @@ -18255,6 +17174,22 @@ } ] }, + "node_modules/fast-xml-builder": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.3.1.tgz", + "integrity": "sha512-pIM/1n3ntFXKYrUZwW7QCK0gAW7XY+wzj1YMIV3tLDvPj/V+zTGJK5e3/4WJfwj0qWw2ElNXiTixda/R+3YSug==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "path-expression-matcher": "^1.6.2", + "xml-naming": "^0.3.0" + } + }, "node_modules/fast-xml-parser": { "version": "4.5.3", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz", @@ -18594,15 +17529,16 @@ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -18654,14 +17590,16 @@ } }, "node_modules/form-data": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", - "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "mime-types": "^2.1.12" + "hasown": "^2.0.4", + "mime-types": "^2.1.35" }, "engines": { "node": ">= 6" @@ -19312,9 +18250,10 @@ } }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -20507,7 +19446,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, "dependencies": { "is-docker": "^3.0.0" }, @@ -20525,7 +19463,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, "bin": { "is-docker": "cli.js" }, @@ -20761,6 +19698,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-unsafe": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-unsafe/-/is-unsafe-2.0.2.tgz", + "integrity": "sha512-HgbIHPBH0KHHCcjLfGsCvhtPTVxjaAZlXjwdz7/GQC40SjSe4sfQsar8J5VFo8JOSbarkpV0OLG95bbaNd9aAQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, "node_modules/is-weakmap": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", @@ -22102,6 +21051,7 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, "bin": { "json5": "lib/cli.js" }, @@ -22130,11 +21080,12 @@ } }, "node_modules/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "license": "MIT", "dependencies": { - "jws": "^3.2.2", + "jws": "^4.0.1", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", @@ -22150,25 +21101,6 @@ "npm": ">=6" } }, - "node_modules/jsonwebtoken/node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jsonwebtoken/node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, "node_modules/jss": { "version": "10.10.0", "resolved": "https://registry.npmjs.org/jss/-/jss-10.10.0.tgz", @@ -22322,21 +21254,23 @@ "license": "MIT" }, "node_modules/jwa": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", - "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", "dependencies": { - "buffer-equal-constant-time": "1.0.1", + "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "node_modules/jws": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", - "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", "dependencies": { - "jwa": "^2.0.0", + "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, @@ -22611,12 +21545,14 @@ "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" }, "node_modules/lodash.isboolean": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" }, "node_modules/lodash.isequal": { "version": "4.5.0", @@ -22627,12 +21563,14 @@ "node_modules/lodash.isinteger": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" }, "node_modules/lodash.isnumber": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" }, "node_modules/lodash.isplainobject": { "version": "4.0.6", @@ -22642,7 +21580,8 @@ "node_modules/lodash.isstring": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" }, "node_modules/lodash.memoize": { "version": "4.1.2", @@ -22659,7 +21598,8 @@ "node_modules/lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" }, "node_modules/lodash.union": { "version": "4.6.0", @@ -22706,23 +21646,6 @@ "node": ">= 12.0.0" } }, - "node_modules/loglevel": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz", - "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==", - "engines": { - "node": ">= 0.6.0" - }, - "funding": { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/loglevel" - } - }, - "node_modules/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, "node_modules/longest-streak": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", @@ -24092,6 +23015,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, "bin": { "mkdirp": "bin/cmd.js" }, @@ -24191,6 +23115,7 @@ "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, "funding": [ { "type": "github", @@ -24659,7 +23584,6 @@ "version": "10.1.2", "resolved": "https://registry.npmjs.org/open/-/open-10.1.2.tgz", "integrity": "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==", - "dev": true, "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", @@ -24677,7 +23601,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", - "dev": true, "dependencies": { "is-inside-container": "^1.0.0" }, @@ -25010,6 +23933,21 @@ "node": ">=8" } }, + "node_modules/path-expression-matcher": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.6.2.tgz", + "integrity": "sha512-enSlaiat05iasnzmgNxRj8reFdj3puY2QpNgP1aPIaVfT6nn9ICuPoFlKHk8EN22HcwewshO+mN2DGbkCEOtqQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -26512,9 +25450,13 @@ } }, "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } }, "node_modules/ps-tree": { "version": "1.2.0", @@ -26586,14 +25528,6 @@ } ] }, - "node_modules/python-struct": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/python-struct/-/python-struct-1.1.3.tgz", - "integrity": "sha512-UsI/mNvk25jRpGKYI38Nfbv84z48oiIWwG67DLVvjRhy8B/0aIK+5Ju5WOHgw/o9rnEmbAS00v4rgKFQeC332Q==", - "dependencies": { - "long": "^4.0.0" - } - }, "node_modules/qs": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", @@ -27791,7 +26725,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", - "dev": true, "engines": { "node": ">=18" }, @@ -28659,42 +27592,46 @@ } }, "node_modules/snowflake-sdk": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/snowflake-sdk/-/snowflake-sdk-2.1.0.tgz", - "integrity": "sha512-daRZRj1y631Y2pK8N85Jm1aBadHVqMU3uIOrqS/6XQ+PYMjV0oDpZsJ0TBRSYdJ0ChFR8Fd+QnUgQ/j2NYkdRQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/snowflake-sdk/-/snowflake-sdk-3.3.0.tgz", + "integrity": "sha512-WJV5BZpYzNuReafTJuHLO5sjYFnrRvqB1T1/xW64UpRDo0GAgLbfKIVZP+S5iBQ0ick8nY9Cqbka2uowQC+JMA==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-s3": "^3.726.0", + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-sdk/client-s3": "^3.1051.0", + "@aws-sdk/client-sts": "^3.1051.0", + "@aws-sdk/credential-provider-node": "^3.972.43", + "@aws-sdk/ec2-metadata-service": "^3.1051.0", + "@azure/identity": "^4.10.1", "@azure/storage-blob": "12.26.x", - "@google-cloud/storage": "^7.7.0", - "@smithy/node-http-handler": "^4.0.1", + "@smithy/node-http-handler": "^4.4.9", + "@smithy/protocol-http": "^5.3.8", + "@smithy/signature-v4": "^5.3.8", "@techteamer/ocsp": "1.0.1", + "asn1.js": "^5.0.0", "asn1.js-rfc2560": "^5.0.0", "asn1.js-rfc5280": "^3.0.0", - "axios": "^1.8.3", + "axios": "^1.15.1", "big-integer": "^1.6.43", "bignumber.js": "^9.1.2", - "binascii": "0.0.2", - "bn.js": "^5.2.1", - "browser-request": "^0.3.3", "expand-tilde": "^2.0.2", - "fast-xml-parser": "^4.2.5", + "fast-xml-parser": "^5.4.1", "fastest-levenshtein": "^1.0.16", "generic-pool": "^3.8.2", - "glob": "^10.0.0", + "google-auth-library": "^10.1.0", "https-proxy-agent": "^7.0.2", - "jsonwebtoken": "^9.0.0", + "jsonwebtoken": "^9.0.3", "mime-types": "^2.1.29", - "mkdirp": "^1.0.3", "moment": "^2.29.4", "moment-timezone": "^0.5.15", "oauth4webapi": "^3.0.1", "open": "^7.3.1", - "python-struct": "^1.1.3", "simple-lru-cache": "^0.0.2", "toml": "^3.0.0", - "uuid": "^8.3.2", - "winston": "^3.1.0", - "wiremock-rest-client": "^1.11.0" + "winston": "^3.1.0" + }, + "engines": { + "node": ">=20" }, "peerDependencies": { "asn1.js": "^5.4.1" @@ -28732,28 +27669,81 @@ "node": ">= 14" } }, - "node_modules/snowflake-sdk/node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" - }, - "node_modules/snowflake-sdk/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "node_modules/snowflake-sdk/node_modules/fast-xml-parser": { + "version": "5.11.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.11.1.tgz", + "integrity": "sha512-TBw6K/fxoQGGjCmZDw9w/ZwP3uDcnTM4YH/g+PFRWr8sbe5idXtxNN6vITh4+1ruCZaho6uBFurElsA7F0zzgw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" + "@nodable/entities": "^3.0.0", + "fast-xml-builder": "^1.2.0", + "is-unsafe": "^2.0.0", + "path-expression-matcher": "^1.6.2", + "strnum": "^2.4.2", + "xml-naming": "^0.3.0" }, "bin": { - "glob": "dist/esm/bin.mjs" + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/snowflake-sdk/node_modules/gaxios": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.3.1.tgz", + "integrity": "sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=18" + } + }, + "node_modules/snowflake-sdk/node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/snowflake-sdk/node_modules/google-auth-library": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.9.1.tgz", + "integrity": "sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.1.4", + "gcp-metadata": "8.1.2", + "google-logging-utils": "1.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/snowflake-sdk/node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" } }, "node_modules/snowflake-sdk/node_modules/https-proxy-agent": { @@ -28768,26 +27758,22 @@ "node": ">= 14" } }, - "node_modules/snowflake-sdk/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/snowflake-sdk/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/snowflake-sdk/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "engines": { - "node": ">=16 || 14 >=14.17" + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" } }, "node_modules/snowflake-sdk/node_modules/open": { @@ -28805,12 +27791,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/snowflake-sdk/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" + "node_modules/snowflake-sdk/node_modules/strnum": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.4.2.tgz", + "integrity": "sha512-rDG3Ah4TV0k1hWvLSzkZtMmLN9+eS+h3knq4MP6A42Y3Yh5qGNnOUs1jJkoSr8FG5dsL28c7KgkIBzSEykqtuw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "anynum": "^1.0.1" } }, "node_modules/sockjs": { @@ -31921,53 +30914,6 @@ "node": ">= 6" } }, - "node_modules/wiremock-rest-client": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/wiremock-rest-client/-/wiremock-rest-client-1.11.0.tgz", - "integrity": "sha512-2EBj80RJdwJNpCnetjUwkdTgnMW4Bq8sFdtR84hmjFZPhW2eE0HmBfhxTztTQ2PtoGOoqIlXh6VK2fvD4pYQ6Q==", - "dependencies": { - "commander": "^6.2.1", - "cross-fetch": "^3.1.5", - "https-proxy-agent": "~4.0.0", - "json5": "^2.2.0", - "loglevel": "^1.8.0", - "nanoid": "^3.3.1" - }, - "bin": { - "wrc": "bin/index.js" - }, - "engines": { - "node": "^12.22.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/wiremock-rest-client/node_modules/agent-base": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", - "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/wiremock-rest-client/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/wiremock-rest-client/node_modules/https-proxy-agent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", - "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", - "dependencies": { - "agent-base": "5", - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -32059,6 +31005,21 @@ "node": ">=12" } }, + "node_modules/xml-naming": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.3.0.tgz", + "integrity": "sha512-ghig2TBE/H11aOVgmahA3MhimvkBr6JIYknH/Dhdk10nXwdbIqBJsbfMxpvFPG8bAw77gN29aQWvKpmVoPlvPQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/xmlbuilder": { "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", @@ -32247,4 +31208,4 @@ } } } -} \ No newline at end of file +} diff --git a/package.json b/package.json index 8632ea7b..44e815ec 100644 --- a/package.json +++ b/package.json @@ -112,8 +112,8 @@ "@ai-sdk/openai": "^3.0.49", "@ai-sdk/openai-compatible": "^2.0.49", "@anthropic-ai/sdk": "^0.60.0", - "@aws-sdk/client-s3": "^3.846.0", - "@aws-sdk/s3-request-presigner": "^3.846.0", + "@aws-sdk/client-s3": "3.1138.0", + "@aws-sdk/s3-request-presigner": "3.1138.0", "@azure/storage-blob": "^12.27.0", "@electron/notarize": "^2.3.2", "@emotion/react": "^11.14.0", @@ -171,7 +171,7 @@ "rehype-sanitize": "^6.0.0", "remark-gfm": "^4.0.1", "simple-git": "^3.27.0", - "snowflake-sdk": "^2.0.3", + "snowflake-sdk": "^3.3.0", "split-pane-react": "^0.1.3", "tar": "^7.4.3", "uuid": "^11.1.0", diff --git a/src/main/extractor/snowflake.extractor.ts b/src/main/extractor/snowflake.extractor.ts index b4f5fea5..ef21a1b7 100644 --- a/src/main/extractor/snowflake.extractor.ts +++ b/src/main/extractor/snowflake.extractor.ts @@ -1,23 +1,61 @@ /* eslint-disable no-restricted-syntax, no-await-in-loop, consistent-return */ import snowflake from 'snowflake-sdk'; import { Column, Table } from '../../types/backend'; +import { + SNOWFLAKE_REAUTH_MESSAGE, + SnowflakeAuthManager, +} from '../utils/snowflakeAuth'; export default class SnowflakeExtractor { private connection: snowflake.Connection; + private authMethod: 'password' | 'oauth_browser'; + constructor(config: { account: string; username: string; - password: string; + password?: string; warehouse: string; database: string; schema: string; role?: string; + authMethod?: 'password' | 'oauth_browser'; }) { - this.connection = snowflake.createConnection(config); + this.authMethod = config.authMethod ?? 'password'; + const baseConfig = { + account: config.account, + username: config.username, + warehouse: config.warehouse, + database: config.database, + schema: config.schema, + role: config.role, + }; + + if (this.authMethod === 'oauth_browser') { + this.connection = snowflake.createConnection({ + ...baseConfig, + authenticator: 'OAUTH_AUTHORIZATION_CODE', + browserActionTimeout: 120000, + clientStoreTemporaryCredential: true, + openExternalBrowserCallback: () => { + throw new Error(SNOWFLAKE_REAUTH_MESSAGE); + }, + }); + } else { + this.connection = snowflake.createConnection({ + ...baseConfig, + password: config.password, + }); + } } async connect(): Promise { + if (this.authMethod === 'oauth_browser') { + // No browser flows outside the Connections screen: a cold session + // fails fast with guidance instead of opening an ungated popup. + // A warm SDK cache connects silently without user interaction. + SnowflakeAuthManager.assertCachedSession(); + } return new Promise((resolve, reject) => { this.connection.connect((err) => { if (err) return reject(err); diff --git a/src/main/ipcHandlers/connectors.ipcHandlers.ts b/src/main/ipcHandlers/connectors.ipcHandlers.ts index 8f31bd56..40a0a4fc 100644 --- a/src/main/ipcHandlers/connectors.ipcHandlers.ts +++ b/src/main/ipcHandlers/connectors.ipcHandlers.ts @@ -5,8 +5,13 @@ import type { QueryResponseType, ExecuteStatementType, } from '../../types/backend'; -import { ConfigureConnectionBody, UpdateConnectionBody } from '../../types/ipc'; +import { + ConfigureConnectionBody, + UpdateConnectionBody, + StartSnowflakeAuthRequest, +} from '../../types/ipc'; import { CloudConnection, RecentItem } from '../../types/frontend'; +import { SnowflakeAuthManager } from '../utils/snowflakeAuth'; const handlerChannels = [ 'connector:configure', @@ -21,6 +26,10 @@ const handlerChannels = [ 'connector:updateQuery', 'connector:getQuery', 'connector:executeQuery', + 'connector:snowflake:auth:start', + 'connector:snowflake:auth:cancel', + 'connector:snowflake:auth:revoke', + 'connector:snowflake:auth:materialize', ]; const removeConnectorsIpcHandlers = () => { @@ -189,6 +198,59 @@ const registerConnectorsHandlers = () => { } }, ); + + ipcMain.handle( + 'connector:snowflake:auth:start', + async (event, request: StartSnowflakeAuthRequest) => { + // Narrow Snowflake-only pre-validation: never invoke the SDK with + // missing identity fields. Detailed validation also lives in + // SnowflakeAuthManager; this keeps a clear IPC boundary. + if ( + !request || + typeof request.correlationId !== 'string' || + !request.correlationId.trim() || + typeof request.account !== 'string' || + !request.account.trim() || + typeof request.username !== 'string' || + !request.username.trim() + ) { + throw new Error( + 'Snowflake account identifier and username are required before starting browser authentication.', + ); + } + return SnowflakeAuthManager.startAuth(request, (payload) => { + event.sender.send('connector:snowflake:auth:event', payload); + }); + }, + ); + + ipcMain.handle( + 'connector:snowflake:auth:cancel', + async (_event, correlationId: string) => { + SnowflakeAuthManager.cancelAuth(correlationId); + return { success: true }; + }, + ); + ipcMain.handle('connector:snowflake:auth:hasToken', async () => { + return SnowflakeAuthManager.hasSnowflakeToken(); + }); + + ipcMain.handle( + 'connector:snowflake:auth:revoke', + async (_event, body?: { connectionName?: string } | string) => { + const connectionName = + typeof body === 'string' ? body : (body?.connectionName ?? ''); + return ConnectorsService.revokeSnowflakeSession(connectionName); + }, + ); + ipcMain.handle( + 'connector:snowflake:auth:materialize', + async (_event, body?: { connectionName?: string } | string) => { + const connectionName = + typeof body === 'string' ? body : (body?.connectionName ?? ''); + return ConnectorsService.materializeSnowflakeOAuthEnv(connectionName); + }, + ); }; export default registerConnectorsHandlers; diff --git a/src/main/services/connectors.service.ts b/src/main/services/connectors.service.ts index 93760968..ac039588 100644 --- a/src/main/services/connectors.service.ts +++ b/src/main/services/connectors.service.ts @@ -51,6 +51,7 @@ import { import SecureStorageService from './secureStorage.service'; import { CloudConnection, RecentItem } from '../../types/frontend'; import { updateProjectConfigFiles } from '../utils/yamlPartialUpdate'; +import { SnowflakeAuthManager } from '../utils/snowflakeAuth'; import DuckLakeService from './duckLake.service'; import DuckLakeInstanceStore from './duckLake/instanceStore.service'; import { buildKineticaUrl, parseKineticaUrl } from '../../shared/kineticaUrl'; @@ -725,9 +726,10 @@ export default class ConnectorsService { } // Clean up connection-specific credentials from secure storage + // (keyed by connection name, matching how they were written). try { await SecureStorageService.cleanupConnectionCredentials( - connectionToDelete.id, + connectionToDelete.connection.name, ); } catch (error) { // eslint-disable-next-line no-console @@ -814,6 +816,67 @@ export default class ConnectorsService { } } + // Unified Snowflake revoke across all credential layers so the + // Connections screen, SQL Editor, and Selected Project screen observe the + // same state: SDK token cache file, keychain secrets, and materialized + // process env. Identity fields (username, account, …) are kept so forms + // can re-hydrate; only secrets are removed. + static async revokeSnowflakeSession( + connectionName: string, + ): Promise { + const name = (connectionName ?? '').trim(); + if (!name) { + throw new Error( + 'Connection name is required to revoke Snowflake credentials.', + ); + } + const revoked = SnowflakeAuthManager.revokeSnowflakeToken(); + for (const field of ['password', 'token']) { + const key = `db-${field}-${name}`; + try { + await SecureStorageService.deleteCredential(key); + } catch { + // Missing credentials are fine; revoke stays idempotent. + } + delete process.env[key]; + } + return revoked; + } + + // Hands the live Snowflake OAuth session to dbt (Python driver) at run + // time: reads the access token from the Node SDK's own cache file and + // exports it as `db-token-` process env, which OAuth profiles + // reference via `{{ env_var(...) }}`. The token never touches profiles, + // logs, keychain, or renderer state — same channel passwords already use. + // Self-gating: no-op (false) unless the named connection is + // Snowflake+oauth_browser. Returns true when a token was materialized. + static async materializeSnowflakeOAuthEnv( + connectionName: string, + ): Promise { + const name = (connectionName ?? '').trim(); + if (!name) { + return false; + } + const connection = await this.findConnectionByName(name); + const snowflakeConn = connection?.connection; + if ( + !snowflakeConn || + snowflakeConn.type !== 'snowflake' || + (snowflakeConn as SnowflakeConnection).authMethod !== 'oauth_browser' + ) { + return false; + } + const accessToken = await SnowflakeAuthManager.readCachedOAuthAccessToken( + snowflakeConn as SnowflakeConnection, + ); + if (!accessToken) { + delete process.env[`db-token-${snowflakeConn.name}`]; + return false; + } + process.env[`db-token-${snowflakeConn.name}`] = accessToken; + return true; + } + /** * Run a select statement and expect the results and fields */ @@ -1017,9 +1080,20 @@ export default class ConnectorsService { connection.type !== 'duckdb' && connection.type !== 'bigquery' ) { - // Only add userName/password for non-BigQuery, non-Databricks, non-DuckDB, non-ducklake + // Only add userName/password for non-BigQuery, non-Databricks, non-DuckDB, non-ducklake. + // Snowflake OAuth never persists a password: the JDBC URL carries + // authenticator=oauth_authorization_code and tokens stay in the SDK + // temporary credential cache (mirrors updateMainConf in + // yamlPartialUpdate.ts). + const isSnowflakeOauth = + connection.type === 'snowflake' && + (connection as SnowflakeConnection).authMethod === 'oauth_browser'; connectionConfig.userName = ev('user'); - connectionConfig.password = ev('password'); + if (isSnowflakeOauth) { + connectionConfig.authenticator = 'oauth_authorization_code'; + } else { + connectionConfig.password = ev('password'); + } } const yamlData: { @@ -1086,8 +1160,13 @@ export default class ConnectorsService { } return postgresUrl; } - case 'snowflake': - return `jdbc:snowflake://${ev('account')}.snowflakecomputing.com/?warehouse=${ev('warehouse')}&db=${ev('dbname')}&schema=${ev('schema')}`; + case 'snowflake': { + let snowflakeUrl = `jdbc:snowflake://${ev('account')}.snowflakecomputing.com/?warehouse=${ev('warehouse')}&db=${ev('dbname')}&schema=${ev('schema')}`; + if ((conn as SnowflakeConnection).authMethod === 'oauth_browser') { + snowflakeUrl += '&authenticator=oauth_authorization_code'; + } + return snowflakeUrl; + } case 'redshift': { let redshiftUrl = `jdbc:redshift://${ev('host')}:${ev('port')}/${ev('dbname')}?currentSchema=${ev('schema')}`; @@ -1134,6 +1213,12 @@ export default class ConnectorsService { project: Project, ): Promise { const rosettaJdbcUrl = await this.generateJdbcUrl(connection); + // Snowflake OAuth never persists a password; the JDBC URL carries + // authenticator=oauth_authorization_code and tokens stay in the SDK + // temporary credential cache. + const isSnowflakeOauth = + connection.type === 'snowflake' && + (connection as SnowflakeConnection).authMethod === 'oauth_browser'; return { name: connection.name || project.name, @@ -1153,26 +1238,38 @@ export default class ConnectorsService { connection.type !== 'duckdb' && connection.type !== 'bigquery' && 'username' in connection && - 'password' in connection && { + 'password' in connection && + !isSnowflakeOauth && { userName: `db-user-${connection.name}`, password: `db-password-${connection.name}`, }), + ...(isSnowflakeOauth && { + userName: `db-user-${connection.name}`, + }), }; } private static mapToDbtConnection(conn: ConnectionInput): DBTConnection { switch (conn.type) { - case 'snowflake': + case 'snowflake': { + const isSnowflakeOauth = + (conn as SnowflakeConnection).authMethod === 'oauth_browser'; return { type: 'snowflake', username: `db-user-${conn.name}`, - password: `db-password-${conn.name}`, + ...(isSnowflakeOauth + ? { + authMethod: 'oauth_browser' as const, + authenticator: 'oauth_authorization_code' as const, + } + : { password: `db-password-${conn.name}` }), database: conn.database, schema: conn.schema, account: conn.account, warehouse: conn.warehouse, ...(conn.role && { role: conn.role }), }; + } case 'bigquery': return { type: 'bigquery', @@ -1299,18 +1396,30 @@ export default class ConnectorsService { threads: 4, ...(conn.ssl && { sslmode: 'require' }), }; - case 'snowflake': + case 'snowflake': { + const isSnowflakeOauth = + (conn as SnowflakeConnection).authMethod === 'oauth_browser'; return { type: 'snowflake', account: envVar('account'), user: envVar('user'), - password: envVar('password'), + ...(isSnowflakeOauth + ? { + // Token comes from `db-token-` process env, materialized + // main-side from the live SDK session at dbt run time (never + // written to files). Plain `oauth` never opens a browser: a + // missing/expired token fails fast with guidance instead. + authenticator: 'oauth', + token: envVar('token'), + } + : { password: envVar('password') }), ...(conn.role && { role: envVar('role') }), warehouse: envVar('warehouse'), database: envVar('dbname'), schema: envVar('schema'), threads: 4, }; + } case 'redshift': const redshiftProfile: any = { type: 'redshift', @@ -1635,7 +1744,7 @@ export default class ConnectorsService { account: dbtConnection.account, warehouse: dbtConnection.warehouse, username: dbtConnection.username, - password: dbtConnection.password, + password: dbtConnection.password || '', database: dbtConnection.database, schema: dbtConnection.schema, role: dbtConnection.role, @@ -1990,14 +2099,20 @@ export default class ConnectorsService { } case 'snowflake': { const sfConn = connection as SnowflakeConnection; + const sfAuthMethod = + sfConn.authMethod === 'oauth_browser' ? 'oauth_browser' : 'password'; const extractor = new SnowflakeExtractor({ - account: sfConn.account.split('.')[0], + account: + sfAuthMethod === 'oauth_browser' + ? sfConn.account + : sfConn.account.split('.')[0], username: sfConn.username, password: sfConn.password, warehouse: sfConn.warehouse, database: sfConn.database, schema: sfConn.schema, role: sfConn.role, + authMethod: sfAuthMethod, }); try { await extractor.connect(); diff --git a/src/main/services/projects.service.ts b/src/main/services/projects.service.ts index 2cff794a..5a357ca1 100644 --- a/src/main/services/projects.service.ts +++ b/src/main/services/projects.service.ts @@ -1079,14 +1079,20 @@ export default class ProjectsService { } static async extractSnowflakeSchema(connection: SnowflakeConnection) { + const sfAuthMethod = + connection.authMethod === 'oauth_browser' ? 'oauth_browser' : 'password'; const extractor = new SnowflakeExtractor({ - account: connection.account.split('.')[0], + account: + sfAuthMethod === 'oauth_browser' + ? connection.account + : connection.account.split('.')[0], username: connection.username, password: connection.password, warehouse: connection.warehouse, database: connection.database, schema: connection.schema, role: connection.role, + authMethod: sfAuthMethod, }); await extractor.connect(); diff --git a/src/main/utils/connectors.ts b/src/main/utils/connectors.ts index a0260bf7..6f6f392a 100644 --- a/src/main/utils/connectors.ts +++ b/src/main/utils/connectors.ts @@ -22,6 +22,10 @@ import { import { SNOWFLAKE_TYPE_MAP } from './constants'; import SecureStorageService from '../services/secureStorage.service'; import { buildKineticaUrl } from '../../shared/kineticaUrl'; +import { + SNOWFLAKE_REAUTH_MESSAGE, + SnowflakeAuthManager, +} from './snowflakeAuth'; export async function testPostgresConnection( config: PostgresConnection, @@ -168,15 +172,38 @@ export const executeRedshiftQuery = async ( } }; -const createSnowflakeConnection = (config: SnowflakeConnection) => { - return snowflake.createConnection({ - account: config.account.split('.')[0], +const getSnowflakeAuthMethod = (config: SnowflakeConnection) => { + return config.authMethod || 'password'; +}; + +export const createSnowflakeConnection = (config: SnowflakeConnection) => { + const authMethod = getSnowflakeAuthMethod(config); + + const baseConfig = { username: config.username, - password: config.password, warehouse: config.warehouse, database: config.database, schema: config.schema, role: config.role, + }; + + if (authMethod === 'oauth_browser') { + return snowflake.createConnection({ + ...baseConfig, + account: config.account, + authenticator: 'OAUTH_AUTHORIZATION_CODE', + browserActionTimeout: 120000, + clientStoreTemporaryCredential: true, + openExternalBrowserCallback: () => { + throw new Error(SNOWFLAKE_REAUTH_MESSAGE); + }, + }); + } + + return snowflake.createConnection({ + ...baseConfig, + account: config.account.split('.')[0], + password: config.password, }); }; @@ -225,40 +252,63 @@ export const executeSnowflakeQuery = async ( registerCancel?: (fn: () => void) => void, ): Promise => { const connection = createSnowflakeConnection(config); + const authMethod = getSnowflakeAuthMethod(config); if (registerCancel) { registerCancel(() => { - connection.destroy(() => {}); + try { + connection.destroy(() => {}); + } catch (e) { + // ignore + } }); } - return new Promise((resolve) => { - connection.connect((err) => { - if (err) { - return resolve({ success: false, error: err.message }); - } + try { + if (authMethod === 'oauth_browser') { + // No browser flows outside the Connections screen: a cold session + // fails fast with guidance instead of opening an ungated popup. + // A warm SDK cache connects silently without user interaction. + SnowflakeAuthManager.assertCachedSession(); + await new Promise((resolve, reject) => { + connection.connectAsync((err) => { + if (err) return reject(err); + resolve(); + }); + }); + } else { + await new Promise((resolve, reject) => { + connection.connect((err) => { + if (err) return reject(err); + resolve(); + }); + }); + } + } catch (err: any) { + return { success: false, error: err.message }; + } - connection.execute({ - sqlText: query, - complete: (error, stmt, rows) => { - connection.destroy(() => {}); - if (error) { - return resolve({ success: false, error: error.message }); - } + return new Promise((resolve) => { + connection.execute({ + sqlText: query, + complete: (error, stmt, rows) => { + connection.destroy(() => {}); + if (error) { + return resolve({ success: false, error: error.message }); + } - const fields = - stmt?.getColumns().map((col) => ({ - name: col.getName(), - type: SNOWFLAKE_TYPE_MAP[col.getType().toUpperCase()] || 0, - })) || []; - - resolve({ - success: true, - data: rows, - fields, - }); - }, - }); + const fields = + stmt?.getColumns()?.map((col) => ({ + name: col.getName(), + type: SNOWFLAKE_TYPE_MAP[col.getType().toUpperCase()] || 0, + })) || []; + + resolve({ + success: true, + data: rows, + fields, + }); + }, }); }); }; diff --git a/src/main/utils/snowflakeAuth.ts b/src/main/utils/snowflakeAuth.ts new file mode 100644 index 00000000..7e0ecde9 --- /dev/null +++ b/src/main/utils/snowflakeAuth.ts @@ -0,0 +1,427 @@ +import * as path from 'path'; +import * as os from 'os'; +import * as fs from 'fs'; +import * as http from 'http'; +import { createHash } from 'crypto'; +import * as snowflake from 'snowflake-sdk'; +import { shell } from 'electron'; +import { + SnowflakeAuthEventPayload, + StartSnowflakeAuthRequest, +} from '../../types/ipc'; +import { + ConnectionTestResult, + SNOWFLAKE_REAUTH_MESSAGE, + SnowflakeConnection, +} from '../../types/backend'; + +export { SNOWFLAKE_REAUTH_MESSAGE }; + +// Snowflake SDK: snowflake-sdk ^3.3.0 (requires Node >= 16). +// OAuth uses OAUTH_AUTHORIZATION_CODE with the SDK-owned system-browser flow +// and local callback. The browser callback exposes this attempt's redirect +// port, so Cancel can stop that SDK flow without probing other local servers. +const BROWSER_ACTION_TIMEOUT_MS = 120000; + +export class SnowflakeAuthManager { + private static activeAttempts = new Map< + string, + { + connection: snowflake.Connection; + connectionKey: string; + abort: () => void; + reject: (err: any) => void; + } + >(); + + // One active browser attempt per Snowflake account+user. Guards duplicate + // Test clicks / double submits for the same connection while allowing + // immediate retry after cancel/finish (entries are released synchronously + // on cancel and in `finally` on every other path). + private static activeConnectionKeys = new Map(); + + private static validateStartRequest( + request: StartSnowflakeAuthRequest, + ): string | null { + if (!request || typeof request !== 'object') { + return 'Invalid authentication request.'; + } + if ( + !request.correlationId || + typeof request.correlationId !== 'string' || + !request.correlationId.trim() + ) { + return 'Missing correlation ID for authentication attempt.'; + } + if ( + !request.account || + typeof request.account !== 'string' || + !request.account.trim() + ) { + return 'Snowflake account identifier is required before starting browser authentication.'; + } + if ( + !request.username || + typeof request.username !== 'string' || + !request.username.trim() + ) { + return 'Snowflake username is required before starting browser authentication.'; + } + const missingField = ( + ['role', 'warehouse', 'database', 'schema'] as const + ).find( + (field) => typeof request[field] !== 'string' || !request[field]?.trim(), + ); + if (missingField) { + return `Snowflake ${missingField} is required before starting browser authentication.`; + } + return null; + } + + private static connectionKeyFor(account: string, username: string): string { + return `${account.trim().toLowerCase()}::${username.trim().toLowerCase()}`; + } + + private static releaseAttempt( + correlationId: string, + connectionKey?: string, + ): void { + this.activeAttempts.delete(correlationId); + if (connectionKey) { + if (this.activeConnectionKeys.get(connectionKey) === correlationId) { + this.activeConnectionKeys.delete(connectionKey); + } + } else { + const staleKeys: string[] = []; + this.activeConnectionKeys.forEach((id, key) => { + if (id === correlationId) { + staleKeys.push(key); + } + }); + staleKeys.forEach((key) => this.activeConnectionKeys.delete(key)); + } + } + + static async startAuth( + request: StartSnowflakeAuthRequest, + sendEvent: (payload: SnowflakeAuthEventPayload) => void, + ): Promise { + const validationError = this.validateStartRequest(request); + if (validationError) { + throw new Error(validationError); + } + + const { + correlationId, + account, + username, + warehouse, + database, + schema, + role, + } = request; + + if (this.activeAttempts.has(correlationId)) { + throw new Error('An authentication attempt is already in progress.'); + } + + const resolvedAccount = account.trim(); + const trimmedUsername = username.trim(); + const connectionKey = this.connectionKeyFor(account, username); + if (this.activeConnectionKeys.has(connectionKey)) { + throw new Error( + 'An authentication attempt for this Snowflake account and user is already in progress.', + ); + } + + sendEvent({ correlationId, status: 'started' }); + + let cancelled = false; + let redirectPort: number | undefined; + const abort = () => { + cancelled = true; + if (redirectPort) this.abortSdkCallbackServer(redirectPort); + }; + const connectionConfig: snowflake.ConnectionOptions = { + account: resolvedAccount, + username: trimmedUsername, + warehouse, + database, + schema, + role, + authenticator: 'OAUTH_AUTHORIZATION_CODE', + browserActionTimeout: BROWSER_ACTION_TIMEOUT_MS, + clientStoreTemporaryCredential: true, + openExternalBrowserCallback: (authorizationUrl) => { + const redirect = new URL( + new URL(authorizationUrl).searchParams.get('redirect_uri') ?? '', + ); + if ( + redirect.protocol !== 'http:' || + redirect.hostname !== '127.0.0.1' || + !redirect.port + ) { + throw new Error('Invalid Snowflake OAuth redirect URI.'); + } + redirectPort = Number(redirect.port); + if (cancelled) { + this.abortSdkCallbackServer(redirectPort); + return undefined; + } + return shell.openExternal(authorizationUrl); + }, + }; + + const connection = snowflake.createConnection(connectionConfig); + + // Register before invoking the SDK so cancel arriving in the race window + // still finds the attempt (previously the map was set inside the promise + // executor, after connectAsync was already called). + let resolveAttempt!: () => void; + let rejectAttempt!: (err: any) => void; + const attemptPromise = new Promise((resolve, reject) => { + resolveAttempt = resolve; + rejectAttempt = reject; + }); + this.activeAttempts.set(correlationId, { + connection, + connectionKey, + abort, + reject: rejectAttempt, + }); + this.activeConnectionKeys.set(connectionKey, correlationId); + + sendEvent({ correlationId, status: 'waiting_for_browser' }); + + try { + // connectAsync opens the browser when authenticator is OAUTH_AUTHORIZATION_CODE + connection.connectAsync((err) => { + if (err) { + rejectAttempt(err); + } else { + resolveAttempt(); + } + }); + + await attemptPromise; + + sendEvent({ correlationId, status: 'completed' }); + return { ok: true, authFlow: 'browser' }; + } catch (error: any) { + const message = error?.message || ''; + const lowercaseMessage = message.toLowerCase(); + + let testMessage = + 'Snowflake connection failed after browser authentication'; + let details = + 'Snowflake authentication failed. Check the connection settings and try again.'; + + if ( + /(cancel|timed out|timeout|did not complete|mfa token cache entry has expired)/i.test( + message, + ) + ) { + testMessage = 'Snowflake browser authentication failed'; + details = + 'Browser authentication did not complete. Finish the Snowflake sign-in flow and test again.'; + sendEvent({ correlationId, status: 'cancelled', error: details }); + } else if (lowercaseMessage.includes('role')) { + testMessage = 'Snowflake role authorization failed'; + details = + 'The selected Snowflake role is not authorized for this user.'; + sendEvent({ correlationId, status: 'failed', error: details }); + } else if (lowercaseMessage.includes('warehouse')) { + testMessage = 'Snowflake warehouse validation failed'; + details = + 'The selected Snowflake warehouse is unavailable or not authorized for this user.'; + sendEvent({ correlationId, status: 'failed', error: details }); + } else if ( + lowercaseMessage.includes('saml') || + lowercaseMessage.includes('sso') + ) { + testMessage = 'Snowflake SAML/SSO authentication failed'; + details = 'Snowflake SSO authentication failed. Try signing in again.'; + sendEvent({ correlationId, status: 'failed', error: details }); + } else if ( + lowercaseMessage.includes('url') || + lowercaseMessage.includes('redirect') || + lowercaseMessage.includes('not recognized') || + lowercaseMessage.includes('idp') + ) { + testMessage = 'Snowflake SSO redirect failed'; + details = 'The Account Locator value may be incorrect.'; + sendEvent({ correlationId, status: 'failed', error: details }); + } else { + sendEvent({ correlationId, status: 'failed', error: details }); + } + + return { + ok: false, + message: testMessage, + details, + authFlow: 'browser', + }; + } finally { + this.releaseAttempt(correlationId, connectionKey); + // Ensure we cleanup the connection to free resources + try { + connection.destroy(() => {}); + } catch (e) { + // Ignore destroy error + } + } + } + + // Fail fast when no cached OAuth session exists. Query and extract + // paths use this so a cold session redirects the user to the Connections + // screen instead of opening a second, ungated browser flow. + static assertCachedSession(): void { + if (!this.hasSnowflakeToken()) { + throw new Error(SNOWFLAKE_REAUTH_MESSAGE); + } + } + + // Reads the live OAuth access token from the Node SDK's own credential + // cache file (never from SDK memory internals). Used to hand the current + // session to dbt (Python driver) via process env at run time — the token + // is never written to profiles, logs, or renderer state. Validate the + // named session silently before reading its identity-specific cache entry. + static async readCachedOAuthAccessToken( + namedConnection: SnowflakeConnection, + ): Promise { + if (!this.hasSnowflakeToken()) return null; + + const options: snowflake.ConnectionOptions = { + account: namedConnection.account, + username: namedConnection.username, + warehouse: namedConnection.warehouse, + database: namedConnection.database, + schema: namedConnection.schema, + role: namedConnection.role, + authenticator: 'OAUTH_AUTHORIZATION_CODE', + clientStoreTemporaryCredential: true, + openExternalBrowserCallback: () => { + throw new Error(SNOWFLAKE_REAUTH_MESSAGE); + }, + }; + let connection: snowflake.Connection | undefined; + try { + connection = snowflake.createConnection(options); + const sdkConnection = connection; + await new Promise((resolve, reject) => { + Promise.resolve( + sdkConnection.connectAsync((error) => + error ? reject(error) : resolve(), + ), + ).catch(reject); + }); + // The SDK resolves host/accessUrl in createConnection and hashes these + // fields with the username, OAuth token URL, and role for its cache key. + if (!options.host || !options.accessUrl) return null; + const normalize = (value: string) => + value.includes('"') ? value : value.toLowerCase(); + const hash = createHash('sha256') + .update( + JSON.stringify({ + snowflakeHost: options.host, + username: normalize(namedConnection.username), + oauthIdpUrl: `${options.accessUrl}/oauth/token-request`, + role: namedConnection.role + ? normalize(namedConnection.role) + : undefined, + }), + 'utf8', + ) + .digest('hex'); + const raw = fs.readFileSync(this.getSnowflakeCacheFile(), 'utf8'); + const parsed: unknown = JSON.parse(raw); + if (!parsed || typeof parsed !== 'object') { + return null; + } + const { tokens } = parsed as { tokens?: unknown }; + if (!tokens || typeof tokens !== 'object') { + return null; + } + const record = tokens as Record; + const accessToken = + record[`SnowflakeTokenCache.v2.OauthAccessToken.${hash}`]; + const refreshToken = + record[`SnowflakeTokenCache.v2.OauthRefreshToken.${hash}`]; + return typeof accessToken === 'string' && + accessToken.length > 0 && + typeof refreshToken === 'string' && + refreshToken.length > 0 + ? accessToken + : null; + } catch (e) { + return null; + } finally { + try { + connection?.destroy(() => {}); + } catch (e) { + // Ignore cleanup errors after the cache check. + } + } + } + + static cancelAuth(correlationId: string): void { + const attempt = this.activeAttempts.get(correlationId); + if (!attempt) { + return; + } + // Release synchronously so a new Test click can start immediately. + this.releaseAttempt(correlationId, attempt.connectionKey); + attempt.reject(new Error('Cancelled by user')); + try { + attempt.connection.destroy(() => {}); + } catch (e) { + // Ignore destroy error + } + // destroy() does not stop the SDK's callback wait; signal its exact port. + attempt.abort(); + } + + private static abortSdkCallbackServer(port: number): void { + const req = http.get( + `http://127.0.0.1:${port}/?error=cancelled_by_user`, + (res) => res.resume(), + ); + req.setTimeout(3000, () => req.destroy()); + req.on('error', () => {}); + } + + private static getSnowflakeCacheFile(): string { + let cacheDir = ''; + if (process.platform === 'win32') { + cacheDir = path.join( + process.env.USERPROFILE || '', + 'AppData/Local/Snowflake/Caches', + ); + } else if (process.platform === 'darwin') { + cacheDir = path.join(os.homedir(), 'Library/Caches/Snowflake'); + } else { + cacheDir = path.join(os.homedir(), '.cache/snowflake'); + } + return path.join(cacheDir, 'credential_cache_v1.json'); + } + + static hasSnowflakeToken(): boolean { + try { + return fs.existsSync(this.getSnowflakeCacheFile()); + } catch (e) { + return false; + } + } + + static revokeSnowflakeToken(): boolean { + try { + const cacheFile = this.getSnowflakeCacheFile(); + if (fs.existsSync(cacheFile)) { + fs.unlinkSync(cacheFile); + } + return true; + } catch { + return false; + } + } +} diff --git a/src/main/utils/yamlPartialUpdate.ts b/src/main/utils/yamlPartialUpdate.ts index 6f0aaba0..bddbe1d5 100644 --- a/src/main/utils/yamlPartialUpdate.ts +++ b/src/main/utils/yamlPartialUpdate.ts @@ -9,7 +9,7 @@ import fs from 'fs'; import yaml from 'js-yaml'; import path from 'path'; -import { ConnectionInput } from '../../types/backend'; +import { ConnectionInput, SnowflakeConnection } from '../../types/backend'; import { buildKineticaUrl } from '../../shared/kineticaUrl'; import { buildKineticaProfileOutput } from './kineticaProfile'; @@ -61,18 +61,32 @@ function generateProfileOutputFields( schema: envVar('schema'), }; - case 'snowflake': - return { + case 'snowflake': { + const isOauth = connection.authMethod === 'oauth_browser'; + const result: any = { ...baseFields, account: envVar('account'), user: envVar('user'), - password: envVar('password'), role: envVar('role'), database: envVar('dbname'), warehouse: envVar('warehouse'), schema: envVar('schema'), }; + if (isOauth) { + // Token comes from `db-token-` process env, materialized + // main-side from the live SDK session at dbt run time (never written + // to files). Plain `oauth` never opens a browser: a missing/expired + // token fails fast with guidance instead. + result.authenticator = 'oauth'; + result.token = envVar('token'); + } else { + result.password = envVar('password'); + } + + return result; + } + case 'bigquery': return { ...baseFields, @@ -151,8 +165,13 @@ function generateJdbcUrl( case 'postgres': return `jdbc:postgresql://${ev('host')}:${ev('port')}/${ev('dbname')}?currentSchema=${ev('schema')}`; - case 'snowflake': - return `jdbc:snowflake://${ev('account')}.snowflakecomputing.com/?warehouse=${ev('warehouse')}&db=${ev('dbname')}&schema=${ev('schema')}`; + case 'snowflake': { + let url = `jdbc:snowflake://${ev('account')}.snowflakecomputing.com/?warehouse=${ev('warehouse')}&db=${ev('dbname')}&schema=${ev('schema')}`; + if (connection.authMethod === 'oauth_browser') { + url += '&authenticator=oauth_authorization_code'; + } + return url; + } case 'redshift': return `jdbc:redshift://${ev('host')}:${ev('port')}/${ev('dbname')}?currentSchema=${ev('schema')}`; @@ -247,6 +266,25 @@ export async function updateProfilesYml( ...newFields, // Override with new connection fields }; + // For Snowflake: explicitly enforce password/token vs authenticator + // fields because the merge above may keep stale values from a previous + // profile (including the retired oauth_authorization_code form). + if (connection.type === 'snowflake') { + if ((connection as SnowflakeConnection).authMethod === 'oauth_browser') { + delete profiles[projectName].outputs.dev.password; + delete profiles[projectName].outputs.dev + .client_store_temporary_credential; + profiles[projectName].outputs.dev.authenticator = 'oauth'; + profiles[projectName].outputs.dev.token = + `{{ env_var("db-token-${connection.name}") }}`; + } else { + delete profiles[projectName].outputs.dev.authenticator; + delete profiles[projectName].outputs.dev.token; + delete profiles[projectName].outputs.dev + .client_store_temporary_credential; + } + } + // Write back to file const updatedContent = yaml.dump(profiles, { indent: 2, @@ -342,11 +380,22 @@ export async function updateMainConf( const typesWithoutCredentials = ['bigquery', 'databricks', 'duckdb']; if (!typesWithoutCredentials.includes(connection.type)) { connectionEntry.userName = ev('user'); - connectionEntry.password = ev('password'); + if ( + connection.type === 'snowflake' && + (connection as SnowflakeConnection).authMethod === 'oauth_browser' + ) { + delete connectionEntry.password; + // Snowflake Local Application OAuth (SNOWFLAKE$LOCAL_APPLICATION built-in) + connectionEntry.authenticator = 'oauth_authorization_code'; + } else { + connectionEntry.password = ev('password'); + delete connectionEntry.authenticator; + } } else { // Remove userName/password if they exist but shouldn't for this type delete connectionEntry.userName; delete connectionEntry.password; + delete connectionEntry.authenticator; } // For Databricks, handle token diff --git a/src/renderer/components/connections/BrowserAuthenticationGate.tsx b/src/renderer/components/connections/BrowserAuthenticationGate.tsx new file mode 100644 index 00000000..83ebf5ed --- /dev/null +++ b/src/renderer/components/connections/BrowserAuthenticationGate.tsx @@ -0,0 +1,132 @@ +import React from 'react'; +import { + Dialog, + DialogContent, + DialogTitle, + Typography, + Button, + CircularProgress, + Box, + DialogActions, +} from '@mui/material'; +import { Close as CloseIcon } from '@mui/icons-material'; + +type GateStatus = + | 'idle' + | 'started' + | 'waiting_for_browser' + | 'completed' + | 'cancelled' + | 'failed'; + +interface Props { + open: boolean; + status: GateStatus; + onCancel: () => void; + error?: string; +} + +const BrowserAuthenticationGate: React.FC = ({ + open, + status, + onCancel, + error, +}) => { + const isCancellable = + status === 'started' || status === 'waiting_for_browser'; + const hasFinished = + status === 'completed' || status === 'cancelled' || status === 'failed'; + + return ( + + + Snowflake Browser Authentication + + + + {status === 'started' && ( + <> + + + Starting authentication flow... + + + )} + + {status === 'waiting_for_browser' && ( + <> + + + Waiting for browser sign-in... + + + Please complete the authentication and MFA in your web browser. + + + )} + + {status === 'completed' && ( + + Authentication Successful! + + )} + + {status === 'cancelled' && ( + <> + + Authentication Cancelled + + + You cancelled the sign-in flow. + + + )} + + {status === 'failed' && ( + <> + + Authentication Failed + + + {error || 'An unknown error occurred.'} + + + )} + + + + + + + ); +}; + +export default BrowserAuthenticationGate; diff --git a/src/renderer/components/connections/snowflake.tsx b/src/renderer/components/connections/snowflake.tsx index 1748f6f6..16ad19cb 100644 --- a/src/renderer/components/connections/snowflake.tsx +++ b/src/renderer/components/connections/snowflake.tsx @@ -8,6 +8,8 @@ import { CircularProgress, IconButton, InputAdornment, + Tabs, + Tab, } from '@mui/material'; import { Visibility, VisibilityOff } from '@mui/icons-material'; import { toast } from 'react-toastify'; @@ -18,10 +20,18 @@ import { useTestConnection, useUpdateConnection, useGetConnections, + useHasSnowflakeToken, + useRevokeSnowflakeToken, } from '../../controllers'; +import { + startSnowflakeAuth, + cancelSnowflakeAuth, + onSnowflakeAuthEvent, +} from '../../services/connectors.service'; import ConnectionHeader from './connection-header'; import useSecureStorage from '../../hooks/useSecureStorage'; import { useConnectionNameValidation } from '../../utils/connectionValidation'; +import BrowserAuthenticationGate from './BrowserAuthenticationGate'; type Props = { onCancel: () => void; @@ -76,8 +86,60 @@ export const Snowflake: React.FC = ({ username: '', password: '', role: existingConnection?.role ?? duplicateConnection?.role ?? 'SYSADMIN', + authMethod: + existingConnection?.authMethod ?? + duplicateConnection?.authMethod ?? + 'password', + }); + + const [gateState, setGateState] = React.useState<{ + open: boolean; + status: any; + error?: string; + correlationId?: string; + }>({ + open: false, + status: 'idle', }); + // Tracks the in-flight OAuth attempt so duplicate Test clicks are ignored + // and unmount/route-change can cancel before disposing local state. + const activeCorrelationIdRef = React.useRef(undefined); + + const validateOAuthFields = (): string | null => { + if (!formState.account.trim()) return 'Account identifier is required.'; + if (!formState.username.trim()) return 'Username is required.'; + if (!formState.warehouse.trim()) return 'Warehouse is required.'; + if (!formState.database.trim()) return 'Database is required.'; + if (!formState.schema.trim()) return 'Schema is required.'; + if (!formState.role?.trim()) return 'Role is required.'; + return null; + }; + + React.useEffect(() => { + const unsub = onSnowflakeAuthEvent((payload) => { + setGateState((prev) => { + if (prev.correlationId !== payload.correlationId) return prev; + return { + ...prev, + status: payload.status, + error: payload.error, + }; + }); + }); + return () => { + unsub(); + // Idempotent cleanup: cancel any in-flight attempt on unmount so an + // old callback cannot unlock a new attempt. + if (activeCorrelationIdRef.current) { + cancelSnowflakeAuth(activeCorrelationIdRef.current).catch( + () => undefined, + ); + activeCorrelationIdRef.current = undefined; + } + }; + }, []); + const { mutate: testConnection, isLoading: isTesting } = useTestConnection({ onSuccess: (success) => { if (success) { @@ -109,6 +171,28 @@ export const Snowflake: React.FC = ({ }, }); + const { data: hasToken, refetch: refetchHasToken } = useHasSnowflakeToken(); + const { mutate: revokeToken, isLoading: isRevoking } = + useRevokeSnowflakeToken(); + + const handleRevokeToken = () => { + revokeToken(formState.name, { + onSuccess: (success) => { + if (success) { + toast.success( + 'Snowflake cached token revoked. You will be prompted to log in again.', + ); + refetchHasToken(); + } else { + toast.error('Failed to revoke token. Cache file might not exist.'); + } + }, + onError: (err) => { + toast.error(`Error revoking token: ${(err as Error).message}`); + }, + }); + }; + const { mutate: updateConnection, isLoading: isUpdating } = useUpdateConnection({ onSuccess: () => { @@ -192,8 +276,23 @@ export const Snowflake: React.FC = ({ return; } - await setDatabaseUsername(formState.username, formState.name); - await setDatabasePassword(formState.password, formState.name); + // OAuth mode must never persist a password: tokens stay in the SDK + // temporary credential cache, never in secure storage / files / logs. + if (formState.authMethod === 'oauth_browser') { + if (connectionStatus !== 'success') { + toast.error('Test the browser connection successfully before saving.'); + return; + } + const oauthError = validateOAuthFields(); + if (oauthError) { + toast.error(oauthError); + return; + } + await setDatabaseUsername(formState.username, formState.name); + } else { + await setDatabaseUsername(formState.username, formState.name); + await setDatabasePassword(formState.password, formState.name); + } await setConnectionField('account', formState.account, formState.name); await setConnectionField('warehouse', formState.warehouse, formState.name); await setConnectionField('dbname', formState.database, formState.name); @@ -220,9 +319,69 @@ export const Snowflake: React.FC = ({ }); }; - const handleTest = () => { + const handleTest = async () => { setConnectionStatus('idle'); - testConnection(formState); + if (formState.authMethod === 'oauth_browser') { + // Single-flight guard: ignore duplicate Test clicks while the gate + // (modal) is already blocking for an active attempt. + if (gateState.open || activeCorrelationIdRef.current) { + return; + } + const oauthError = validateOAuthFields(); + if (oauthError) { + toast.error(oauthError); + return; + } + const correlationId = crypto.randomUUID(); + activeCorrelationIdRef.current = correlationId; + setGateState({ open: true, status: 'started', correlationId }); + try { + const result: any = await startSnowflakeAuth({ + correlationId, + account: formState.account.trim(), + username: formState.username.trim(), + warehouse: formState.warehouse.trim(), + database: formState.database.trim(), + schema: formState.schema.trim(), + role: formState.role?.trim() || '', + }); + if (activeCorrelationIdRef.current !== correlationId) return; + if (result.ok) { + toast.success( + 'Connection test successful. Snowflake may reuse a cached OAuth session without opening the browser.', + ); + setConnectionStatus('success'); + } else { + toast.error(`Test failed: ${result.message}`); + setConnectionStatus('failed'); + } + } catch (err: any) { + if (activeCorrelationIdRef.current !== correlationId) return; + toast.error(`Test failed: ${err.message}`); + setConnectionStatus('failed'); + setGateState((prev) => ({ + ...prev, + status: 'failed', + error: err.message, + })); + } finally { + if (activeCorrelationIdRef.current === correlationId) { + activeCorrelationIdRef.current = undefined; + } + } + } else { + testConnection(formState); + } + }; + + const handleCancelAuth = () => { + const correlationId = + activeCorrelationIdRef.current ?? gateState.correlationId; + if (correlationId) { + cancelSnowflakeAuth(correlationId).catch(() => undefined); + activeCorrelationIdRef.current = undefined; + } + setGateState((prev) => ({ ...prev, open: false })); }; const getIndicatorColor = () => { @@ -257,6 +416,13 @@ export const Snowflake: React.FC = ({ isLoading={isUpdating || isConfiguring} /> + + = ({ placeholder="xy12345.us-east-2.aws" /> + { + setConnectionStatus('idle'); + setFormState((prev) => ({ ...prev, authMethod: val })); + }} + indicatorColor="primary" + textColor="primary" + variant="fullWidth" + sx={{ mb: 1, borderBottom: 1, borderColor: 'divider' }} + > + + + + = ({ fullWidth /> - - setShowPassword(!showPassword)} - onMouseDown={(e) => e.preventDefault()} - edge="end" - > - {showPassword ? : } - - - ), - }, - }} - /> + {formState.authMethod !== 'oauth_browser' && ( + + setShowPassword(!showPassword)} + onMouseDown={(e) => e.preventDefault()} + edge="end" + > + {showPassword ? : } + + + ), + }, + }} + /> + )} = ({ variant="contained" color="primary" onClick={handleTest} - disabled={isTesting} + disabled={isTesting || gateState.open} sx={{ mr: 2, position: 'relative', @@ -404,6 +587,19 @@ export const Snowflake: React.FC = ({ }} /> + + {formState.authMethod === 'oauth_browser' && hasToken && ( + + )} diff --git a/src/renderer/components/sqlEditor/index.tsx b/src/renderer/components/sqlEditor/index.tsx index 896a6af0..480f9e84 100644 --- a/src/renderer/components/sqlEditor/index.tsx +++ b/src/renderer/components/sqlEditor/index.tsx @@ -6,7 +6,11 @@ import { Inputs, RelativeContainer } from './styles'; import { connectorsServices, projectsServices } from '../../services'; import { DuckLakeService } from '../../services/duckLake.service'; import { QueryHistoryType } from '../../../types/frontend'; -import { ConnectionInput, Project } from '../../../types/backend'; +import { + ConnectionInput, + Project, + SNOWFLAKE_REAUTH_MESSAGE, +} from '../../../types/backend'; import { SqlEditorComponent } from './editorComponent'; import { useAppContext } from '../../hooks'; import { useSqlEditorBridge } from '../../controllers'; @@ -180,6 +184,12 @@ export const SqlEditor: React.FC = ({ if (result.error) { setError(result.error); + // Missing Snowflake session: toast the shared guidance so it is + // visible even when the results pane is out of view. All other + // query errors keep their existing inline-only display. + if (result.error === SNOWFLAKE_REAUTH_MESSAGE) { + toast.error(result.error); + } setLoadingQuery(false); return; } diff --git a/src/renderer/context/AppProvider.tsx b/src/renderer/context/AppProvider.tsx index 1bbac1b4..7bf80f8e 100644 --- a/src/renderer/context/AppProvider.tsx +++ b/src/renderer/context/AppProvider.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { toast } from 'react-toastify'; import { AppContextType } from '../../types/frontend'; import { Splash } from '../components'; import { @@ -150,6 +151,11 @@ const AppProvider: React.FC = ({ children }) => { setLastFetchedProjectId(null); // eslint-disable-next-line no-console console.error('Failed to fetch schema:', error); + toast.error( + `Failed to fetch schema: ${ + error instanceof Error ? error.message : 'Unknown error' + }`, + ); } finally { setIsLoadingSchema(false); } diff --git a/src/renderer/context/RunnerProvider.tsx b/src/renderer/context/RunnerProvider.tsx index ecc010ce..97302c15 100644 --- a/src/renderer/context/RunnerProvider.tsx +++ b/src/renderer/context/RunnerProvider.tsx @@ -8,6 +8,7 @@ import React, { } from 'react'; import { useSecureStorage } from '../hooks'; import { useSetConnectionEnvVariable } from '../controllers'; +import { materializeSnowflakeToken } from '../services/connectors.service'; export interface RunnerLogEntry { message: string; @@ -204,6 +205,13 @@ export const RunnerProvider: React.FC = ({ children }) => { ); } + // Snowflake OAuth: hand the live session token to dbt via process + // env (main-side; the token never enters the renderer). Self-gating + // main-side: no-op unless the named connection is snowflake+oauth. + if (connType === 'snowflake') { + await materializeSnowflakeToken(connectionName).catch(() => false); + } + if (connType) { const fieldMap: Record = { postgres: ['host', 'port', 'dbname', 'schema'], diff --git a/src/renderer/controllers/connectors.controller.ts b/src/renderer/controllers/connectors.controller.ts index 79335ac3..a2618a48 100644 --- a/src/renderer/controllers/connectors.controller.ts +++ b/src/renderer/controllers/connectors.controller.ts @@ -383,3 +383,18 @@ export const useUpdateConnectionQuery = ( }, }); }; + +export const useHasSnowflakeToken = () => { + return useQuery(['hasSnowflakeToken'], connectorsServices.hasSnowflakeToken, { + refetchOnWindowFocus: true, + }); +}; + +export const useRevokeSnowflakeToken = () => { + const queryClient = useQueryClient(); + return useMutation(connectorsServices.revokeSnowflakeToken, { + onSuccess: () => { + queryClient.invalidateQueries(['hasSnowflakeToken']); + }, + }); +}; diff --git a/src/renderer/hooks/useDbt.ts b/src/renderer/hooks/useDbt.ts index 07706b3a..29488af6 100644 --- a/src/renderer/hooks/useDbt.ts +++ b/src/renderer/hooks/useDbt.ts @@ -9,7 +9,13 @@ import { useCheckProjectAdapterCompatibility, useSetConnectionEnvVariable, } from '../controllers'; -import { Project, DbtCommandType, ConnectionInput } from '../../types/backend'; +import { + Project, + DbtCommandType, + ConnectionInput, + SNOWFLAKE_REAUTH_MESSAGE, +} from '../../types/backend'; +import { materializeSnowflakeToken } from '../services/connectors.service'; import { useAppContext } from './index'; import { extractCliErrorDetails } from '../utils/dbtCommandResult'; import { useDbtRunHistory } from './useDbtRunHistory'; @@ -33,6 +39,17 @@ interface UseDbtReturn { activeCommand: DbtCommandType | null; } +const hasSnowflakeOAuthSession = (connection: ConnectionInput) => { + if ( + connection.type !== 'snowflake' || + connection.authMethod !== 'oauth_browser' + ) { + return Promise.resolve(true); + } + // The token stays in main; only the connection name crosses IPC. + return materializeSnowflakeToken(connection.name).catch(() => false); +}; + const useDbt = ( successCallback?: () => void, cloudRunCb?: (command: DbtCommandType) => void, @@ -282,6 +299,10 @@ const useDbt = ( connection.connection.name, connection.connection, ); + if (!(await hasSnowflakeOAuthSession(connection.connection))) { + if (options.showToast) toast.error(SNOWFLAKE_REAUTH_MESSAGE); + return; + } // Build command string const cmdString = buildCommand(command, project, args); @@ -422,6 +443,10 @@ const useDbt = ( connection.connection.name, connection.connection, ); + if (!(await hasSnowflakeOAuthSession(connection.connection))) { + toast.error(SNOWFLAKE_REAUTH_MESSAGE); + return ''; + } // Build command string const cmdString = buildCommand( @@ -551,6 +576,10 @@ const useDbt = ( connection.connection.name, connection.connection, ); + if (!(await hasSnowflakeOAuthSession(connection.connection))) { + toast.error(SNOWFLAKE_REAUTH_MESSAGE); + return ''; + } const cmdString = buildCommand('list', project, ''); if (!cmdString) { return ''; diff --git a/src/renderer/screens/notebooks/index.tsx b/src/renderer/screens/notebooks/index.tsx index 69330fd5..28adbbf4 100644 --- a/src/renderer/screens/notebooks/index.tsx +++ b/src/renderer/screens/notebooks/index.tsx @@ -344,6 +344,7 @@ const Notebooks = () => { if (result.error) { // eslint-disable-next-line no-console console.error('Failed to fetch schema:', result.error); + toast.error(`Failed to fetch schema: ${result.error}`); setTabSchemas((prev) => ({ ...prev, [connectionId]: [] })); } else { setTabSchemas((prev) => ({ @@ -355,6 +356,9 @@ const Notebooks = () => { } catch (error: any) { // eslint-disable-next-line no-console console.error('Failed to fetch schema:', error); + toast.error( + `Failed to fetch schema: ${error?.message ?? 'Unknown error'}`, + ); setTabSchemas((prev) => ({ ...prev, [connectionId]: [] })); } finally { setLoadingSchemas((prev) => ({ ...prev, [connectionId]: false })); diff --git a/src/renderer/screens/sql/index.tsx b/src/renderer/screens/sql/index.tsx index 403e33e9..8fe86149 100644 --- a/src/renderer/screens/sql/index.tsx +++ b/src/renderer/screens/sql/index.tsx @@ -473,6 +473,7 @@ const Sql = () => { if (result.error) { // eslint-disable-next-line no-console console.error('Failed to fetch schema:', result.error); + toast.error(`Failed to fetch schema: ${result.error}`); setTabSchemas((prev) => ({ ...prev, [connectionId]: [] })); } else { setTabSchemas((prev) => ({ ...prev, [connectionId]: result.tables })); @@ -480,6 +481,9 @@ const Sql = () => { } catch (error: any) { // eslint-disable-next-line no-console console.error('Failed to fetch schema:', error); + toast.error( + `Failed to fetch schema: ${error?.message ?? 'Unknown error'}`, + ); setTabSchemas((prev) => ({ ...prev, [connectionId]: [] })); } finally { setLoadingSchemas((prev) => ({ ...prev, [connectionId]: false })); diff --git a/src/renderer/services/connectors.service.ts b/src/renderer/services/connectors.service.ts index e600f78a..e330caa6 100644 --- a/src/renderer/services/connectors.service.ts +++ b/src/renderer/services/connectors.service.ts @@ -5,8 +5,14 @@ import { QueryResponseType, BigQueryTestResponse, ConnectionModel, + ConnectorTestResponse, } from '../../types/backend'; -import { ConfigureConnectionBody, UpdateConnectionBody } from '../../types/ipc'; +import { + ConfigureConnectionBody, + UpdateConnectionBody, + StartSnowflakeAuthRequest, + SnowflakeAuthEventPayload, +} from '../../types/ipc'; export const configureConnection = async ( body: ConfigureConnectionBody, @@ -165,3 +171,65 @@ export const executeQueryForConnection = async (body: { >('connector:executeQuery', body); return data; }; + +export const startSnowflakeAuth = async ( + request: StartSnowflakeAuthRequest, +): Promise => { + const { data } = await client.post< + StartSnowflakeAuthRequest, + ConnectorTestResponse + >('connector:snowflake:auth:start', request); + return data; +}; + +export const cancelSnowflakeAuth = async ( + correlationId: string, +): Promise => { + await client.post( + 'connector:snowflake:auth:cancel', + correlationId, + ); +}; + +export const onSnowflakeAuthEvent = ( + listener: (payload: SnowflakeAuthEventPayload) => void, +) => { + const handler = (...args: unknown[]) => { + listener(args[0] as SnowflakeAuthEventPayload); + }; + return window.electron.ipcRenderer.on( + 'connector:snowflake:auth:event', + handler, + ); +}; + +export const hasSnowflakeToken = async (): Promise => { + const { data } = await client.post( + 'connector:snowflake:auth:hasToken', + undefined, + ); + return data; +}; + +export const revokeSnowflakeToken = async ( + connectionName: string, +): Promise => { + const { data } = await client.post<{ connectionName: string }, boolean>( + 'connector:snowflake:auth:revoke', + { connectionName }, + ); + return data; +}; + +// Hands the live Snowflake OAuth access token to dbt via process env. +// Only the connection name crosses IPC; the token itself never enters the +// renderer. Returns true when a token was materialized. +export const materializeSnowflakeToken = async ( + connectionName: string, +): Promise => { + const { data } = await client.post<{ connectionName: string }, boolean>( + 'connector:snowflake:auth:materialize', + { connectionName }, + ); + return data; +}; diff --git a/src/types/backend.ts b/src/types/backend.ts index 23d1913d..d15b7feb 100644 --- a/src/types/backend.ts +++ b/src/types/backend.ts @@ -36,12 +36,21 @@ export type PostgresConnection = ConnectionBase & { sslRejectUnauthorized?: boolean; }; +export type SnowflakeAuthMethod = 'password' | 'oauth_browser'; + +// Shown verbatim by every screen when a Snowflake OAuth session is missing. +// Single source of truth shared by main and renderer so all three screens +// display identical guidance. +export const SNOWFLAKE_REAUTH_MESSAGE = + 'Snowflake session not found or expired. Open the Connections screen, select this Snowflake connection, and click Test Connection to sign in again in the browser.'; + export type SnowflakeConnection = ConnectionBase & { type: 'snowflake'; account: string; warehouse: string; role?: string; client_session_keep_alive?: boolean; + authMethod?: SnowflakeAuthMethod; }; export type BigQueryConnection = ConnectionBase & { @@ -152,13 +161,16 @@ export type PostgresDBTConnection = DBTConnectionBase & { ssl?: boolean; }; -export type SnowflakeDBTConnection = DBTConnectionBase & { +export type SnowflakeDBTConnection = Omit & { type: 'snowflake'; + password?: string; account: string; warehouse: string; role?: string; client_session_keep_alive?: boolean; query_tag?: string; + authMethod?: SnowflakeAuthMethod; + authenticator?: 'oauth_authorization_code' | 'externalbrowser'; }; export type BigQueryDBTConnection = DBTConnectionBase & { @@ -763,6 +775,19 @@ export type BigQueryTestResponse = { success: boolean; }; +export type ConnectionTestResult = { + ok: boolean; + code?: string; + message?: string; + details?: string; + authFlow?: 'none' | 'browser'; +}; + +export type ConnectorTestResponse = + | boolean + | BigQueryTestResponse + | ConnectionTestResult; + export type UpdateInfo = { currentVersion: string; newVersion: string; diff --git a/src/types/ipc.ts b/src/types/ipc.ts index fedabfbd..610c9609 100644 --- a/src/types/ipc.ts +++ b/src/types/ipc.ts @@ -128,7 +128,13 @@ export type ConnectorChannels = | 'connector:updateQuery' | 'connector:getQuery' | 'connector:executeQuery' - | 'connector:save'; + | 'connector:save' + | 'connector:snowflake:auth:start' + | 'connector:snowflake:auth:cancel' + | 'connector:snowflake:auth:revoke' + | 'connector:snowflake:auth:materialize' + | 'connector:snowflake:auth:hasToken' + | 'connector:snowflake:auth:event'; export type SourcesChannels = | 'sources:create' @@ -748,3 +754,26 @@ export interface DeleteBucketRequest { export interface DeleteBucketResponse { success: boolean; } + +export type SnowflakeAuthLifecycleEvent = + | 'started' + | 'waiting_for_browser' + | 'completed' + | 'cancelled' + | 'failed'; + +export type SnowflakeAuthEventPayload = { + correlationId: string; + status: SnowflakeAuthLifecycleEvent; + error?: string; +}; + +export type StartSnowflakeAuthRequest = { + correlationId: string; + account: string; + username: string; + warehouse: string; + database: string; + schema: string; + role: string; +}; diff --git a/tests/unit/main/services/connectors.service.test.ts b/tests/unit/main/services/connectors.service.test.ts index 0e0fea95..8e4b4af9 100644 --- a/tests/unit/main/services/connectors.service.test.ts +++ b/tests/unit/main/services/connectors.service.test.ts @@ -1,4 +1,34 @@ +/* eslint-disable import/first */ import fs from 'fs'; + +// Stub @aws-sdk (pulled in via cloudExplorer.service in the import graph; +// the real dist-cjs bundle cannot be parsed by jest). +jest.mock('@aws-sdk/client-s3', () => { + const Dummy = class {}; + return { + S3Client: Dummy, + ListBucketsCommand: Dummy, + ListObjectsV2Command: Dummy, + ListObjectsCommand: Dummy, + GetObjectCommand: Dummy, + PutObjectCommand: Dummy, + CreateMultipartUploadCommand: Dummy, + UploadPartCommand: Dummy, + CompleteMultipartUploadCommand: Dummy, + AbortMultipartUploadCommand: Dummy, + DeleteObjectCommand: Dummy, + DeleteObjectsCommand: Dummy, + CreateBucketCommand: Dummy, + DeleteBucketCommand: Dummy, + ListObjectVersionsCommand: Dummy, + HeadBucketCommand: Dummy, + }; +}); + +jest.mock('@aws-sdk/s3-request-presigner', () => ({ + getSignedUrl: jest.fn(), +})); + import ConnectorsService from '../../../../src/main/services/connectors.service'; import { ProjectsService } from '../../../../src/main/services'; diff --git a/tests/unit/main/utils/snowflakeAuth.test.ts b/tests/unit/main/utils/snowflakeAuth.test.ts new file mode 100644 index 00000000..44156e3f --- /dev/null +++ b/tests/unit/main/utils/snowflakeAuth.test.ts @@ -0,0 +1,253 @@ +/* eslint-disable import/first */ +jest.mock('snowflake-sdk', () => ({ + createConnection: jest.fn(), +})); + +// Import after mock so the manager uses the mocked SDK. +import * as net from 'net'; +import * as snowflake from 'snowflake-sdk'; +import { shell } from 'electron'; +import { + SNOWFLAKE_REAUTH_MESSAGE, + SnowflakeAuthManager, +} from '../../../../src/main/utils/snowflakeAuth'; + +const createConnectionMock = snowflake.createConnection as jest.Mock; + +const baseRequest = (overrides: Record = {}) => ({ + correlationId: 'corr-1', + account: 'xy12345.us-east-2.aws', + username: 'alice', + warehouse: 'COMPUTE_WH', + database: 'DB', + schema: 'PUBLIC', + role: 'SYSADMIN', + ...overrides, +}); + +const noopSend = jest.fn(); + +describe('SnowflakeAuthManager (OAuth browser slice)', () => { + beforeEach(() => { + jest.clearAllMocks(); + noopSend.mockClear(); + // Release static guards between tests (cancel unknown ids is a no-op). + SnowflakeAuthManager.cancelAuth('corr-1'); + SnowflakeAuthManager.cancelAuth('corr-2'); + SnowflakeAuthManager.cancelAuth('corr-3'); + }); + + it('rejects requests with missing account/username/correlationId without invoking the SDK', async () => { + await expect( + SnowflakeAuthManager.startAuth( + baseRequest({ account: ' ' }) as any, + noopSend, + ), + ).rejects.toThrow(/account identifier/i); + await expect( + SnowflakeAuthManager.startAuth( + baseRequest({ username: '' }) as any, + noopSend, + ), + ).rejects.toThrow(/username/i); + await expect( + SnowflakeAuthManager.startAuth( + baseRequest({ correlationId: '' }) as any, + noopSend, + ), + ).rejects.toThrow(/correlation/i); + await expect( + SnowflakeAuthManager.startAuth( + baseRequest({ role: '' }) as any, + noopSend, + ), + ).rejects.toThrow(/role/i); + expect(createConnectionMock).not.toHaveBeenCalled(); + }); + + it('rejects a duplicate correlationId while an attempt is active', async () => { + const hanging = { + connectAsync: jest.fn(() => undefined), + destroy: jest.fn(() => undefined), + }; + createConnectionMock.mockReturnValueOnce(hanging); + + const pending = SnowflakeAuthManager.startAuth( + baseRequest({ correlationId: 'corr-1' }) as any, + noopSend, + ); + // Second start with the same correlationId must fail fast. + await expect( + SnowflakeAuthManager.startAuth( + baseRequest({ correlationId: 'corr-1' }) as any, + noopSend, + ), + ).rejects.toThrow(/already in progress/i); + + SnowflakeAuthManager.cancelAuth('corr-1'); + const result = await pending; + expect(result.ok).toBe(false); + expect(noopSend).toHaveBeenCalledWith( + expect.objectContaining({ + correlationId: 'corr-1', + status: 'cancelled', + }), + ); + expect(hanging.destroy).toHaveBeenCalled(); + }); + + it('rejects a second attempt for the same account/user with a different correlationId', async () => { + const hanging = { + connectAsync: jest.fn(() => undefined), + destroy: jest.fn(() => undefined), + }; + createConnectionMock.mockReturnValueOnce(hanging); + + const pending = SnowflakeAuthManager.startAuth( + baseRequest({ correlationId: 'corr-1' }) as any, + noopSend, + ); + await expect( + SnowflakeAuthManager.startAuth( + baseRequest({ correlationId: 'corr-2' }) as any, + noopSend, + ), + ).rejects.toThrow(/account.*user.*already in progress/i); + + SnowflakeAuthManager.cancelAuth('corr-1'); + await pending; + }); + + it('allows immediate retry after cancel and cleans up deterministically', async () => { + const first = { + connectAsync: jest.fn(() => undefined), + destroy: jest.fn(() => undefined), + }; + const second = { + connectAsync: jest.fn((cb: (err: null) => void) => cb(null)), + destroy: jest.fn(() => undefined), + }; + createConnectionMock.mockReturnValueOnce(first).mockReturnValueOnce(second); + + const pending = SnowflakeAuthManager.startAuth( + baseRequest({ correlationId: 'corr-1' }) as any, + noopSend, + ); + SnowflakeAuthManager.cancelAuth('corr-1'); + const cancelled = await pending; + expect(cancelled.ok).toBe(false); + expect(first.destroy).toHaveBeenCalled(); + + // Retry with a fresh correlationId must not be blocked. + const retried = await SnowflakeAuthManager.startAuth( + baseRequest({ correlationId: 'corr-2' }) as any, + noopSend, + ); + expect(retried).toEqual({ ok: true, authFlow: 'browser' }); + expect(second.destroy).toHaveBeenCalled(); + }); + + it('cancel is idempotent for unknown correlationIds', () => { + expect(() => + SnowflakeAuthManager.cancelAuth('does-not-exist'), + ).not.toThrow(); + }); + + it('does not send raw SDK errors to the renderer', async () => { + const secret = 'sensitive-token-value'; + createConnectionMock.mockReturnValueOnce({ + connectAsync: jest.fn((callback) => callback(new Error(secret))), + destroy: jest.fn(), + }); + const result = await SnowflakeAuthManager.startAuth( + baseRequest({ correlationId: 'corr-3' }) as any, + noopSend, + ); + expect(JSON.stringify(result)).not.toContain(secret); + expect(JSON.stringify(noopSend.mock.calls)).not.toContain(secret); + }); + + it('assertCachedSession fails fast with guidance when no cached session exists', () => { + jest + .spyOn(SnowflakeAuthManager, 'hasSnowflakeToken') + .mockReturnValueOnce(false); + expect(() => SnowflakeAuthManager.assertCachedSession()).toThrow( + SNOWFLAKE_REAUTH_MESSAGE, + ); + }); + + it('assertCachedSession passes when a cached session exists', () => { + jest + .spyOn(SnowflakeAuthManager, 'hasSnowflakeToken') + .mockReturnValueOnce(true); + expect(() => SnowflakeAuthManager.assertCachedSession()).not.toThrow(); + }); + + it('cancel delivers an IdP-error request only to the SDK redirect port', async () => { + const hanging = { + connectAsync: jest.fn(() => undefined), + destroy: jest.fn(() => undefined), + }; + createConnectionMock.mockReturnValueOnce(hanging); + + // Pre-existing server: must NOT be contacted by cancel. + let beforeHit = false; + const beforeServer = net.createServer((socket) => { + socket.on('data', () => { + beforeHit = true; + socket.end('HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n'); + }); + }); + await new Promise((resolve) => { + beforeServer.listen(0, '127.0.0.1', () => resolve()); + }); + + const pending = SnowflakeAuthManager.startAuth( + baseRequest({ correlationId: 'corr-1' }) as any, + noopSend, + ); + + // In-window server: simulates the SDK local callback server. + let notifyReceived: (line: string) => void = () => undefined; + const receivedPromise = new Promise((resolve) => { + notifyReceived = resolve; + }); + const sdkLikeServer = net.createServer((socket) => { + socket.on('data', (chunk) => { + const line = chunk.toString().split('\r\n')[0] ?? ''; + socket.end('HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n'); + notifyReceived(line); + }); + }); + await new Promise((resolve) => { + sdkLikeServer.listen(0, '127.0.0.1', () => { + resolve(); + }); + }); + + try { + const { port } = sdkLikeServer.address() as net.AddressInfo; + const [config] = createConnectionMock.mock.calls[0]; + const authorizationUrl = `https://example.snowflakecomputing.com/oauth/authorize?redirect_uri=${encodeURIComponent(`http://127.0.0.1:${port}`)}`; + config.openExternalBrowserCallback(authorizationUrl); + expect(shell.openExternal).toHaveBeenCalledWith(authorizationUrl); + SnowflakeAuthManager.cancelAuth('corr-1'); + await pending; + + const timeoutPromise = new Promise((resolve) => { + setTimeout(() => { + resolve(''); + }, 5000); + }); + const receivedLine = await Promise.race([ + receivedPromise, + timeoutPromise, + ]); + expect(receivedLine).toContain('?error=cancelled_by_user'); + expect(beforeHit).toBe(false); + } finally { + beforeServer.close(); + sdkLikeServer.close(); + } + }); +}); diff --git a/tests/unit/main/utils/snowflakeColdSession.test.ts b/tests/unit/main/utils/snowflakeColdSession.test.ts new file mode 100644 index 00000000..8922bfbb --- /dev/null +++ b/tests/unit/main/utils/snowflakeColdSession.test.ts @@ -0,0 +1,98 @@ +/* eslint-disable import/first */ +jest.mock('snowflake-sdk', () => ({ + createConnection: jest.fn(), +})); + +// Import after mock so the modules under test use the mocked SDK. +import * as snowflake from 'snowflake-sdk'; +import { executeSnowflakeQuery } from '../../../../src/main/utils/connectors'; +import SnowflakeExtractor from '../../../../src/main/extractor/snowflake.extractor'; +import { + SNOWFLAKE_REAUTH_MESSAGE, + SnowflakeAuthManager, +} from '../../../../src/main/utils/snowflakeAuth'; + +const createConnectionMock = snowflake.createConnection as jest.Mock; + +const oauthConfig = { + type: 'snowflake', + name: 'snowflake web login', + account: 'xy12345.us-east-2.aws', + username: 'alice', + warehouse: 'COMPUTE_WH', + database: 'DB', + schema: 'PUBLIC', + role: 'SYSADMIN', + authMethod: 'oauth_browser', +} as any; + +describe('Snowflake cold-session redirect (Option B: auth lives in Connections screen)', () => { + beforeEach(() => { + jest.clearAllMocks(); + jest + .spyOn(SnowflakeAuthManager, 'hasSnowflakeToken') + .mockReturnValue(false); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it('SQL Editor path returns guidance without opening a browser flow', async () => { + const connection = { + connectAsync: jest.fn(() => undefined), + destroy: jest.fn(() => undefined), + }; + createConnectionMock.mockReturnValueOnce(connection); + const result = await executeSnowflakeQuery( + oauthConfig, + 'SELECT CURRENT_USER()', + ); + expect(result).toEqual({ success: false, error: SNOWFLAKE_REAUTH_MESSAGE }); + // connectAsync never invoked: no browser, no 120s orphan. + expect(connection.connectAsync).not.toHaveBeenCalled(); + const options = createConnectionMock.mock.calls[0][0]; + expect(() => + options.openExternalBrowserCallback('https://example.com'), + ).toThrow(SNOWFLAKE_REAUTH_MESSAGE); + }); + + it('schema extract path throws guidance without opening a browser flow', async () => { + const extractor = new SnowflakeExtractor({ + account: oauthConfig.account, + username: oauthConfig.username, + warehouse: oauthConfig.warehouse, + database: oauthConfig.database, + schema: oauthConfig.schema, + role: oauthConfig.role, + authMethod: 'oauth_browser', + }); + await expect(extractor.connect()).rejects.toThrow(SNOWFLAKE_REAUTH_MESSAGE); + const options = createConnectionMock.mock.calls[0][0]; + expect(() => + options.openExternalBrowserCallback('https://example.com'), + ).toThrow(SNOWFLAKE_REAUTH_MESSAGE); + }); + + it('password mode is unaffected by the session check', async () => { + const connection = { + connect: jest.fn((cb: (err: null) => void) => { + cb(null); + }), + destroy: jest.fn(() => undefined), + execute: jest.fn((opts: { complete: Function }) => { + opts.complete(null, null, []); + }), + }; + createConnectionMock.mockReturnValueOnce(connection); + const result = await executeSnowflakeQuery( + { ...oauthConfig, authMethod: 'password', password: 'secret' }, + 'SELECT 1', + ); + expect(createConnectionMock).toHaveBeenCalled(); + expect( + createConnectionMock.mock.calls[0][0].openExternalBrowserCallback, + ).toBeUndefined(); + expect(result).toEqual({ success: true, data: [], fields: [] }); + }); +}); diff --git a/tests/unit/main/utils/snowflakeDbTokenBridge.test.ts b/tests/unit/main/utils/snowflakeDbTokenBridge.test.ts new file mode 100644 index 00000000..54c9d9b5 --- /dev/null +++ b/tests/unit/main/utils/snowflakeDbTokenBridge.test.ts @@ -0,0 +1,357 @@ +/* eslint-disable import/first */ +jest.mock('snowflake-sdk', () => ({ + createConnection: jest.fn(), +})); + +jest.mock('openai', () => ({ + OpenAI: jest.fn(), +})); + +// Stub @aws-sdk (pulled in via cloudExplorer.service in the import graph; +// the real dist-cjs bundle cannot be parsed by jest). Only the names used at +// module scope need to exist. +jest.mock('@aws-sdk/client-s3', () => { + const Dummy = class {}; + return { + S3Client: Dummy, + ListBucketsCommand: Dummy, + ListObjectsV2Command: Dummy, + ListObjectsCommand: Dummy, + GetObjectCommand: Dummy, + PutObjectCommand: Dummy, + CreateMultipartUploadCommand: Dummy, + UploadPartCommand: Dummy, + CompleteMultipartUploadCommand: Dummy, + AbortMultipartUploadCommand: Dummy, + DeleteObjectCommand: Dummy, + DeleteObjectsCommand: Dummy, + CreateBucketCommand: Dummy, + DeleteBucketCommand: Dummy, + ListObjectVersionsCommand: Dummy, + HeadBucketCommand: Dummy, + }; +}); + +jest.mock('@aws-sdk/s3-request-presigner', () => ({ + getSignedUrl: jest.fn(), +})); + +// os.homedir() does not reliably follow process.env.HOME on every platform, +// so redirect it directly for a hermetic cache location. (Prefixed `mock` +// to satisfy jest's factory scoping rules.) +let mockHome = ''; +jest.mock('os', () => { + const actual = jest.requireActual('os') as Record; + return { + ...actual, + homedir: () => mockHome || (actual.homedir as () => string)(), + }; +}); + +const mockConnections: any[] = []; + +jest.mock('../../../../src/main/database', () => ({ + __esModule: true, + default: { + getField: jest.fn((key: string) => + Promise.resolve(key === 'connections' ? mockConnections : undefined), + ), + updateField: jest.fn(), + }, +})); + +jest.mock('../../../../src/main/services/index', () => ({ + ProjectsService: { + loadProjects: jest.fn().mockResolvedValue([]), + updateProject: jest.fn(), + }, +})); + +jest.mock('../../../../src/main/services/secureStorage.service', () => ({ + __esModule: true, + default: { + setCredential: jest.fn(), + getCredential: jest.fn(), + deleteCredential: jest.fn(), + }, +})); + +// Import after mocks. +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { createHash } from 'crypto'; +import * as yaml from 'js-yaml'; +import * as snowflake from 'snowflake-sdk'; + +import { + SNOWFLAKE_REAUTH_MESSAGE, + SnowflakeAuthManager, +} from '../../../../src/main/utils/snowflakeAuth'; +import ConnectorsService from '../../../../src/main/services/connectors.service'; +import { updateProfilesYml } from '../../../../src/main/utils/yamlPartialUpdate'; + +const oauthConnection = { + id: 'conn-oauth-1', + connection: { + type: 'snowflake', + name: 'snowflake web login', + account: 'xy12345.us-east-2.aws', + username: 'alice', + warehouse: 'COMPUTE_WH', + database: 'DB', + schema: 'PUBLIC', + role: 'SYSADMIN', + authMethod: 'oauth_browser', + }, +} as any; + +const passwordConnection = { + id: 'conn-pw-1', + connection: { + type: 'snowflake', + name: 'snowflake pw', + account: 'xy12345.us-east-2.aws', + username: 'alice', + password: 'secret', + warehouse: 'COMPUTE_WH', + database: 'DB', + schema: 'PUBLIC', + authMethod: 'password', + }, +} as any; + +function writeCacheFile(dir: string, content: unknown): void { + let cacheDir = path.join(dir, '.cache', 'snowflake'); + if (process.platform === 'win32') { + cacheDir = path.join(dir, 'AppData', 'Local', 'Snowflake', 'Caches'); + } else if (process.platform === 'darwin') { + cacheDir = path.join(dir, 'Library', 'Caches', 'Snowflake'); + } + fs.mkdirSync(cacheDir, { recursive: true }); + fs.writeFileSync( + path.join(cacheDir, 'credential_cache_v1.json'), + typeof content === 'string' ? content : JSON.stringify(content), + 'utf8', + ); +} + +const accountHost = 'xy12345.us-east-2.aws.snowflakecomputing.com'; +const accountUrl = `https://${accountHost}`; +const keyHash = createHash('sha256') + .update( + JSON.stringify({ + snowflakeHost: accountHost, + username: 'alice', + oauthIdpUrl: `${accountUrl}/oauth/token-request`, + role: 'sysadmin', + }), + ) + .digest('hex'); + +const pairCache = (hash: string, accessToken = 'access-123') => ({ + tokens: { + [`SnowflakeTokenCache.v2.OauthAccessToken.${hash}`]: accessToken, + [`SnowflakeTokenCache.v2.OauthRefreshToken.${hash}`]: 'refresh-123', + }, +}); + +describe('Snowflake dbt token bridge', () => { + let tmpHome = ''; + const originalUserProfile = process.env.USERPROFILE; + + beforeEach(() => { + tmpHome = fs.mkdtempSync(path.join(os.tmpdir(), 'snow-bridge-test-')); + mockHome = tmpHome; + if (process.platform === 'win32') process.env.USERPROFILE = tmpHome; + (snowflake.createConnection as jest.Mock).mockImplementation((options) => { + options.host = accountHost; + options.accessUrl = accountUrl; + return { + connectAsync: jest.fn((callback) => callback(null)), + destroy: jest.fn((callback) => callback(null)), + }; + }); + mockConnections.length = 0; + delete process.env['db-token-snowflake web login']; + }); + + afterEach(() => { + mockHome = ''; + if (process.platform === 'win32') { + if (originalUserProfile === undefined) delete process.env.USERPROFILE; + else process.env.USERPROFILE = originalUserProfile; + } + jest.clearAllMocks(); + delete process.env['db-token-snowflake web login']; + fs.rmSync(tmpHome, { recursive: true, force: true }); + }); + + it('reads the named connection token after a silent SDK connection', async () => { + writeCacheFile(tmpHome, pairCache(keyHash)); + expect(SnowflakeAuthManager.hasSnowflakeToken()).toBe(true); + await expect( + SnowflakeAuthManager.readCachedOAuthAccessToken( + oauthConnection.connection, + ), + ).resolves.toBe('access-123'); + const options = (snowflake.createConnection as jest.Mock).mock.calls[0][0]; + expect(options.openExternalBrowserCallback).toEqual(expect.any(Function)); + expect(() => + options.openExternalBrowserCallback('https://example.com'), + ).toThrow(SNOWFLAKE_REAUTH_MESSAGE); + }); + + it('returns null without a cache file or with malformed JSON', async () => { + await expect( + SnowflakeAuthManager.readCachedOAuthAccessToken( + oauthConnection.connection, + ), + ).resolves.toBeNull(); + writeCacheFile(tmpHome, 'not-json{{{'); + await expect( + SnowflakeAuthManager.readCachedOAuthAccessToken( + oauthConnection.connection, + ), + ).resolves.toBeNull(); + }); + + it('selects only the matching identity when multiple accounts are cached', async () => { + writeCacheFile(tmpHome, { + tokens: { + ...pairCache(keyHash).tokens, + ...pairCache('other-account', 'wrong-token').tokens, + }, + }); + await expect( + SnowflakeAuthManager.readCachedOAuthAccessToken( + oauthConnection.connection, + ), + ).resolves.toBe('access-123'); + writeCacheFile(tmpHome, pairCache('other-account', 'wrong-token')); + await expect( + SnowflakeAuthManager.readCachedOAuthAccessToken( + oauthConnection.connection, + ), + ).resolves.toBeNull(); + }); + + it('returns null when the matching access token has no paired refresh token', async () => { + writeCacheFile(tmpHome, { + tokens: { + [`SnowflakeTokenCache.v2.OauthAccessToken.${keyHash}`]: 'access-123', + }, + }); + await expect( + SnowflakeAuthManager.readCachedOAuthAccessToken( + oauthConnection.connection, + ), + ).resolves.toBeNull(); + }); + + it('does not read a token when the silent SDK connection fails', async () => { + writeCacheFile(tmpHome, pairCache(keyHash)); + (snowflake.createConnection as jest.Mock).mockImplementationOnce( + (options) => { + options.host = accountHost; + options.accessUrl = accountUrl; + return { + connectAsync: jest.fn((callback) => callback(new Error('expired'))), + destroy: jest.fn((callback) => callback(null)), + }; + }, + ); + await expect( + SnowflakeAuthManager.readCachedOAuthAccessToken( + oauthConnection.connection, + ), + ).resolves.toBeNull(); + }); + + it('materializes the token env for oauth connections with a warm cache', async () => { + mockConnections.push(oauthConnection); + writeCacheFile(tmpHome, pairCache(keyHash)); + const ok = await ConnectorsService.materializeSnowflakeOAuthEnv( + 'snowflake web login', + ); + expect(ok).toBe(true); + expect(process.env['db-token-snowflake web login']).toBe('access-123'); + }); + + it('materialize clears a stale OAuth env token when the cache is cold', async () => { + mockConnections.push(oauthConnection, passwordConnection); + process.env['db-token-snowflake web login'] = 'stale-access-token'; + expect( + await ConnectorsService.materializeSnowflakeOAuthEnv( + 'snowflake web login', + ), + ).toBe(false); + expect(process.env['db-token-snowflake web login']).toBeUndefined(); + expect( + await ConnectorsService.materializeSnowflakeOAuthEnv('snowflake pw'), + ).toBe(false); + expect(await ConnectorsService.materializeSnowflakeOAuthEnv('nope')).toBe( + false, + ); + expect(await ConnectorsService.materializeSnowflakeOAuthEnv('')).toBe( + false, + ); + }); + + it('generates oauth+token profiles with no password for dbt', async () => { + const yml = await ConnectorsService.generateProfilesYml( + 'snowflake_web', + oauthConnection.connection, + ); + const parsed = yaml.load(yml) as any; + const { dev } = parsed.snowflake_web.outputs; + expect(dev.authenticator).toBe('oauth'); + expect(dev.token).toBe('{{ env_var("db-token-snowflake web login") }}'); + expect(dev.password).toBeUndefined(); + expect(dev.client_store_temporary_credential).toBeUndefined(); + expect(JSON.stringify(parsed)).not.toContain('oauth_authorization_code'); + }); + + it('partial update migrates a stale password profile to oauth+token', async () => { + const projectPath = await fs.promises.mkdtemp( + path.join(os.tmpdir(), 'snow-bridge-profiles-'), + ); + try { + await fs.promises.writeFile( + path.join(projectPath, 'profiles.yml'), + yaml.dump({ + snowflake_web: { + target: 'dev', + outputs: { + dev: { + type: 'snowflake', + password: '{{ env_var("db-password-snowflake web login") }}', + authenticator: 'oauth_authorization_code', + client_store_temporary_credential: true, + }, + }, + }, + }), + 'utf8', + ); + await updateProfilesYml( + projectPath, + 'snowflake_web', + oauthConnection.connection, + ); + const result = yaml.load( + await fs.promises.readFile( + path.join(projectPath, 'profiles.yml'), + 'utf8', + ), + ) as any; + const { dev } = result.snowflake_web.outputs; + expect(dev.authenticator).toBe('oauth'); + expect(dev.token).toBe('{{ env_var("db-token-snowflake web login") }}'); + expect(dev.password).toBeUndefined(); + expect(dev.client_store_temporary_credential).toBeUndefined(); + } finally { + await fs.promises.rm(projectPath, { recursive: true, force: true }); + } + }); +});