diff --git a/.changeset/twelve-cycles-call.md b/.changeset/twelve-cycles-call.md new file mode 100644 index 000000000..2455fc732 --- /dev/null +++ b/.changeset/twelve-cycles-call.md @@ -0,0 +1,5 @@ +--- +'@neo4j-cypher/language-support': patch +--- + +Adds signature help capabilities to the language support diff --git a/.vscode/settings.json b/.vscode/settings.json index c6d1ea446..b6a5307f3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,7 +2,7 @@ "typescript.tsc.autoDetect": "off", "typescript.preferences.quoteStyle": "single", "editor.codeActionsOnSave": { - "source.fixAll.eslint": true + "source.fixAll.eslint": "explicit" }, "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true, diff --git a/package-lock.json b/package-lock.json index d0fd7fbc8..75c84fd50 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,8 @@ "typescript": "4.9.5" }, "engines": { - "node": ">=18.18.2" + "node": ">=18.18.2", + "vscode": "^1.22.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -1889,6 +1890,12 @@ "node": ">=6.9.0" } }, + "node_modules/@balena/dockerignore": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@balena/dockerignore/-/dockerignore-1.0.2.tgz", + "integrity": "sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==", + "dev": true + }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", @@ -4676,6 +4683,15 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@testcontainers/neo4j": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testcontainers/neo4j/-/neo4j-10.4.0.tgz", + "integrity": "sha512-/9AmFdXP+ZcS2XRv4/Y9USVaMOYORVa1pqnnJMh2ict5dtcXs2AJUp1PhoU1hVOP7kTSFUp0k9rTn7q9w3k7eA==", + "dev": true, + "dependencies": { + "testcontainers": "^10.4.0" + } + }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -4766,6 +4782,26 @@ "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-1.1.10.tgz", "integrity": "sha512-fx/z6fn+xRhyBfD5AIRj4Xj0rdZc/v+89w1rRacQdPh6wNd7XijqC2zalbLjeODxkDMB+Pls07xpcKwWq9nMQw==" }, + "node_modules/@types/docker-modem": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/docker-modem/-/docker-modem-3.0.6.tgz", + "integrity": "sha512-yKpAGEuKRSS8wwx0joknWxsmLha78wNMe9R2S3UNsVOkZded8UqOrV8KoeDXoXsjndxwyF3eIhyClGbO1SEhEg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/ssh2": "*" + } + }, + "node_modules/@types/dockerode": { + "version": "3.3.23", + "resolved": "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.3.23.tgz", + "integrity": "sha512-Lz5J+NFgZS4cEVhquwjIGH4oQwlVn2h7LXD3boitujBnzOE5o7s9H8hchEjoDK2SlRsJTogdKnQeiJgPPKLIEw==", + "dev": true, + "dependencies": { + "@types/docker-modem": "*", + "@types/node": "*" + } + }, "node_modules/@types/eslint": { "version": "8.44.6", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.6.tgz", @@ -4918,6 +4954,39 @@ "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", "dev": true }, + "node_modules/@types/ssh2": { + "version": "1.11.18", + "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.11.18.tgz", + "integrity": "sha512-7eH4ppQMFlzvn//zhwD54MWaITR1aSc1oFBye9vb76GZ2Y9PSFYdwVIwOlxRXWs5+1hifntXyt+8a6SUbOD7Hg==", + "dev": true, + "dependencies": { + "@types/node": "^18.11.18" + } + }, + "node_modules/@types/ssh2-streams": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@types/ssh2-streams/-/ssh2-streams-0.1.12.tgz", + "integrity": "sha512-Sy8tpEmCce4Tq0oSOYdfqaBpA3hDM8SoxoFh5vzFsu2oL+znzGz8oVWW7xb4K920yYMUY+PIG31qZnFMfPWNCg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ssh2/node_modules/@types/node": { + "version": "18.19.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.4.tgz", + "integrity": "sha512-xNzlUhzoHotIsnFoXmJB+yWmBvFZgKCI9TtPIEdYIMM1KWfwuY8zh7wvc1u1OAXlC7dlf6mZVx/s+Y5KfFz19A==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/ssh2/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/@types/stack-utils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.2.tgz", @@ -5214,9 +5283,9 @@ } }, "node_modules/@vscode/test-electron": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.5.tgz", - "integrity": "sha512-lAW7nQ0HuPqJnGJrtCzEKZCICtRizeP6qNanyCrjmdCOAAWjX3ixiG8RVPwqsYPQBWLPgYuE12qQlwXsOR/2fQ==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.8.tgz", + "integrity": "sha512-b4aZZsBKtMGdDljAsOPObnAi7+VWIaYl3ylCz1jTs+oV6BZ4TNHcVNC3xUn0azPeszBmwSBDQYfFESIaUQnrOg==", "dev": true, "dependencies": { "http-proxy-agent": "^4.0.1", @@ -5680,6 +5749,59 @@ "node": ">= 8" } }, + "node_modules/archiver": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", + "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", + "dev": true, + "dependencies": { + "archiver-utils": "^2.1.0", + "async": "^3.2.4", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dev": true, + "dependencies": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/archiver/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -5802,6 +5924,15 @@ "node": ">=0.10.0" } }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, "node_modules/asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -5842,6 +5973,18 @@ "node": ">=8" } }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "dev": true + }, + "node_modules/async-lock": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.1.tgz", + "integrity": "sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==", + "dev": true + }, "node_modules/autoprefixer": { "version": "10.4.16", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz", @@ -5910,6 +6053,12 @@ "typed-rest-client": "^1.8.4" } }, + "node_modules/b4a": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", + "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==", + "dev": true + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -6200,6 +6349,15 @@ } ] }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, "node_modules/benchmark": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.4.tgz", @@ -6245,7 +6403,6 @@ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, - "optional": true, "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -6271,7 +6428,6 @@ "url": "https://feross.org/support" } ], - "optional": true, "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -6282,7 +6438,6 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, - "optional": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -6544,12 +6699,31 @@ "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", "peer": true }, + "node_modules/buildcheck": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.6.tgz", + "integrity": "sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==", + "dev": true, + "optional": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", "peer": true }, + "node_modules/byline": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", + "integrity": "sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/c8": { "version": "7.14.0", "resolved": "https://registry.npmjs.org/c8/-/c8-7.14.0.tgz", @@ -6915,8 +7089,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true, - "optional": true + "dev": true }, "node_modules/chroma-js": { "version": "2.4.2", @@ -7156,6 +7329,35 @@ "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true }, + "node_modules/compress-commons": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", + "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", + "dev": true, + "dependencies": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/compress-commons/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/compression-webpack-plugin": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-10.0.0.tgz", @@ -7384,6 +7586,60 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, + "node_modules/cpu-features": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.9.tgz", + "integrity": "sha512-AKjgn2rP2yJyfbepsmLfiYcmtNn/2eUvocUyM/09yB0YDiz39HteK/5/T4Onf0pmdYDMgkBoGvRLvEguzyL7wQ==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "dependencies": { + "buildcheck": "~0.0.6", + "nan": "^2.17.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", + "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", + "dev": true, + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/crc32-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/create-ecdh": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", @@ -8069,6 +8325,73 @@ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", "dev": true }, + "node_modules/docker-compose": { + "version": "0.24.3", + "resolved": "https://registry.npmjs.org/docker-compose/-/docker-compose-0.24.3.tgz", + "integrity": "sha512-x3/QN3AIOMe7j2c8f/jcycizMft7dl8MluoB9OGPAYCyKHHiPUFqI9GjCcsU0kYy24vYKMCcfR6+5ZaEyQlrxg==", + "dev": true, + "dependencies": { + "yaml": "^2.2.2" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/docker-modem": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-3.0.8.tgz", + "integrity": "sha512-f0ReSURdM3pcKPNS30mxOHSbaFLcknGmQjwSfmbcdOw1XWKXVhukM3NJHhr7NpY9BIyyWQb0EBo3KQvvuU5egQ==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "readable-stream": "^3.5.0", + "split-ca": "^1.0.1", + "ssh2": "^1.11.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/docker-modem/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/dockerode": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/dockerode/-/dockerode-3.3.5.tgz", + "integrity": "sha512-/0YNa3ZDNeLr/tSckmD69+Gq+qVNhvKfAHNeZJBnp7EOP6RGKV8ORrJHkUn20So5wU+xxT7+1n5u8PjHbfjbSA==", + "dev": true, + "dependencies": { + "@balena/dockerignore": "^1.0.2", + "docker-modem": "^3.0.0", + "tar-fs": "~2.0.1" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/dockerode/node_modules/tar-fs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.1.tgz", + "integrity": "sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA==", + "dev": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.0.0" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -8222,7 +8545,6 @@ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, - "optional": true, "dependencies": { "once": "^1.4.0" } @@ -9265,6 +9587,12 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "dev": true + }, "node_modules/fast-glob": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", @@ -9510,8 +9838,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true, - "optional": true + "dev": true }, "node_modules/fs-extra": { "version": "7.0.1", @@ -9623,6 +9950,18 @@ "node": ">=8.0.0" } }, + "node_modules/get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -12823,6 +13162,18 @@ "node": ">=6" } }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -13113,6 +13464,30 @@ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "dev": true + }, + "node_modules/lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", + "dev": true + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "dev": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -13131,6 +13506,12 @@ "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", "dev": true }, + "node_modules/lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", + "dev": true + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -13623,12 +14004,23 @@ "node": ">= 8.0.0" } }, + "node_modules/mkdirp": { + "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" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true, - "optional": true + "dev": true }, "node_modules/mocha": { "version": "10.2.0", @@ -13982,6 +14374,13 @@ "thenify-all": "^1.0.0" } }, + "node_modules/nan": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", + "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", + "dev": true, + "optional": true + }, "node_modules/nanoid": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", @@ -14068,6 +14467,26 @@ "dev": true, "optional": true }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -15158,6 +15577,33 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, + "node_modules/properties-reader": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/properties-reader/-/properties-reader-2.3.0.tgz", + "integrity": "sha512-z597WicA7nDZxK12kZqHr2TcvwNU1GCfA5UwfDY/HDp3hXPoPlb5rlEx9bwGTiJnc0OqbBTkU975jDToth8Gxw==", + "dev": true, + "dependencies": { + "mkdirp": "^1.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/steveukx/properties?sponsor=1" + } + }, "node_modules/pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -15189,7 +15635,6 @@ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, - "optional": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -15264,6 +15709,12 @@ } ] }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", + "dev": true + }, "node_modules/quick-lru": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", @@ -15505,6 +15956,36 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "dev": true, + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -15737,6 +16218,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -16288,12 +16778,56 @@ "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", "dev": true }, + "node_modules/split-ca": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split-ca/-/split-ca-1.0.1.tgz", + "integrity": "sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ==", + "dev": true + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, + "node_modules/ssh-remote-port-forward": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/ssh-remote-port-forward/-/ssh-remote-port-forward-1.0.4.tgz", + "integrity": "sha512-x0LV1eVDwjf1gmG7TTnfqIzf+3VPRz7vrNIjX6oYLbeCrf/PeVY6hkT68Mg+q02qXxQhrLjB0jfgvhevoCRmLQ==", + "dev": true, + "dependencies": { + "@types/ssh2": "^0.5.48", + "ssh2": "^1.4.0" + } + }, + "node_modules/ssh-remote-port-forward/node_modules/@types/ssh2": { + "version": "0.5.52", + "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-0.5.52.tgz", + "integrity": "sha512-lbLLlXxdCZOSJMCInKH2+9V/77ET2J6NPQHpFI0kda61Dd1KglJs+fPQBchizmzYSOJBgdTajhPqBO1xxLywvg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/ssh2-streams": "*" + } + }, + "node_modules/ssh2": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.15.0.tgz", + "integrity": "sha512-C0PHgX4h6lBxYx7hcXwu3QWdh4tg6tZZsTfXcdvc5caW/EMxaB4H9dWsl7qk+F7LAW762hp8VbXOX7x4xUYvEw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "asn1": "^0.2.6", + "bcrypt-pbkdf": "^1.0.2" + }, + "engines": { + "node": ">=10.16.0" + }, + "optionalDependencies": { + "cpu-features": "~0.0.9", + "nan": "^2.18.0" + } + }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -16374,6 +16908,16 @@ "mixme": "^0.5.1" } }, + "node_modules/streamx": { + "version": "2.15.6", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.6.tgz", + "integrity": "sha512-q+vQL4AAz+FdfT137VF69Cc/APqUbxy+MDOImRrMvchJpigHj9GksgDU2LYbO9rx7RX6osWgxJB2WxhYv4SZAw==", + "dev": true, + "dependencies": { + "fast-fifo": "^1.1.0", + "queue-tick": "^1.0.1" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -16676,7 +17220,6 @@ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dev": true, - "optional": true, "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -16693,7 +17236,6 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, - "optional": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -16843,6 +17385,51 @@ "node": ">=8" } }, + "node_modules/testcontainers": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-10.4.0.tgz", + "integrity": "sha512-kMmJXOAuJeQTRbGSrIEBaAzTzGzmY4+DU5xW5CxgzxgywCoy53ubeiTh3eZ1rzT54YR3zf0nijlb/l7OT4E+/g==", + "dev": true, + "dependencies": { + "@balena/dockerignore": "^1.0.2", + "@types/dockerode": "^3.3.21", + "archiver": "^5.3.2", + "async-lock": "^1.4.0", + "byline": "^5.0.0", + "debug": "^4.3.4", + "docker-compose": "^0.24.2", + "dockerode": "^3.3.5", + "get-port": "^5.1.1", + "node-fetch": "^2.7.0", + "proper-lockfile": "^4.1.2", + "properties-reader": "^2.3.0", + "ssh-remote-port-forward": "^1.0.4", + "tar-fs": "^3.0.4", + "tmp": "^0.2.1" + } + }, + "node_modules/testcontainers/node_modules/tar-fs": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", + "integrity": "sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==", + "dev": true, + "dependencies": { + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + } + }, + "node_modules/testcontainers/node_modules/tar-stream": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.6.tgz", + "integrity": "sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==", + "dev": true, + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -16928,6 +17515,12 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, "node_modules/tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", @@ -17330,6 +17923,12 @@ "win32" ] }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -17779,6 +18378,12 @@ "defaults": "^1.0.3" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, "node_modules/webpack": { "version": "5.89.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", @@ -17973,6 +18578,16 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -18356,6 +18971,55 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zip-stream": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", + "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", + "dev": true, + "dependencies": { + "archiver-utils": "^3.0.4", + "compress-commons": "^4.1.2", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/zip-stream/node_modules/archiver-utils": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", + "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", + "dev": true, + "dependencies": { + "glob": "^7.2.3", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/zip-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "packages/language-server": { "name": "@neo4j-cypher/language-server", "version": "2.0.0-next.3", @@ -19498,10 +20162,11 @@ "vscode-languageclient": "^8.1.0" }, "devDependencies": { + "@testcontainers/neo4j": "^10.4.0", "@types/mocha": "^10.0.1", "@types/node": "^16.11.7", "@types/vscode": "^1.75.0", - "@vscode/test-electron": "^2.2.3", + "@vscode/test-electron": "^2.3.8", "@vscode/vsce": "^2.21.1", "mocha": "^10.2.0", "typescript": "^4.9.5" diff --git a/package.json b/package.json index 7f1d1a5aa..698c07592 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,8 @@ }, "engineStrict": true, "engines": { - "node": ">=18.18.2" + "node": ">=18.18.2", + "vscode": "^1.22.0" }, "devDependencies": { "@changesets/cli": "^2.26.2", diff --git a/packages/react-codemirror/playwright/index.html b/packages/react-codemirror/playwright/index.html index 610ddf8a4..a5c5c3693 100644 --- a/packages/react-codemirror/playwright/index.html +++ b/packages/react-codemirror/playwright/index.html @@ -6,7 +6,7 @@ Testing Page -
+
diff --git a/packages/react-codemirror/src/CypherEditor.tsx b/packages/react-codemirror/src/CypherEditor.tsx index f80930041..d7b9dd130 100644 --- a/packages/react-codemirror/src/CypherEditor.tsx +++ b/packages/react-codemirror/src/CypherEditor.tsx @@ -57,6 +57,10 @@ export interface CypherEditorProps { * @default false */ autofocus?: boolean; + /** + * Where to place the cursor in the query. Cannot be enabled at the same time than autofocus + */ + offset?: number; /** * Whether the editor should wrap lines. * @@ -249,6 +253,8 @@ export class CypherEditor extends Component { if (this.props.value) { this.updateCursorPosition(this.props.value.length); } + } else if (this.props.offset) { + this.updateCursorPosition(this.props.offset); } } diff --git a/packages/react-codemirror/src/e2e_tests/signature-help.spec.tsx b/packages/react-codemirror/src/e2e_tests/signature-help.spec.tsx new file mode 100644 index 000000000..0e782bf8a --- /dev/null +++ b/packages/react-codemirror/src/e2e_tests/signature-help.spec.tsx @@ -0,0 +1,312 @@ +import { testData } from '@neo4j-cypher/language-support'; +import { expect, test } from '@playwright/experimental-ct-react'; +import { Locator } from 'playwright/test'; +import { CypherEditor } from '../CypherEditor'; + +test.use({ viewport: { width: 1000, height: 500 } }); + +type TooltipExpectations = { + includes?: string[]; + excludes?: string[]; +}; + +function testTooltip(tooltip: Locator, expectations: TooltipExpectations) { + const includes = expectations.includes ?? []; + const excludes = expectations.excludes ?? []; + + const included = Promise.all( + includes.map((text) => { + return expect(tooltip).toContainText(text, { + timeout: 2000, + }); + }), + ); + + const excluded = Promise.all( + excludes.map((text) => { + return expect(tooltip).not.toContainText(text, { + timeout: 2000, + }); + }), + ); + + return Promise.all([included, excluded]); +} + +test('Signature help works for functions', async ({ page, mount }) => { + const query = 'RETURN abs('; + + await mount( + , + ); + + await expect(page.locator('.cm-tooltip-signature-help').last()).toBeVisible({ + timeout: 2000, + }); +}); + +test('Signature help works for procedures', async ({ page, mount }) => { + const query = 'CALL apoc.import.csv('; + + await mount( + , + ); + + await expect(page.locator('.cm-tooltip-signature-help').last()).toBeVisible({ + timeout: 2000, + }); +}); + +test('Signature help shows the description for the first argument', async ({ + page, + mount, +}) => { + const query = 'CALL apoc.import.csv('; + + await mount( + , + ); + + const tooltip = page.locator('.cm-tooltip-signature-help').last(); + + await testTooltip(tooltip, { + includes: [ + 'nodes :: LIST', + 'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file', + ], + }); +}); + +test('Signature help shows the description for the first argument when the cursor is at that position', async ({ + page, + mount, +}) => { + const query = 'CALL apoc.import.csv()'; + + await mount( + , + ); + + const tooltip = page.locator('.cm-tooltip-signature-help').last(); + + await testTooltip(tooltip, { + includes: [ + 'nodes :: LIST', + 'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file', + ], + }); +}); + +test('Signature help shows the description for the second argument', async ({ + page, + mount, +}) => { + const query = 'CALL apoc.import.csv(nodes,'; + + await mount( + , + ); + + const tooltip = page.locator('.cm-tooltip-signature-help').last(); + + await testTooltip(tooltip, { + includes: [ + 'rels :: LIST', + 'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file', + ], + }); +}); + +test('Signature help shows the description for the second argument when the cursor is at that position', async ({ + page, + mount, +}) => { + const query = 'CALL apoc.import.csv(nodes,)'; + + await mount( + , + ); + + const tooltip = page.locator('.cm-tooltip-signature-help').last(); + + await testTooltip(tooltip, { + includes: [ + 'rels :: LIST', + 'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file', + ], + }); +}); + +test('Signature help shows the description for the second argument when the cursor is at that position, even after whitespaces', async ({ + page, + mount, +}) => { + const query = 'CALL apoc.import.csv(nodes, )'; + + await mount( + , + ); + + const tooltip = page.locator('.cm-tooltip-signature-help').last(); + + await testTooltip(tooltip, { + includes: [ + 'rels :: LIST', + 'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file', + ], + }); +}); + +test('Signature help shows description for arguments with a space following a separator', async ({ + page, + mount, +}) => { + const query = 'CALL apoc.import.csv(nodes, '; + + await mount( + , + ); + + const tooltip = page.locator('.cm-tooltip-signature-help').last(); + + await testTooltip(tooltip, { + includes: [ + 'rels :: LIST', + 'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file', + ], + }); +}); + +test('Signature help shows the description for the third argument', async ({ + page, + mount, +}) => { + const query = 'CALL apoc.import.csv(nodes, rels,'; + + await mount( + , + ); + + const tooltip = page.locator('.cm-tooltip-signature-help').last(); + + await testTooltip(tooltip, { + includes: [ + 'config :: MAP', + 'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file', + ], + }); +}); + +test('Signature help works on multiline queries', async ({ page, mount }) => { + const query = `CALL apoc.import.csv( + nodes, + rels, + `; + + await mount( + , + ); + + const tooltip = page.locator('.cm-tooltip-signature-help').last(); + + await testTooltip(tooltip, { + includes: [ + 'config :: MAP', + 'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file', + ], + }); +}); + +test('Signature help only shows the description past the last argument', async ({ + page, + mount, +}) => { + const query = 'CALL apoc.import.csv(nodes, rels, config,'; + + await mount( + , + ); + + const tooltip = page.locator('.cm-tooltip-signature-help').last(); + + await testTooltip(tooltip, { + includes: [ + 'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file', + ], + excludes: ['config :: MAP'], + }); +}); + +test('Signature help does not show any help when method finished', async ({ + page, + mount, +}) => { + const query = 'CALL apoc.import.csv(nodes, rels, config)'; + + await mount( + , + ); + + await expect( + page.locator('.cm-tooltip-signature-help').last(), + ).not.toBeVisible({ + timeout: 2000, + }); +}); + +test('Signature help does not blow up on empty query', async ({ + page, + mount, +}) => { + const query = ''; + + await mount( + , + ); + + await expect( + page.locator('.cm-tooltip-signature-help').last(), + ).not.toBeVisible({ + timeout: 2000, + }); +}); diff --git a/packages/react-codemirror/src/index.ts b/packages/react-codemirror/src/index.ts index 8effa9ebf..ea77314b7 100644 --- a/packages/react-codemirror/src/index.ts +++ b/packages/react-codemirror/src/index.ts @@ -1,4 +1,4 @@ -export { CypherParser, parse } from '@neo4j-cypher/language-support'; +export { CypherParser } from '@neo4j-cypher/language-support'; export { CypherEditor } from './CypherEditor'; export { cypher } from './lang-cypher/lang-cypher'; export { darkThemeConstants, lightThemeConstants } from './themes'; diff --git a/packages/react-codemirror/src/lang-cypher/lang-cypher.ts b/packages/react-codemirror/src/lang-cypher/lang-cypher.ts index 3df7cdf46..86a3da598 100644 --- a/packages/react-codemirror/src/lang-cypher/lang-cypher.ts +++ b/packages/react-codemirror/src/lang-cypher/lang-cypher.ts @@ -6,6 +6,7 @@ import { import type { DbSchema } from '@neo4j-cypher/language-support'; import { cypherAutocomplete } from './autocomplete'; import { ParserAdapter } from './ParserAdapter'; +import { signatureHelpTooltip } from './signature-help'; import { cypherLinter } from './syntax-validation'; const facet = defineLanguageFacet({ @@ -28,5 +29,6 @@ export function cypher(config: CypherConfig) { autocomplete: cypherAutocomplete(config), }), cypherLinter(config), + signatureHelpTooltip(config), ]); } diff --git a/packages/react-codemirror/src/lang-cypher/signature-help.ts b/packages/react-codemirror/src/lang-cypher/signature-help.ts new file mode 100644 index 000000000..cd8ae9b0e --- /dev/null +++ b/packages/react-codemirror/src/lang-cypher/signature-help.ts @@ -0,0 +1,104 @@ +import { EditorState, StateField } from '@codemirror/state'; +import { showTooltip, Tooltip } from '@codemirror/view'; +import { signatureHelp } from '@neo4j-cypher/language-support'; +import { CypherConfig } from './lang-cypher'; + +function getTriggerCharacter(query: string, offset: number) { + let i = offset - 1; + let triggerCharacter = query.at(i); + + // Discard all space characters. Note that a space can be more than just a ' ' + while (/\s/.test(triggerCharacter) && i > 0) { + i -= 1; + triggerCharacter = query.at(i); + } + + return triggerCharacter; +} + +function getSignatureHelpTooltip( + state: EditorState, + config: CypherConfig, +): Tooltip[] { + let result: Tooltip[] = []; + const schema = config.schema; + const ranges = state.selection.ranges; + const range = ranges.at(0); + + if (schema && ranges.length === 1 && range.from === range.to) { + const position = range.from; + const query = state.doc.toString(); + + const triggerCharacter = getTriggerCharacter(query, position); + + if (triggerCharacter === '(' || triggerCharacter === ',') { + const queryUntilPosition = query.slice(0, position); + + const signatureHelpInfo = signatureHelp(queryUntilPosition, schema); + const activeSignature = signatureHelpInfo.activeSignature; + const signatures = signatureHelpInfo.signatures; + const activeParameter = signatureHelpInfo.activeParameter; + + if ( + activeSignature !== undefined && + activeSignature >= 0 && + activeSignature < signatures.length && + signatures[activeSignature].documentation !== undefined + ) { + const signature = signatures[activeSignature]; + const parameters = signature.parameters; + let doc = signature.documentation.toString(); + + if ( + activeParameter >= 0 && + activeParameter < + (signatures[activeSignature].parameters?.length ?? 0) + ) { + doc = + parameters[activeParameter].documentation.toString() + '\n\n' + doc; + } + + result = [ + { + pos: position, + above: true, + strictSide: true, + arrow: true, + create: () => { + const div = document.createElement('div'); + const methodName = document.createElement('div'); + const argPlusDescription = document.createElement('div'); + const separator = document.createElement('hr'); + const lineBreak = document.createElement('br'); + + div.append( + ...[methodName, separator, lineBreak, argPlusDescription], + ); + div.className = 'cm-tooltip-signature-help'; + + methodName.innerText = signature.label; + argPlusDescription.innerText = doc; + + return { dom: div }; + }, + }, + ]; + } + } + } + + return result; +} + +export function signatureHelpTooltip(config: CypherConfig) { + return StateField.define({ + create: (state) => getSignatureHelpTooltip(state, config), + + update(tooltips, tr) { + if (!tr.docChanged && !tr.selection) return tooltips; + return getSignatureHelpTooltip(tr.state, config); + }, + + provide: (f) => showTooltip.computeN([f], (state) => state.field(f)), + }); +} diff --git a/packages/vscode-extension/.gitignore b/packages/vscode-extension/.gitignore new file mode 100644 index 000000000..e57758540 --- /dev/null +++ b/packages/vscode-extension/.gitignore @@ -0,0 +1 @@ +e2e_tests/fixtures/.vscode/settings.json \ No newline at end of file diff --git a/packages/vscode-extension/e2e_tests/fixtures/.vscode/settings-template.json b/packages/vscode-extension/e2e_tests/fixtures/.vscode/settings-template.json new file mode 100644 index 000000000..72d44bc69 --- /dev/null +++ b/packages/vscode-extension/e2e_tests/fixtures/.vscode/settings-template.json @@ -0,0 +1,7 @@ +{ + "neo4j.connect": true, + "neo4j.password": "{PASSWORD}", + "neo4j.URL": "neo4j://localhost:{PORT}", + "neo4j.user": "neo4j", + "neo4j.trace.server": "off" +} diff --git a/packages/vscode-extension/e2e_tests/fixtures/signature-help.cypher b/packages/vscode-extension/e2e_tests/fixtures/signature-help.cypher new file mode 100644 index 000000000..b17673662 --- /dev/null +++ b/packages/vscode-extension/e2e_tests/fixtures/signature-help.cypher @@ -0,0 +1,3 @@ +RETURN abs() +CALL apoc.import.csv(nodes, rels, config) +CALL apoc.import.csv(nodes, rels, config, other) \ No newline at end of file diff --git a/packages/vscode-extension/e2e_tests/main.ts b/packages/vscode-extension/e2e_tests/main.ts index 44a146c5d..c73d07514 100644 --- a/packages/vscode-extension/e2e_tests/main.ts +++ b/packages/vscode-extension/e2e_tests/main.ts @@ -1,7 +1,44 @@ +import { Neo4jContainer } from '@testcontainers/neo4j'; import { runTests } from '@vscode/test-electron'; +import * as fs from 'fs'; import * as path from 'path'; +function setSetting(file: string, variable: RegExp, value: string) { + const data = fs.readFileSync(file).toString(); + const result = data.replace(variable, value); + fs.writeFileSync(file, result); +} + +function updateSettingsFile(port: number, password: string) { + const settingsPath = path.join( + __dirname, + '../../e2e_tests/fixtures/.vscode/', + ); + const settingsTemplate = path.join(settingsPath, 'settings-template.json'); + const settingsFile = path.join(settingsPath, 'settings.json'); + fs.copyFileSync(settingsTemplate, settingsFile); + setSetting(settingsFile, /\{PORT\}/g, port.toString()); + setSetting(settingsFile, /\{PASSWORD\}/g, password); +} + async function main() { + const password = 'password'; + + const container = await new Neo4jContainer('neo4j:5') + .withExposedPorts(7474, 7687) + .withApoc() + .withPassword(password) + // Giving it a name prevents us from spinning up a different + // container every time we run the tests and allows us + // closing a lingering one when the tests finish + .withName('vscode-integration-tests') + .start(); + + const port = container.getMappedPort(7687); + // This sets up a settings.json file based on the settings-template.json + // replacing the random port and password we have given the container + updateSettingsFile(port, password); + try { /* This is equivalent to running from a command line: @@ -19,11 +56,17 @@ async function main() { const extensionTestsPath = path.resolve(__dirname, './testRunner'); // Bootstraps VS Code and executes the integration tests - await runTests({ extensionDevelopmentPath, extensionTestsPath }); + await runTests({ + launchArgs: [path.join(__dirname, '../../e2e_tests/fixtures/')], + extensionDevelopmentPath, + extensionTestsPath, + }); } catch (err) { console.error('Failed to run integration tests'); process.exit(1); } + + await container.stop(); } void main(); diff --git a/packages/vscode-extension/e2e_tests/testRunner.ts b/packages/vscode-extension/e2e_tests/testRunner.ts index a05f8ce2e..2e9e1a5e3 100644 --- a/packages/vscode-extension/e2e_tests/testRunner.ts +++ b/packages/vscode-extension/e2e_tests/testRunner.ts @@ -9,7 +9,7 @@ export function run(): Promise { ui: 'tdd', color: true, }); - mocha.timeout(100000); + mocha.timeout(10000); const testsRoot = __dirname; diff --git a/packages/vscode-extension/e2e_tests/tests/signature-help.spec.ts b/packages/vscode-extension/e2e_tests/tests/signature-help.spec.ts new file mode 100644 index 000000000..3ffb87ee9 --- /dev/null +++ b/packages/vscode-extension/e2e_tests/tests/signature-help.spec.ts @@ -0,0 +1,139 @@ +import { testData } from '@neo4j-cypher/language-support'; +import * as assert from 'assert'; +import * as vscode from 'vscode'; +import { eventually, getDocumentUri, openDocument } from '../helpers'; + +type InclusionTestArgs = { + textFile: string; + position: vscode.Position; + expected: vscode.SignatureHelp; +}; + +export async function testSignatureHelp({ + textFile, + position, + expected, +}: InclusionTestArgs) { + const docUri = getDocumentUri(textFile); + + await openDocument(docUri); + + await eventually(async () => { + const signatureHelp: vscode.SignatureHelp = + await vscode.commands.executeCommand( + 'vscode.executeSignatureHelpProvider', + docUri, + position, + ); + + assert.equal(signatureHelp.activeParameter, expected.activeParameter); + + expected.signatures.forEach((expectedSignature) => { + const foundSignature = signatureHelp.signatures.find((signature) => { + return signature.label === expectedSignature.label; + }); + + assert.equal( + foundSignature.documentation, + expectedSignature.documentation, + ); + + expectedSignature.parameters.forEach((expectedParameter) => { + const foundParameter = foundSignature.parameters.find( + (parameter) => parameter.label === expectedParameter.label, + ); + + assert.equal( + foundParameter.documentation, + expectedParameter.documentation, + ); + }); + }); + }); +} + +suite('Signature help spec', () => { + test('Signature help works for functions', async () => { + const position = new vscode.Position(0, 11); + + const expected: vscode.SignatureHelp = { + activeParameter: 0, + // We don't test the active signature, otherwise we would have to modify + // these tests every time a new function is added to the database + activeSignature: undefined, + signatures: [testData.mockSchema.functionSignatures.abs], + }; + + await testSignatureHelp({ + textFile: 'signature-help.cypher', + position: position, + expected: expected, + }); + }); + + test('Signature help works for procedures', async () => { + const position = new vscode.Position(1, 21); + + const expected: vscode.SignatureHelp = { + activeParameter: 0, + activeSignature: undefined, + signatures: [testData.mockSchema.procedureSignatures['apoc.import.csv']], + }; + + await testSignatureHelp({ + textFile: 'signature-help.cypher', + position: position, + expected: expected, + }); + }); + + test('Signature help works when changing arguments', async () => { + const position = new vscode.Position(1, 27); + + const expected: vscode.SignatureHelp = { + activeParameter: 1, + activeSignature: undefined, + signatures: [testData.mockSchema.procedureSignatures['apoc.import.csv']], + }; + + await testSignatureHelp({ + textFile: 'signature-help.cypher', + position: position, + expected: expected, + }); + }); + + test('Signature help works for arguments with a space following a separator', async () => { + const position = new vscode.Position(1, 28); + + const expected: vscode.SignatureHelp = { + activeParameter: 1, + activeSignature: undefined, + signatures: [testData.mockSchema.procedureSignatures['apoc.import.csv']], + }; + + await testSignatureHelp({ + textFile: 'signature-help.cypher', + position: position, + expected: expected, + }); + }); + + test('Signature help only shows the description past the last argument', async () => { + const position = new vscode.Position(2, 42); + + const expected: vscode.SignatureHelp = { + // This is what would make it show only the function description + // since there are only 3 arguments in the signature and the last index is 2 + activeParameter: 3, + activeSignature: undefined, + signatures: [testData.mockSchema.procedureSignatures['apoc.import.csv']], + }; + + await testSignatureHelp({ + textFile: 'signature-help.cypher', + position: position, + expected: expected, + }); + }); +}); diff --git a/packages/vscode-extension/package.json b/packages/vscode-extension/package.json index 0d95f882d..aac50ead3 100644 --- a/packages/vscode-extension/package.json +++ b/packages/vscode-extension/package.json @@ -94,12 +94,13 @@ "vscode-languageclient": "^8.1.0" }, "devDependencies": { + "@testcontainers/neo4j": "^10.4.0", "@types/mocha": "^10.0.1", "@types/node": "^16.11.7", "@types/vscode": "^1.75.0", - "@vscode/test-electron": "^2.2.3", + "@vscode/test-electron": "^2.3.8", + "@vscode/vsce": "^2.21.1", "mocha": "^10.2.0", - "typescript": "^4.9.5", - "@vscode/vsce": "^2.21.1" + "typescript": "^4.9.5" } }