From 25f94af6e0205d04efae56b1e55550d90a47df7b Mon Sep 17 00:00:00 2001 From: Antonio Barcelos Date: Fri, 4 Aug 2023 14:12:51 +0200 Subject: [PATCH 01/16] Introduce `testcontainers` for integration tests `testcontainers` replaces `boltkit` as library to start docker containers. The container should be able to start when `npm run test`, `npm run test::integration` and `npm run test::browser` are run if methods are not called from testkit. Running the tests direct from the IDE should be also an supported usecase. --- packages/neo4j-driver/gulpfile.babel.js | 11 +- packages/neo4j-driver/package-lock.json | 1290 ++++++++++++++++- packages/neo4j-driver/package.json | 1 + packages/neo4j-driver/test/bolt-v3.test.js | 2 +- packages/neo4j-driver/test/bolt-v4x0.test.js | 2 +- packages/neo4j-driver/test/driver.test.js | 84 +- packages/neo4j-driver/test/examples.test.js | 2 +- .../test/internal/connection-channel.test.js | 32 +- .../neo4j-driver/test/internal/logger.test.js | 6 +- .../test/internal/node/package.test.js | 2 +- .../test/internal/server-version.test.js | 2 +- .../test/internal/shared-neo4j.js | 321 +--- .../test/nested-statements.test.js | 2 +- packages/neo4j-driver/test/result.test.js | 2 +- .../neo4j-driver/test/rx/navigation.test.js | 4 +- .../test/rx/nested-statements.test.js | 2 +- packages/neo4j-driver/test/rx/session.test.js | 2 +- packages/neo4j-driver/test/rx/summary.test.js | 6 +- .../neo4j-driver/test/rx/transaction.test.js | 2 +- packages/neo4j-driver/test/session.test.js | 8 +- .../neo4j-driver/test/spatial-types.test.js | 4 +- packages/neo4j-driver/test/stress-test.js | 2 +- packages/neo4j-driver/test/stress.test.js | 2 +- packages/neo4j-driver/test/summary.test.js | 4 +- .../neo4j-driver/test/temporal-types.test.js | 4 +- .../neo4j-driver/test/transaction.test.js | 6 +- packages/neo4j-driver/test/types.test.js | 12 +- 27 files changed, 1349 insertions(+), 468 deletions(-) diff --git a/packages/neo4j-driver/gulpfile.babel.js b/packages/neo4j-driver/gulpfile.babel.js index 4d1f4998e..d1603d85a 100644 --- a/packages/neo4j-driver/gulpfile.babel.js +++ b/packages/neo4j-driver/gulpfile.babel.js @@ -139,7 +139,8 @@ gulp.task('test-nodejs-stub', () => { return runJasmineTests('#stub*') }) -gulp.task('test-nodejs-integration', () => { +gulp.task('test-nodejs-integration', async () => { + await sharedNeo4j.start() return runJasmineTests('#integration*') }) @@ -190,13 +191,11 @@ gulp.task('set', function () { }) gulp.task('start-neo4j', function (done) { - sharedNeo4j.start() - done() + sharedNeo4j.start().then(done) }) gulp.task('stop-neo4j', function (done) { - sharedNeo4j.stop() - done() + sharedNeo4j.stop().then(done) }) gulp.task('run-stress-tests', function () { @@ -242,7 +241,7 @@ gulp.task('test-browser', gulp.series('browser', 'run-browser-test')) gulp.task( 'test', - gulp.series('run-ts-declaration-tests', 'test-nodejs', 'test-browser') + gulp.series('run-ts-declaration-tests', 'start-neo4j', 'test-nodejs', 'test-browser', 'stop-neo4j') ) gulp.task('default', gulp.series('test')) diff --git a/packages/neo4j-driver/package-lock.json b/packages/neo4j-driver/package-lock.json index 6869b1111..c22c9852a 100644 --- a/packages/neo4j-driver/package-lock.json +++ b/packages/neo4j-driver/package-lock.json @@ -52,6 +52,7 @@ "rollup-plugin-polyfill-node": "^0.11.0", "semver": "^7.5.3", "source-map": "0.7.4", + "testcontainers": "^8.16.0", "tmp": "0.2.1", "typescript": "^4.9.5", "vinyl-buffer": "^1.0.1", @@ -1743,6 +1744,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/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -1989,6 +1996,15 @@ "node": ">= 0.6.0" } }, + "node_modules/@types/archiver": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-5.3.2.tgz", + "integrity": "sha512-IctHreBuWE5dvBDz/0WeKtyVKVRs4h75IblxOACL92wU66v+HGAfEYAOyXkOFphvRJMhuXdI9huDXpX0FC6lCw==", + "dev": true, + "dependencies": { + "@types/readdir-glob": "*" + } + }, "node_modules/@types/component-emitter": { "version": "1.2.11", "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", @@ -2007,6 +2023,26 @@ "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", "dev": true }, + "node_modules/@types/docker-modem": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/docker-modem/-/docker-modem-3.0.3.tgz", + "integrity": "sha512-i1A2Etnav7uHizZ87vUf4EqwJehY3JOcTfBS0pGBlO+HQ0jg2lUMCaJRg9VQM8ldZkpYdIfsenxcTOCpwxPXEg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/ssh2": "*" + } + }, + "node_modules/@types/dockerode": { + "version": "3.3.19", + "resolved": "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.3.19.tgz", + "integrity": "sha512-7CC5yIpQi+bHXwDK43b/deYXteP3Lem9gdocVVHJPSRJJLMfbiOchQV3rDmAPkMw+n3GIVj7m1six3JW+VcwwA==", + "dev": true, + "dependencies": { + "@types/docker-modem": "*", + "@types/node": "*" + } + }, "node_modules/@types/eslint": { "version": "8.4.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz", @@ -2052,11 +2088,20 @@ "dev": true }, "node_modules/@types/node": { - "version": "14.18.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz", - "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==", + "version": "18.17.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.2.tgz", + "integrity": "sha512-wBo3KqP/PBqje5TI9UTiuL3yWfP6sdPtjtygSOqcYZWT232dfDeDOnkDps5wqZBP9NgGgYrNejinl0faAuE+HQ==", "dev": true }, + "node_modules/@types/readdir-glob": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/readdir-glob/-/readdir-glob-1.1.1.tgz", + "integrity": "sha512-ImM6TmoF8bgOwvehGviEj3tRdRBbQujr1N+0ypaln/GWjaerOB26jb93vsRHmdMtvVQZQebOlqt2HROark87mQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -2066,6 +2111,24 @@ "@types/node": "*" } }, + "node_modules/@types/ssh2": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.11.13.tgz", + "integrity": "sha512-08WbG68HvQ2YVi74n2iSUnYHYpUdFc/s2IsI0BHBdJwaqYJpWlVv9elL0tYShTv60yr0ObdxJR5NrCRiGJ/0CQ==", + "dev": true, + "dependencies": { + "@types/node": "^18.11.18" + } + }, + "node_modules/@types/ssh2-streams": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/@types/ssh2-streams/-/ssh2-streams-0.1.9.tgz", + "integrity": "sha512-I2J9jKqfmvXLR5GomDiCoHrEJ58hAOmFrekfFqmCFd+A6gaEStvWnPykoWUwld1PNg4G5ag1LwdA+Lz1doRJqg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/vinyl": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.6.tgz", @@ -2424,6 +2487,86 @@ "node": ">=4" } }, + "node_modules/archiver": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz", + "integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==", + "dev": true, + "dependencies": { + "archiver-utils": "^2.1.0", + "async": "^3.2.3", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.0.0", + "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/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "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/archiver/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", @@ -3343,13 +3486,27 @@ } }, "node_modules/buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", - "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, "node_modules/buffer-alloc": { @@ -3410,6 +3567,16 @@ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": 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-modules": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", @@ -3428,6 +3595,15 @@ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "dev": 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/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -3568,6 +3744,12 @@ "node": ">=0.10.0" } }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, "node_modules/chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -3937,6 +4119,35 @@ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", "dev": true }, + "node_modules/compress-commons": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", + "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", + "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/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -4101,6 +4312,60 @@ "node": ">= 0.10" } }, + "node_modules/cpu-features": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.8.tgz", + "integrity": "sha512-BbHBvtYhUhksqTjr6bhNOjGgMnhwhGTQmOoZGD+K7BCaQDCuZl/Ve1ZxUSMRwVC4D/rkCPQ2MAIeYzrWyK7eEg==", + "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.2", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", + "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", + "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", @@ -4602,6 +4867,124 @@ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true }, + "node_modules/docker-compose": { + "version": "0.23.19", + "resolved": "https://registry.npmjs.org/docker-compose/-/docker-compose-0.23.19.tgz", + "integrity": "sha512-v5vNLIdUqwj4my80wxFDkNH+4S85zsRuH29SO7dCWVWPCMt/ohZBsGN6g6KXWifT0pzQ7uOxqEKCYCDPJ8Vz4g==", + "dev": true, + "dependencies": { + "yaml": "^1.10.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/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/dockerode/node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/dockerode/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/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/dockerode/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/dom-serialize": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", @@ -6160,6 +6543,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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": "2.3.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", @@ -8769,30 +9164,6 @@ "util": "^0.12.0" } }, - "node_modules/karma-typescript/node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, "node_modules/karma-typescript/node_modules/domain-browser": { "version": "4.22.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.22.0.tgz", @@ -9322,6 +9693,12 @@ "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", "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.escape": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", @@ -9367,6 +9744,12 @@ "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", "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.keys": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", @@ -9453,6 +9836,12 @@ "lodash.escape": "^3.0.0" } }, + "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/log4js": { "version": "6.4.4", "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.4.tgz", @@ -9851,6 +10240,12 @@ "mkdirp": "bin/cmd.js" } }, + "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 + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -9909,9 +10304,9 @@ } }, "node_modules/nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", "dev": true, "optional": true }, @@ -10788,6 +11183,30 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "node_modules/properties-reader": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/properties-reader/-/properties-reader-2.2.0.tgz", + "integrity": "sha512-CgVcr8MwGoBKK24r9TwHfZkLLaNFHQ6y4wgT9w/XzdpacOOi5ciH4hcuLechSDAwXsfrGQtI2JTutY2djOx2Ow==", + "dev": true, + "dependencies": { + "mkdirp": "^1.0.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/properties-reader/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/psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -11029,6 +11448,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": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", @@ -11988,6 +12437,12 @@ "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", "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/split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -12025,6 +12480,44 @@ "node": ">=0.10.0" } }, + "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.14.0", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.14.0.tgz", + "integrity": "sha512-AqzD1UCqit8tbOKoj6ztDDi1ffJZ2rV2SwlgrVVrHPkV5vWqGJOVp5pmtj18PunkPJAuKQsnInyKV+/Nb2bUnA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "asn1": "^0.2.6", + "bcrypt-pbkdf": "^1.0.2" + }, + "engines": { + "node": ">=10.16.0" + }, + "optionalDependencies": { + "cpu-features": "~0.0.8", + "nan": "^2.17.0" + } + }, "node_modules/sshpk": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", @@ -12445,6 +12938,69 @@ "node": ">=6" } }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/tar-fs/node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/tar-fs/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/tar-fs/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/tar-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", @@ -12515,6 +13071,26 @@ } } }, + "node_modules/testcontainers": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-8.16.0.tgz", + "integrity": "sha512-4wVmnzj4mAVXSQ8kU4uyNiXPs5W8UHdwCRbUuyeOSSODcgmDGQ8Te/YOYuF12HnxyzABEm1nR2I0ZCsQw/GZ/Q==", + "dev": true, + "dependencies": { + "@balena/dockerignore": "^1.0.2", + "@types/archiver": "^5.3.1", + "@types/dockerode": "^3.3.8", + "archiver": "^5.3.1", + "byline": "^5.0.0", + "debug": "^4.3.4", + "docker-compose": "^0.23.17", + "dockerode": "^3.3.1", + "get-port": "^5.1.1", + "properties-reader": "^2.2.0", + "ssh-remote-port-forward": "^1.0.4", + "tar-fs": "^2.1.1" + } + }, "node_modules/textextensions": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-3.3.0.tgz", @@ -13724,6 +14300,15 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/yargs": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", @@ -13829,6 +14414,34 @@ "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } + }, + "node_modules/zip-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", + "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", + "dev": true, + "dependencies": { + "archiver-utils": "^2.1.0", + "compress-commons": "^4.1.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" + } } }, "dependencies": { @@ -15016,6 +15629,12 @@ "to-fast-properties": "^2.0.0" } }, + "@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 + }, "@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -15204,6 +15823,15 @@ "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==", "dev": true }, + "@types/archiver": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-5.3.2.tgz", + "integrity": "sha512-IctHreBuWE5dvBDz/0WeKtyVKVRs4h75IblxOACL92wU66v+HGAfEYAOyXkOFphvRJMhuXdI9huDXpX0FC6lCw==", + "dev": true, + "requires": { + "@types/readdir-glob": "*" + } + }, "@types/component-emitter": { "version": "1.2.11", "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", @@ -15222,6 +15850,26 @@ "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", "dev": true }, + "@types/docker-modem": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/docker-modem/-/docker-modem-3.0.3.tgz", + "integrity": "sha512-i1A2Etnav7uHizZ87vUf4EqwJehY3JOcTfBS0pGBlO+HQ0jg2lUMCaJRg9VQM8ldZkpYdIfsenxcTOCpwxPXEg==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/ssh2": "*" + } + }, + "@types/dockerode": { + "version": "3.3.19", + "resolved": "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.3.19.tgz", + "integrity": "sha512-7CC5yIpQi+bHXwDK43b/deYXteP3Lem9gdocVVHJPSRJJLMfbiOchQV3rDmAPkMw+n3GIVj7m1six3JW+VcwwA==", + "dev": true, + "requires": { + "@types/docker-modem": "*", + "@types/node": "*" + } + }, "@types/eslint": { "version": "8.4.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz", @@ -15267,11 +15915,20 @@ "dev": true }, "@types/node": { - "version": "14.18.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz", - "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==", + "version": "18.17.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.2.tgz", + "integrity": "sha512-wBo3KqP/PBqje5TI9UTiuL3yWfP6sdPtjtygSOqcYZWT232dfDeDOnkDps5wqZBP9NgGgYrNejinl0faAuE+HQ==", "dev": true }, + "@types/readdir-glob": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/readdir-glob/-/readdir-glob-1.1.1.tgz", + "integrity": "sha512-ImM6TmoF8bgOwvehGviEj3tRdRBbQujr1N+0ypaln/GWjaerOB26jb93vsRHmdMtvVQZQebOlqt2HROark87mQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -15281,6 +15938,24 @@ "@types/node": "*" } }, + "@types/ssh2": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.11.13.tgz", + "integrity": "sha512-08WbG68HvQ2YVi74n2iSUnYHYpUdFc/s2IsI0BHBdJwaqYJpWlVv9elL0tYShTv60yr0ObdxJR5NrCRiGJ/0CQ==", + "dev": true, + "requires": { + "@types/node": "^18.11.18" + } + }, + "@types/ssh2-streams": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/@types/ssh2-streams/-/ssh2-streams-0.1.9.tgz", + "integrity": "sha512-I2J9jKqfmvXLR5GomDiCoHrEJ58hAOmFrekfFqmCFd+A6gaEStvWnPykoWUwld1PNg4G5ag1LwdA+Lz1doRJqg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/vinyl": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.6.tgz", @@ -15573,27 +16248,97 @@ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "^1.0.1" + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true, + "requires": { + "buffer-equal": "^1.0.0" + } + }, + "archive-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", + "integrity": "sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA=", + "dev": true, + "requires": { + "file-type": "^4.2.0" + } + }, + "archiver": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz", + "integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==", + "dev": true, + "requires": { + "archiver-utils": "^2.1.0", + "async": "^3.2.3", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.0.0", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "dependencies": { + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "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, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" } } } }, - "append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "requires": { - "buffer-equal": "^1.0.0" - } - }, - "archive-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", - "integrity": "sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA=", + "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, "requires": { - "file-type": "^4.2.0" + "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" } }, "archy": { @@ -16358,13 +17103,13 @@ } }, "buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", - "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, "buffer-alloc": { @@ -16419,6 +17164,13 @@ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, + "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 + }, "builtin-modules": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", @@ -16431,6 +17183,12 @@ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "dev": true }, + "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 + }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -16544,6 +17302,12 @@ } } }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, "chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -16851,6 +17615,31 @@ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", "dev": true }, + "compress-commons": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", + "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", + "dev": true, + "requires": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "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, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -16994,6 +17783,46 @@ "vary": "^1" } }, + "cpu-features": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.8.tgz", + "integrity": "sha512-BbHBvtYhUhksqTjr6bhNOjGgMnhwhGTQmOoZGD+K7BCaQDCuZl/Ve1ZxUSMRwVC4D/rkCPQ2MAIeYzrWyK7eEg==", + "dev": true, + "optional": true, + "requires": { + "buildcheck": "~0.0.6", + "nan": "^2.17.0" + } + }, + "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 + }, + "crc32-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", + "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", + "dev": true, + "requires": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "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, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "create-ecdh": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", @@ -17411,6 +18240,110 @@ } } }, + "docker-compose": { + "version": "0.23.19", + "resolved": "https://registry.npmjs.org/docker-compose/-/docker-compose-0.23.19.tgz", + "integrity": "sha512-v5vNLIdUqwj4my80wxFDkNH+4S85zsRuH29SO7dCWVWPCMt/ohZBsGN6g6KXWifT0pzQ7uOxqEKCYCDPJ8Vz4g==", + "dev": true, + "requires": { + "yaml": "^1.10.2" + } + }, + "docker-modem": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-3.0.8.tgz", + "integrity": "sha512-f0ReSURdM3pcKPNS30mxOHSbaFLcknGmQjwSfmbcdOw1XWKXVhukM3NJHhr7NpY9BIyyWQb0EBo3KQvvuU5egQ==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "readable-stream": "^3.5.0", + "split-ca": "^1.0.1", + "ssh2": "^1.11.0" + }, + "dependencies": { + "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, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "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, + "requires": { + "@balena/dockerignore": "^1.0.2", + "docker-modem": "^3.0.0", + "tar-fs": "~2.0.1" + }, + "dependencies": { + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "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, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "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, + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.0.0" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } + } + } + }, "dom-serialize": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", @@ -18703,6 +19636,12 @@ "has-symbols": "^1.0.1" } }, + "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 + }, "get-stream": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", @@ -20938,16 +21877,6 @@ "util": "^0.12.0" } }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, "domain-browser": { "version": "4.22.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.22.0.tgz", @@ -21223,6 +22152,12 @@ "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", "dev": true }, + "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 + }, "lodash.escape": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", @@ -21268,6 +22203,12 @@ "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", "dev": true }, + "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 + }, "lodash.keys": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", @@ -21354,6 +22295,12 @@ "lodash.escape": "^3.0.0" } }, + "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 + }, "log4js": { "version": "6.4.4", "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.4.tgz", @@ -21674,6 +22621,12 @@ "minimist": "^1.2.6" } }, + "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 + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -21731,9 +22684,9 @@ "dev": true }, "nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", "dev": true, "optional": true }, @@ -22423,6 +23376,23 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "properties-reader": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/properties-reader/-/properties-reader-2.2.0.tgz", + "integrity": "sha512-CgVcr8MwGoBKK24r9TwHfZkLLaNFHQ6y4wgT9w/XzdpacOOi5ciH4hcuLechSDAwXsfrGQtI2JTutY2djOx2Ow==", + "dev": true, + "requires": { + "mkdirp": "^1.0.4" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, "psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -22632,6 +23602,35 @@ } } }, + "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, + "requires": { + "minimatch": "^5.1.0" + }, + "dependencies": { + "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, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "readdirp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", @@ -23406,6 +24405,12 @@ "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", "dev": true }, + "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 + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -23436,6 +24441,40 @@ } } }, + "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, + "requires": { + "@types/ssh2": "^0.5.48", + "ssh2": "^1.4.0" + }, + "dependencies": { + "@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, + "requires": { + "@types/node": "*", + "@types/ssh2-streams": "*" + } + } + } + }, + "ssh2": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.14.0.tgz", + "integrity": "sha512-AqzD1UCqit8tbOKoj6ztDDi1ffJZ2rV2SwlgrVVrHPkV5vWqGJOVp5pmtj18PunkPJAuKQsnInyKV+/Nb2bUnA==", + "dev": true, + "requires": { + "asn1": "^0.2.6", + "bcrypt-pbkdf": "^1.0.2", + "cpu-features": "~0.0.8", + "nan": "^2.17.0" + } + }, "sshpk": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", @@ -23791,6 +24830,65 @@ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + }, + "dependencies": { + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "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, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } + } + } + }, "tar-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", @@ -23831,6 +24929,26 @@ "terser": "^5.16.8" } }, + "testcontainers": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-8.16.0.tgz", + "integrity": "sha512-4wVmnzj4mAVXSQ8kU4uyNiXPs5W8UHdwCRbUuyeOSSODcgmDGQ8Te/YOYuF12HnxyzABEm1nR2I0ZCsQw/GZ/Q==", + "dev": true, + "requires": { + "@balena/dockerignore": "^1.0.2", + "@types/archiver": "^5.3.1", + "@types/dockerode": "^3.3.8", + "archiver": "^5.3.1", + "byline": "^5.0.0", + "debug": "^4.3.4", + "docker-compose": "^0.23.17", + "dockerode": "^3.3.1", + "get-port": "^5.1.1", + "properties-reader": "^2.2.0", + "ssh-remote-port-forward": "^1.0.4", + "tar-fs": "^2.1.1" + } + }, "textextensions": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-3.3.0.tgz", @@ -24779,6 +25897,12 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + }, "yargs": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", @@ -24868,6 +25992,30 @@ "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } + }, + "zip-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", + "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", + "dev": true, + "requires": { + "archiver-utils": "^2.1.0", + "compress-commons": "^4.1.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "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, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } } } } diff --git a/packages/neo4j-driver/package.json b/packages/neo4j-driver/package.json index 39bdbe131..e9253e5e0 100644 --- a/packages/neo4j-driver/package.json +++ b/packages/neo4j-driver/package.json @@ -74,6 +74,7 @@ "rollup-plugin-polyfill-node": "^0.11.0", "semver": "^7.5.3", "source-map": "0.7.4", + "testcontainers": "^8.16.0", "tmp": "0.2.1", "typescript": "^4.9.5", "vinyl-buffer": "^1.0.1", diff --git a/packages/neo4j-driver/test/bolt-v3.test.js b/packages/neo4j-driver/test/bolt-v3.test.js index 9aef3b8a0..eaeb372be 100644 --- a/packages/neo4j-driver/test/bolt-v3.test.js +++ b/packages/neo4j-driver/test/bolt-v3.test.js @@ -37,7 +37,7 @@ describe('#integration Bolt V3 API', () => { beforeEach(async () => { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) session = driver.session() diff --git a/packages/neo4j-driver/test/bolt-v4x0.test.js b/packages/neo4j-driver/test/bolt-v4x0.test.js index f9d0d4d8f..a12f33dd2 100644 --- a/packages/neo4j-driver/test/bolt-v4x0.test.js +++ b/packages/neo4j-driver/test/bolt-v4x0.test.js @@ -27,7 +27,7 @@ describe('#integration Bolt V4.0 API', () => { beforeEach(async () => { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) session = driver.session() diff --git a/packages/neo4j-driver/test/driver.test.js b/packages/neo4j-driver/test/driver.test.js index f39b48aef..1724baef0 100644 --- a/packages/neo4j-driver/test/driver.test.js +++ b/packages/neo4j-driver/test/driver.test.js @@ -44,7 +44,7 @@ describe('#unit driver', () => { it('should create an unencrypted, non-routed driver for scheme: bolt', () => { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) expect(driver._isEncrypted()).toBeFalsy() @@ -54,7 +54,7 @@ describe('#unit driver', () => { it('should create an encrypted, system CAs trusting, non-routed driver for scheme: bolt+s', () => { driver = neo4j.driver( - `bolt+s://${sharedNeo4j.hostname}`, + `bolt+s://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) expect(driver._isEncrypted()).toBeTruthy() @@ -65,7 +65,7 @@ describe('#unit driver', () => { it('should create an encrypted, all trusting, non-routed driver for scheme: bolt+ssc', () => { driver = neo4j.driver( - `bolt+ssc://${sharedNeo4j.hostname}`, + `bolt+ssc://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) expect(driver._isEncrypted()).toBeTruthy() @@ -76,7 +76,7 @@ describe('#unit driver', () => { it('should create an unencrypted, routed driver for scheme: neo4j', () => { driver = neo4j.driver( - `neo4j://${sharedNeo4j.hostname}`, + `neo4j://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) expect(driver._isEncrypted()).toBeFalsy() @@ -86,7 +86,7 @@ describe('#unit driver', () => { it('should create an encrypted, system CAs trusting, routed driver for scheme: neo4j+s', () => { driver = neo4j.driver( - `neo4j+s://${sharedNeo4j.hostname}`, + `neo4j+s://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) expect(driver._isEncrypted()).toBeTruthy() @@ -97,7 +97,7 @@ describe('#unit driver', () => { it('should create an encrypted, all trusting, routed driver for scheme: neo4j+ssc', () => { driver = neo4j.driver( - `neo4j+ssc://${sharedNeo4j.hostname}`, + `neo4j+ssc://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) expect(driver._isEncrypted()).toBeTruthy() @@ -109,7 +109,7 @@ describe('#unit driver', () => { it('should throw when encryption in url AND in config', () => { expect(() => neo4j.driver( - `neo4j+ssc://${sharedNeo4j.hostname}`, + `neo4j+ssc://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken, { encrypted: 'ENCRYPTION_OFF' @@ -118,7 +118,7 @@ describe('#unit driver', () => { ).toThrow() // Throw even in case where there is no conflict expect(() => - neo4j.driver(`neo4j+s://${sharedNeo4j.hostname}`, sharedNeo4j.authToken, { + neo4j.driver(`neo4j+s://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken, { encrypted: 'ENCRYPTION_ON' }) ).toThrow() @@ -135,7 +135,7 @@ describe('#unit driver', () => { ].forEach(([bookmarks, expectedBookmarks]) => { it(`should create session using param bookmarks=${bookmarks}`, () => { driver = neo4j.driver( - `neo4j+ssc://${sharedNeo4j.hostname}`, + `neo4j+ssc://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) @@ -147,7 +147,7 @@ describe('#unit driver', () => { it('should create session using auth', () => { driver = neo4j.driver( - `neo4j+ssc://${sharedNeo4j.hostname}`, + `neo4j+ssc://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) @@ -165,7 +165,7 @@ describe('#unit driver', () => { ].forEach(([bookmarkManager, configuredBookmarkManager]) => { it('should create session using param bookmark manager', () => { driver = neo4j.driver( - `neo4j+ssc://${sharedNeo4j.hostname}`, + `neo4j+ssc://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) @@ -177,7 +177,7 @@ describe('#unit driver', () => { it('should redirect logger to session', () => { driver = neo4j.driver( - `neo4j+ssc://${sharedNeo4j.hostname}`, + `neo4j+ssc://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) @@ -195,7 +195,7 @@ describe('#integration driver', () => { beforeAll(async () => { const tmpDriver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) protocolVersion = await sharedNeo4j.cleanupAndGetProtocolVersion(tmpDriver) @@ -217,7 +217,7 @@ describe('#integration driver', () => { encrypted: false } driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken, config ) @@ -250,7 +250,7 @@ describe('#integration driver', () => { it('should expose sessions', () => { // Given driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) @@ -315,22 +315,22 @@ describe('#integration driver', () => { it('should handle wrong scheme', () => { expect(() => - neo4j.driver(`tank://${sharedNeo4j.hostname}`, sharedNeo4j.authToken) + neo4j.driver(`tank://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken) ).toThrow(new Error('Unknown scheme: tank')) }) it('should handle URL parameter string', () => { expect(() => - neo4j.driver({ uri: `bolt://${sharedNeo4j.hostname}` }) + neo4j.driver({ uri: `bolt://${sharedNeo4j.hostnameWithBoltPort}` }) ).toThrowError(TypeError) - expect(() => neo4j.driver([`bolt:${sharedNeo4j.hostname}`])).toThrowError( + expect(() => neo4j.driver([`bolt:${sharedNeo4j.hostnameWithBoltPort}`])).toThrowError( TypeError ) expect(() => { const driver = neo4j.driver( - String(`bolt://${sharedNeo4j.hostname}`), + String(`bolt://${sharedNeo4j.hostnameWithBoltPort}`), sharedNeo4j.authToken ) return driver.session() @@ -339,7 +339,7 @@ describe('#integration driver', () => { it('should fail early on wrong credentials', async () => { // Given - driver = neo4j.driver(`bolt://${sharedNeo4j.hostname}`, wrongCredentials()) + driver = neo4j.driver(`bolt://${sharedNeo4j.hostnameWithBoltPort}`, wrongCredentials()) const session = driver.session() const txc = session.beginTransaction() @@ -353,7 +353,7 @@ describe('#integration driver', () => { }) it('should fail queries on wrong credentials', done => { - driver = neo4j.driver(`bolt://${sharedNeo4j.hostname}`, wrongCredentials()) + driver = neo4j.driver(`bolt://${sharedNeo4j.hostnameWithBoltPort}`, wrongCredentials()) const session = driver.session() session.run('RETURN 1').catch(error => { @@ -365,7 +365,7 @@ describe('#integration driver', () => { it('should indicate success early on correct credentials', done => { // Given driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) @@ -379,7 +379,7 @@ describe('#integration driver', () => { it('should be possible to pass a realm with basic auth tokens', done => { // Given driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, neo4j.auth.basic(sharedNeo4j.username, sharedNeo4j.password, 'native') ) @@ -393,7 +393,7 @@ describe('#integration driver', () => { it('should be possible to create custom auth tokens', done => { // Given driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, neo4j.auth.custom( sharedNeo4j.username, sharedNeo4j.password, @@ -412,7 +412,7 @@ describe('#integration driver', () => { it('should be possible to create custom auth tokens with additional parameters', done => { // Given driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, neo4j.auth.custom( sharedNeo4j.username, sharedNeo4j.password, @@ -436,7 +436,7 @@ describe('#integration driver', () => { // Given driver = neo4j.driver( - `neo4j://${sharedNeo4j.hostname}`, + `neo4j://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) const session = driver.session() @@ -450,7 +450,7 @@ describe('#integration driver', () => { } catch (error) { expect(error.code).toEqual(neo4j.error.SERVICE_UNAVAILABLE) expect(error.message).toEqual( - `Server at ${sharedNeo4j.hostname}:7687 can't perform routing. ` + + `Server at ${sharedNeo4j.hostnameWithBoltPort} can't perform routing. ` + 'Make sure you are connecting to a causal cluster' ) } finally { @@ -461,13 +461,13 @@ describe('#integration driver', () => { }) it('should have correct user agent', async () => { - const directDriver = neo4j.driver(`bolt://${sharedNeo4j.hostname}`) + const directDriver = neo4j.driver(`bolt://${sharedNeo4j.hostnameWithBoltPort}`) expect(directDriver._getOrCreateConnectionProvider()._userAgent).toBe( 'neo4j-javascript/0.0.0-dev' ) await directDriver.close() - const routingDriver = neo4j.driver(`neo4j://${sharedNeo4j.hostname}`) + const routingDriver = neo4j.driver(`neo4j://${sharedNeo4j.hostnameWithBoltPort}`) expect(routingDriver._getOrCreateConnectionProvider()._userAgent).toBe( 'neo4j-javascript/0.0.0-dev' ) @@ -476,7 +476,7 @@ describe('#integration driver', () => { it('should fail when bolt:// scheme used with routing params', () => { expect(() => - neo4j.driver(`bolt://${sharedNeo4j.hostname}:7687/?policy=my_policy`) + neo4j.driver(`bolt://${sharedNeo4j.hostnameWithBoltPort}/?policy=my_policy`) ).toThrow() }) @@ -499,7 +499,7 @@ describe('#integration driver', () => { it('should fail when fetch size is negative', () => { expect(() => - neo4j.driver(`bolt://${sharedNeo4j.hostname}`, sharedNeo4j.authToken, { + neo4j.driver(`bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken, { fetchSize: -77 }) ).toThrow() @@ -507,7 +507,7 @@ describe('#integration driver', () => { it('should fail when fetch size is 0', () => { expect(() => - neo4j.driver(`bolt://${sharedNeo4j.hostname}`, sharedNeo4j.authToken, { + neo4j.driver(`bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken, { fetchSize: 0 }) ).toThrow() @@ -515,7 +515,7 @@ describe('#integration driver', () => { it('should discard closed connections', async () => { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) @@ -544,7 +544,7 @@ describe('#integration driver', () => { it('should discard old connections', async () => { const maxLifetime = 100000 driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken, { maxConnectionLifetime: maxLifetime @@ -598,12 +598,14 @@ describe('#integration driver', () => { const itIpv6 = sharedNeo4j.ipv6Enabled ? it : xit - itIpv6('should connect to IPv6 address without port', done => { - testIPv6Connection('bolt://[::1]', done) - }) + if (!sharedNeo4j.isTestContainer) { + itIpv6('should connect to IPv6 address without port', done => { + testIPv6Connection('bolt://[::1]', done) + }) + } itIpv6('should connect to IPv6 address with port', done => { - testIPv6Connection('bolt://[::1]:7687', done) + testIPv6Connection(`bolt://[::1]:${sharedNeo4j.boltPort}`, done) }) const nativeNumbers = [ @@ -632,7 +634,7 @@ describe('#integration driver', () => { }) it('hasReachableServer success', async () => { - await expectAsync(neo4j.hasReachableServer(`${sharedNeo4j.scheme}://${sharedNeo4j.hostname}`)) + await expectAsync(neo4j.hasReachableServer(`${sharedNeo4j.scheme}://${sharedNeo4j.hostnameWithBoltPort}`)) .toBeResolvedTo(true) }) @@ -677,7 +679,7 @@ describe('#integration driver', () => { function testNumberInReturnedRecord (inputNumber, expectedNumber, done) { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken, { disableLosslessIntegers: true @@ -729,7 +731,7 @@ describe('#integration driver', () => { expectedValue ) { const driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken, config ) diff --git a/packages/neo4j-driver/test/examples.test.js b/packages/neo4j-driver/test/examples.test.js index 90b56608a..cd7f1af90 100644 --- a/packages/neo4j-driver/test/examples.test.js +++ b/packages/neo4j-driver/test/examples.test.js @@ -48,7 +48,7 @@ describe('#integration examples', () => { const user = sharedNeo4j.username const password = sharedNeo4j.password - const uri = `bolt://${sharedNeo4j.hostname}:7687` + const uri = `bolt://${sharedNeo4j.hostnameWithBoltPort}` beforeAll(() => { driverGlobal = neo4j.driver(uri, sharedNeo4j.authToken) diff --git a/packages/neo4j-driver/test/internal/connection-channel.test.js b/packages/neo4j-driver/test/internal/connection-channel.test.js index be7db2adc..a2ab6c046 100644 --- a/packages/neo4j-driver/test/internal/connection-channel.test.js +++ b/packages/neo4j-driver/test/internal/connection-channel.test.js @@ -71,7 +71,7 @@ describe('#integration ChannelConnection', () => { try { clock.setSystemTime(424242) - connection = await createConnection(`bolt://${sharedNeo4j.hostname}`) + connection = await createConnection(`bolt://${sharedNeo4j.hostnameWithBoltPort}`) expect(connection.creationTimestamp).toEqual(424242) } finally { @@ -80,7 +80,7 @@ describe('#integration ChannelConnection', () => { }) it('should read/write basic messages', done => { - createConnection(`bolt://${sharedNeo4j.hostname}`) + createConnection(`bolt://${sharedNeo4j.hostnameWithBoltPort}`) .then(connection => { connection.protocol().initialize({ userAgent: 'mydriver/0.0.0', @@ -97,7 +97,7 @@ describe('#integration ChannelConnection', () => { }) it('should retrieve stream', async done => { - connection = await createConnection(`bolt://${sharedNeo4j.hostname}`) + connection = await createConnection(`bolt://${sharedNeo4j.hostnameWithBoltPort}`) const records = [] const pullAllObserver = { @@ -131,7 +131,7 @@ describe('#integration ChannelConnection', () => { }) it('should provide error message when connecting to http-port', async done => { - await createConnection(`bolt://${sharedNeo4j.hostname}:7474`, { + await createConnection(`bolt://${sharedNeo4j.hostnameWithHttpPort}`, { encrypted: false }, null, new Logger('error', () => {})) .then(done.fail.bind(done)) @@ -182,7 +182,7 @@ describe('#integration ChannelConnection', () => { }) it('should notify when connection initialization completes', async done => { - connection = await createConnection(`bolt://${sharedNeo4j.hostname}`) + connection = await createConnection(`bolt://${sharedNeo4j.hostnameWithBoltPort}`) connection .connect('mydriver/0.0.0', BOLT_AGENT, basicAuthToken()) @@ -194,7 +194,7 @@ describe('#integration ChannelConnection', () => { }) it('should notify when connection initialization fails', async done => { - connection = await createConnection(`bolt://${sharedNeo4j.hostname}`) // wrong port + connection = await createConnection(`bolt://${sharedNeo4j.hostnameWithBoltPort}`) // wrong port connection .connect('mydriver/0.0.0', BOLT_AGENT, basicWrongAuthToken()) @@ -206,7 +206,7 @@ describe('#integration ChannelConnection', () => { }) it('should have server version after connection initialization completed', async done => { - connection = await createConnection(`bolt://${sharedNeo4j.hostname}`) + connection = await createConnection(`bolt://${sharedNeo4j.hostnameWithBoltPort}`) connection .connect('mydriver/0.0.0', BOLT_AGENT, basicAuthToken()) .then(initializedConnection => { @@ -219,7 +219,7 @@ describe('#integration ChannelConnection', () => { }) it('should fail all new observers after failure to connect', async done => { - connection = await createConnection(`bolt://${sharedNeo4j.hostname}`) + connection = await createConnection(`bolt://${sharedNeo4j.hostnameWithBoltPort}`) connection .connect('mydriver/0.0.0', BOLT_AGENT, basicWrongAuthToken()) @@ -279,7 +279,7 @@ describe('#integration ChannelConnection', () => { }) it('should reset and flush when SUCCESS received', async done => { - connection = await createConnection(`bolt://${sharedNeo4j.hostname}`) + connection = await createConnection(`bolt://${sharedNeo4j.hostnameWithBoltPort}`) connection .connect('my-driver/1.2.3', BOLT_AGENT, basicAuthToken()) @@ -303,7 +303,7 @@ describe('#integration ChannelConnection', () => { }) it('should fail to reset and flush when FAILURE received', async done => { - createConnection(`bolt://${sharedNeo4j.hostname}`) + createConnection(`bolt://${sharedNeo4j.hostnameWithBoltPort}`) .then(connection => { connection.connect('my-driver/1.2.3', BOLT_AGENT, basicAuthToken()).then(() => { connection @@ -330,7 +330,7 @@ describe('#integration ChannelConnection', () => { }) it('should fail to reset and flush when RECORD received', async done => { - connection = await createConnection(`bolt://${sharedNeo4j.hostname}`) + connection = await createConnection(`bolt://${sharedNeo4j.hostnameWithBoltPort}`) connection .connect('my-driver/1.2.3', BOLT_AGENT, basicAuthToken()) @@ -358,7 +358,7 @@ describe('#integration ChannelConnection', () => { }) it('should acknowledge failure with RESET when SUCCESS received', async done => { - createConnection(`bolt://${sharedNeo4j.hostname}`) + createConnection(`bolt://${sharedNeo4j.hostnameWithBoltPort}`) .then(connection => { connection .connect('my-driver/1.2.3', BOLT_AGENT, basicAuthToken()) @@ -401,7 +401,7 @@ describe('#integration ChannelConnection', () => { ) createChannelConnection( - ServerAddress.fromUrl(`bolt://${sharedNeo4j.hostname}`), + ServerAddress.fromUrl(`bolt://${sharedNeo4j.hostnameWithBoltPort}`), {}, errorHandler, Logger.noOp() @@ -424,7 +424,7 @@ describe('#integration ChannelConnection', () => { it('should send INIT/HELLO and GOODBYE messages', async () => { const messages = [] - connection = await createConnection(`bolt://${sharedNeo4j.hostname}`) + connection = await createConnection(`bolt://${sharedNeo4j.hostnameWithBoltPort}`) recordWrittenMessages(connection._protocol, messages) await connection.connect('mydriver/0.0.0', BOLT_AGENT, basicAuthToken()) @@ -442,7 +442,7 @@ describe('#integration ChannelConnection', () => { }) it('should not prepare broken connection to close', async () => { - connection = await createConnection(`bolt://${sharedNeo4j.hostname}`) + connection = await createConnection(`bolt://${sharedNeo4j.hostnameWithBoltPort}`) await connection.connect('my-connection/9.9.9', BOLT_AGENT, basicAuthToken()) expect(connection._protocol).toBeDefined() @@ -528,7 +528,7 @@ describe('#integration ChannelConnection', () => { } function testQueueingOfObserversWithBrokenConnection (connectionAction, done) { - createConnection(`bolt://${sharedNeo4j.hostname}`) + createConnection(`bolt://${sharedNeo4j.hostnameWithBoltPort}`) .then(connection => { connection._handleProtocolError(ILLEGAL_MESSAGE) expect(connection.isOpen()).toBeFalsy() diff --git a/packages/neo4j-driver/test/internal/logger.test.js b/packages/neo4j-driver/test/internal/logger.test.js index 9abedf09a..c247c0d2f 100644 --- a/packages/neo4j-driver/test/internal/logger.test.js +++ b/packages/neo4j-driver/test/internal/logger.test.js @@ -83,7 +83,7 @@ describe('#integration Logger', () => { const logged = [] const config = memorizingLoggerConfig(logged) const driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken, config ) @@ -116,7 +116,7 @@ describe('#integration Logger', () => { console.log = message => logged.push(message) const driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken, { logging: neo4j.logging.console('debug') @@ -153,7 +153,7 @@ describe('#integration Logger', () => { console.log = message => logged.push(message) const driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken, { logging: neo4j.logging.console() diff --git a/packages/neo4j-driver/test/internal/node/package.test.js b/packages/neo4j-driver/test/internal/node/package.test.js index c88adda3f..6106f4133 100644 --- a/packages/neo4j-driver/test/internal/node/package.test.js +++ b/packages/neo4j-driver/test/internal/node/package.test.js @@ -41,7 +41,7 @@ describe('Package', function () { } driver = neo4j.driver( - 'bolt://localhost', + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, neo4j.auth.basic(sharedNeo4j.username, sharedNeo4j.password) ) const session = driver.session() diff --git a/packages/neo4j-driver/test/internal/server-version.test.js b/packages/neo4j-driver/test/internal/server-version.test.js index d99a11278..7e903d792 100644 --- a/packages/neo4j-driver/test/internal/server-version.test.js +++ b/packages/neo4j-driver/test/internal/server-version.test.js @@ -154,7 +154,7 @@ describe('#unit ServerVersion', () => { describe('#integration ServerVersion', () => { it('should fetch version using driver', async () => { const driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) const version = await ServerVersion.fromDriver(driver) diff --git a/packages/neo4j-driver/test/internal/shared-neo4j.js b/packages/neo4j-driver/test/internal/shared-neo4j.js index 441844f3c..9cd14d007 100644 --- a/packages/neo4j-driver/test/internal/shared-neo4j.js +++ b/packages/neo4j-driver/test/internal/shared-neo4j.js @@ -17,114 +17,15 @@ * limitations under the License. */ import neo4j from '../../src' -import { json } from 'neo4j-driver-core' +import Neo4jContainer from './neo4j-container' -class UnsupportedPlatform { - pathJoin () { - throw new Error("Module 'path' is not available on this platform") - } - - spawn (command, args) { - throw new Error("Module 'child_process' is not available on this platform") - } - - listDir (path) { - throw new Error("Module 'fs' is not available on this platform") - } - - removeDir (path) { - throw new Error("Module 'fs' is not available on this platform") - } - - moveDir (from, to) { - throw new Error("Module 'fs' is not available on this platform") - } - - isDirectory (path) { - throw new Error("Module 'fs' is not available on this platform") - } - - env (key) { - throw new Error("Module 'process' is not available on this platform") - } - - cwd () { - throw new Error("Module 'process' is not available on this platform") - } -} - -class SupportedPlatform extends UnsupportedPlatform { - constructor () { - super() - this._env = global.__karma__ ? global.__karma__.config.env : process.env - this._path = require('path') - this._childProcess = require('child_process') - this._fs = require('fs-extra') - this._cwd = global.__karma__ ? global.__karma__.config.basePath : process.cwd() - } - - static create () { - try { - return new SupportedPlatform() - } catch (e) { - return null - } - } - - pathJoin () { - return this._path.join(...Array.from(arguments)) - } - - spawn (command, args) { - const options = { - // ignore stdin, use default values for stdout and stderr - // otherwise spawned java process does not see IPv6 address of the local interface and Neo4j fails to start - // https://github.com/nodejs/node-v0.x-archive/issues/7406 - stdio: ['ignore', null, null] - } - return this._childProcess.spawnSync(command, args, options) - } - - listDir (path) { - return this._fs.readdirSync(path) - } - - removeDir (path) { - if (this.isDirectory(path)) { - this._fs.removeSync(path) - } - } - - moveDir (from, to) { - this._fs.moveSync(from, to, { overwrite: true }) - } - - isDirectory (path) { - try { - this._fs.accessSync(path) - const stat = this._fs.statSync(path) - return stat.isDirectory() - } catch (e) { - return false - } - } - - env (key) { - return this._env[key] - } - - cwd () { - return this._cwd - } -} - -const platform = SupportedPlatform.create() || new UnsupportedPlatform() const env = global.__karma__ ? global.__karma__.config.env : process.env const username = env.TEST_NEO4J_USER || 'neo4j' const password = env.TEST_NEO4J_PASS || 'password' const hostname = env.TEST_NEO4J_HOST || 'localhost' const scheme = env.TEST_NEO4J_SCHEME || 'bolt' +const version = env.TEST_NEO4J_VERSION || '5.8' const cluster = env.TEST_NEO4J_IS_CLUSTER !== undefined ? env.TEST_NEO4J_IS_CLUSTER === '1' @@ -136,176 +37,25 @@ const ipv6Enabled = : true const authToken = neo4j.auth.basic(username, password) -const tlsConfig = { - key: 'dbms.connector.bolt.tls_level', - levels: { - optional: 'OPTIONAL', - required: 'REQUIRED', - disabled: 'DISABLED' - } -} - -const defaultConfig = { - // tell neo4j to listen for IPv6 connections, only supported by 3.1+ - 'dbms.connectors.default_listen_address': '::', - - // HTTP server should keep listening on default address - 'dbms.connector.http.listen_address': 'localhost:7474', - - // shorten the default time to wait for the bookmarks from 30 to 5 seconds - 'dbms.transaction.bookmark_ready_timeout': '5s', - - // make TLS optional - 'dbms.connector.bolt.tls_level': tlsConfig.levels.optional -} - -const NEOCTRL_ARGS = 'NEOCTRL_ARGS' -const neoCtrlVersionParam = '-e' -const defaultNeo4jVersion = '4.0' -const defaultNeoCtrlArgs = `${neoCtrlVersionParam} ${defaultNeo4jVersion}` +const neo4jContainer = new Neo4jContainer({ + user: username, + password, + containerLogs: false, + version, + edition +}) -function neoctrlArgs () { - return platform.env(NEOCTRL_ARGS) || defaultNeoCtrlArgs +async function start () { + await neo4jContainer.start() } -function neoctrlVersion () { - return neoctrlArgs() - .replace(/-e/, '') - .trim() +async function stop () { + await neo4jContainer.stop() } -function neo4jDir () { - return platform.pathJoin( - platform.cwd(), - 'build', - 'neo4j', - neoctrlVersion(), - 'neo4jHome' - ) -} - -function neo4jCertPath () { - return platform.pathJoin(neo4jDir(), 'certificates', 'neo4j.cert') -} - -function neo4jKeyPath () { - return platform.pathJoin(neo4jDir(), 'certificates', 'neo4j.key') -} - -function install () { - const targetDir = neo4jDir() - - if (platform.isDirectory(targetDir)) { - console.log( - `Found existing Neo4j ${neoctrlVersion()} installation at "${targetDir}"` - ) - } else { - const installDir = platform.pathJoin(targetDir, '..') - // first delete any existing data inside our target folder - platform.removeDir(installDir) - - const installArgs = neoctrlArgs() - .split(' ') - .map(a => a.trim()) - installArgs.push(installDir) - - console.log(`Installing neo4j with arguments "${installArgs}"`) - const result = runCommand('neoctrl-install', installArgs) - if (!result.successful) { - throw new Error('Unable to install Neo4j.\n' + result.fullOutput) - } - - const installedNeo4jDir = result.stdout - platform.moveDir(installedNeo4jDir, targetDir) - console.log(`Installed neo4j into "${targetDir}"`) - } -} - -function configure (config) { - console.log( - `Configuring neo4j at "${neo4jDir()}" with "${json.stringify(config)}"` - ) - - const configEntries = Object.keys(config).map(key => `${key}=${config[key]}`) - if (configEntries.length > 0) { - const result = runCommand('neoctrl-configure', [ - neo4jDir(), - ...configEntries - ]) - if (!result.successful) { - throw new Error(`Unable to configure neo4j.\n${result.fullOutput}`) - } - - console.log('Configuration complete.') - } -} - -function createUser (username, password) { - console.log(`Creating user "${username}" on neo4j at "${neo4jDir()}".`) - - const result = runCommand('neoctrl-create-user', [ - neo4jDir(), - username, - password - ]) - if (!result.successful) { - throw new Error(`Unable to create user on neo4j.\n${result.fullOutput}`) - } - console.log('User created.') -} - -function startNeo4j () { - console.log(`Starting neo4j at "${neo4jDir()}".`) - const result = runCommand('neoctrl-start', [neo4jDir()]) - if (!result.successful) { - throw new Error(`Unable to start.\n${result.fullOutput}`) - } - console.log('Neo4j started.') -} - -function stopNeo4j () { - console.log(`Stopping neo4j at "${neo4jDir()}".`) - const result = runCommand('neoctrl-stop', [neo4jDir()]) - if (!result.successful) { - throw new Error(`Unable to stop.\n${result.fullOutput}`) - } - console.log('Neo4j stopped.') -} - -function start () { - const boltKitCheckResult = runCommand('neoctrl-install', ['-h']) - - if (boltKitCheckResult.successful) { - install() - configure(defaultConfig) - createUser(username, password) - startNeo4j() - } else { - console.warn( - "Boltkit unavailable. Please install it by running 'pip install --upgrade boltkit." - ) - console.warn('Integration tests will be skipped.') - console.warn( - "Command 'neoctrl-install -h' resulted in\n" + - boltKitCheckResult.fullOutput - ) - } -} - -function stop () { - stopNeo4j() -} - -function restart (configOverride) { - stopNeo4j() - const newConfig = Object.assign({}, defaultConfig) - if (configOverride) { - Object.keys(configOverride).forEach( - key => (newConfig[key] = configOverride[key]) - ) - } - configure(newConfig) - startNeo4j() +async function restart (configOverride) { + await stop() + await start() } async function cleanupAndGetProtocolVersionAndBookmarks (driver) { @@ -340,32 +90,6 @@ async function getEdition (driver) { } } -function runCommand (command, args) { - const spawnResult = platform.spawn(command, args) - return new RunCommandResult(spawnResult) -} - -class RunCommandResult { - constructor (spawnResult) { - this.successful = spawnResult.status === 0 - this.stdout = (spawnResult.stdout || '').toString().trim() - this.stderr = (spawnResult.stderr || '').toString().trim() - this.fullOutput = - 'STDOUT:\n\t' + - this.stdout + - '\n' + - 'STDERR:\n\t' + - this.stderr + - '\n' + - 'EXIT CODE:\n\t' + - spawnResult.status + - '\n' + - 'ERROR:\n\t' + - spawnResult.error + - '\n' - } -} - const debugLogging = { level: 'debug', logger: (level, message) => console.warn(`${level}: ${message}`) @@ -375,17 +99,24 @@ export default { start: start, stop: stop, restart: restart, - neo4jCertPath: neo4jCertPath, - neo4jKeyPath: neo4jKeyPath, username: username, password: password, authToken: authToken, logging: debugLogging, cleanupAndGetProtocolVersion: cleanupAndGetProtocolVersion, cleanupAndGetProtocolVersionAndBookmarks, - tlsConfig: tlsConfig, getEdition: getEdition, hostname: hostname, + get hostnameWithBoltPort () { + return `${hostname}:${neo4jContainer.getBoltPort()}` + }, + get hostnameWithHttpPort () { + return `${hostname}:${neo4jContainer.getHttpPort()}` + }, + get boltPort () { + return neo4jContainer.getBoltPort() + }, + isTestContainer: true, ipv6Enabled: ipv6Enabled, edition: edition, scheme: scheme, diff --git a/packages/neo4j-driver/test/nested-statements.test.js b/packages/neo4j-driver/test/nested-statements.test.js index 262ee4f9a..79230c405 100644 --- a/packages/neo4j-driver/test/nested-statements.test.js +++ b/packages/neo4j-driver/test/nested-statements.test.js @@ -26,7 +26,7 @@ describe('#integration session', () => { beforeEach(async () => { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) session = driver.session({ fetchSize: 2 }) diff --git a/packages/neo4j-driver/test/result.test.js b/packages/neo4j-driver/test/result.test.js index 035c3c059..6b9c52be8 100644 --- a/packages/neo4j-driver/test/result.test.js +++ b/packages/neo4j-driver/test/result.test.js @@ -26,7 +26,7 @@ describe('#integration result stream', () => { beforeEach(async () => { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) session = driver.session() diff --git a/packages/neo4j-driver/test/rx/navigation.test.js b/packages/neo4j-driver/test/rx/navigation.test.js index d49a03b65..377eac931 100644 --- a/packages/neo4j-driver/test/rx/navigation.test.js +++ b/packages/neo4j-driver/test/rx/navigation.test.js @@ -36,7 +36,7 @@ describe('#integration-rx navigation', () => { beforeEach(async () => { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) session = driver.rxSession() @@ -199,7 +199,7 @@ describe('#integration-rx navigation', () => { beforeEach(async () => { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) session = driver.rxSession() diff --git a/packages/neo4j-driver/test/rx/nested-statements.test.js b/packages/neo4j-driver/test/rx/nested-statements.test.js index f3f0233a8..ea5e58bb2 100644 --- a/packages/neo4j-driver/test/rx/nested-statements.test.js +++ b/packages/neo4j-driver/test/rx/nested-statements.test.js @@ -41,7 +41,7 @@ describe('#integration-rx transaction', () => { beforeEach(async () => { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) session = driver.rxSession() diff --git a/packages/neo4j-driver/test/rx/session.test.js b/packages/neo4j-driver/test/rx/session.test.js index 6f4e587a6..2aee9aa26 100644 --- a/packages/neo4j-driver/test/rx/session.test.js +++ b/packages/neo4j-driver/test/rx/session.test.js @@ -42,7 +42,7 @@ describe('#integration rx-session', () => { beforeEach(async () => { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) session = driver.rxSession() diff --git a/packages/neo4j-driver/test/rx/summary.test.js b/packages/neo4j-driver/test/rx/summary.test.js index 2c961089e..5edaa9b0c 100644 --- a/packages/neo4j-driver/test/rx/summary.test.js +++ b/packages/neo4j-driver/test/rx/summary.test.js @@ -33,7 +33,7 @@ describe('#integration-rx summary', () => { beforeEach(async () => { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) session = driver.rxSession() @@ -126,7 +126,7 @@ describe('#integration-rx summary', () => { beforeEach(async () => { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) session = driver.rxSession() @@ -226,7 +226,7 @@ describe('#integration-rx summary', () => { beforeEach(async () => { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) session = driver.rxSession({ database: 'system' }) diff --git a/packages/neo4j-driver/test/rx/transaction.test.js b/packages/neo4j-driver/test/rx/transaction.test.js index eea506f53..7e6434b5d 100644 --- a/packages/neo4j-driver/test/rx/transaction.test.js +++ b/packages/neo4j-driver/test/rx/transaction.test.js @@ -41,7 +41,7 @@ describe('#integration-rx transaction', () => { beforeEach(async () => { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) session = driver.rxSession() diff --git a/packages/neo4j-driver/test/session.test.js b/packages/neo4j-driver/test/session.test.js index 477960a5c..7d114126f 100644 --- a/packages/neo4j-driver/test/session.test.js +++ b/packages/neo4j-driver/test/session.test.js @@ -42,7 +42,7 @@ describe('#integration session', () => { beforeEach(async () => { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) session = driver.session() @@ -56,7 +56,7 @@ describe('#integration session', () => { it('should be possible to close driver after closing session with failed tx ', done => { const driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) const session = driver.session() @@ -187,7 +187,7 @@ describe('#integration session', () => { session.run(query).then(result => { const sum = result.summary expect(sum.server).toBeDefined() - expect(sum.server.address).toEqual(`${sharedNeo4j.hostname}:7687`) + expect(sum.server.address).toEqual(`${sharedNeo4j.hostnameWithBoltPort}`) expect(sum.server.version).toBeUndefined() done() }) @@ -1194,7 +1194,7 @@ describe('#integration session', () => { function numberOfAcquiredConnectionsFromPool () { const pool = driver._connectionProvider._connectionPool return pool.activeResourceCount( - ServerAddress.fromUrl(`${sharedNeo4j.hostname}:7687`) + ServerAddress.fromUrl(`${sharedNeo4j.hostnameWithBoltPort}`) ) } diff --git a/packages/neo4j-driver/test/spatial-types.test.js b/packages/neo4j-driver/test/spatial-types.test.js index c18505acd..d53deee8e 100644 --- a/packages/neo4j-driver/test/spatial-types.test.js +++ b/packages/neo4j-driver/test/spatial-types.test.js @@ -35,11 +35,11 @@ describe('#integration spatial-types', () => { beforeAll(() => { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) driverWithNativeNumbers = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken, { disableLosslessIntegers: true } ) diff --git a/packages/neo4j-driver/test/stress-test.js b/packages/neo4j-driver/test/stress-test.js index 272d56c65..8aeeb46d7 100644 --- a/packages/neo4j-driver/test/stress-test.js +++ b/packages/neo4j-driver/test/stress-test.js @@ -45,7 +45,7 @@ const WRITE_QUERY = const TEST_MODE = modeFromEnvOrDefault('STRESS_TEST_MODE') const DATABASE_URI = fromEnvOrDefault( 'STRESS_TEST_DATABASE_URI', - `${sharedNeo4j.scheme}://${sharedNeo4j.hostname}:${sharedNeo4j.port}` + `${sharedNeo4j.scheme}://${sharedNeo4j.hostnameWithBoltPort}}` ) const RUNNING_TIME_IN_SECONDS = parseInt( diff --git a/packages/neo4j-driver/test/stress.test.js b/packages/neo4j-driver/test/stress.test.js index 9127cfe85..79248432c 100644 --- a/packages/neo4j-driver/test/stress.test.js +++ b/packages/neo4j-driver/test/stress.test.js @@ -48,7 +48,7 @@ describe('#integration stress tests', () => { const TEST_MODE = modeFromEnvOrDefault('STRESS_TEST_MODE') const DATABASE_URI = fromEnvOrDefault( 'STRESS_TEST_DATABASE_URI', - `${sharedNeo4j.scheme}://${sharedNeo4j.hostname}:${sharedNeo4j.port}` + `${sharedNeo4j.scheme}://${sharedNeo4j.hostnameWithBoltPort}}` ) const USERNAME = fromEnvOrDefault( diff --git a/packages/neo4j-driver/test/summary.test.js b/packages/neo4j-driver/test/summary.test.js index fa1ce77a7..0eb0dfb50 100644 --- a/packages/neo4j-driver/test/summary.test.js +++ b/packages/neo4j-driver/test/summary.test.js @@ -26,7 +26,7 @@ describe('#integration result summary', () => { beforeEach(done => { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) session = driver.session() @@ -64,7 +64,7 @@ describe('#integration result summary', () => { beforeEach(done => { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken, { disableLosslessIntegers: true diff --git a/packages/neo4j-driver/test/temporal-types.test.js b/packages/neo4j-driver/test/temporal-types.test.js index 39a1132d7..d135542e0 100644 --- a/packages/neo4j-driver/test/temporal-types.test.js +++ b/packages/neo4j-driver/test/temporal-types.test.js @@ -54,11 +54,11 @@ describe('#integration temporal-types', () => { beforeAll(() => { driver = neo4j.driver( - `${sharedNeo4j.scheme}://${sharedNeo4j.hostname}`, + `${sharedNeo4j.scheme}://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) driverWithNativeNumbers = neo4j.driver( - `${sharedNeo4j.scheme}://${sharedNeo4j.hostname}`, + `${sharedNeo4j.scheme}://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken, { disableLosslessIntegers: true } ) diff --git a/packages/neo4j-driver/test/transaction.test.js b/packages/neo4j-driver/test/transaction.test.js index 548f793f3..5846a3ba9 100644 --- a/packages/neo4j-driver/test/transaction.test.js +++ b/packages/neo4j-driver/test/transaction.test.js @@ -26,7 +26,7 @@ describe('#integration transaction', () => { beforeEach(async () => { driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) session = driver.session() @@ -306,7 +306,7 @@ describe('#integration transaction', () => { .then(result => { const sum = result.summary expect(sum.server).toBeDefined() - expect(sum.server.address).toEqual(`${sharedNeo4j.hostname}:7687`) + expect(sum.server.address).toEqual(`${sharedNeo4j.hostnameWithBoltPort}`) expect(sum.server.version).toBeUndefined() tx.commit().then(done) }) @@ -326,7 +326,7 @@ describe('#integration transaction', () => { const server = summary.server expect(server).toBeDefined() - expect(server.address).toEqual(`${sharedNeo4j.hostname}:7687`) + expect(server.address).toEqual(`${sharedNeo4j.hostnameWithBoltPort}`) expect(server.version).toBeUndefined() done() } diff --git a/packages/neo4j-driver/test/types.test.js b/packages/neo4j-driver/test/types.test.js index 4570469d7..ff3db4554 100644 --- a/packages/neo4j-driver/test/types.test.js +++ b/packages/neo4j-driver/test/types.test.js @@ -71,7 +71,7 @@ describe('#integration node values', () => { it('should support returning nodes ', done => { // Given const driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) const session = driver.session() @@ -95,7 +95,7 @@ describe('#integration relationship values', () => { it('should support returning relationships', done => { // Given const driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) const session = driver.session() @@ -119,7 +119,7 @@ describe('#integration path values', () => { it('should support returning paths', done => { // Given const driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) const session = driver.session() @@ -177,7 +177,7 @@ describe('#integration byte arrays', () => { it('should fail to return byte array if server does not support byte arrays', done => { const driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) const session = driver.session() @@ -196,7 +196,7 @@ describe('#integration byte arrays', () => { function testValue (actual, expected) { return done => { const driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) const queryPromise = runReturnQuery(driver, actual, expected) @@ -211,7 +211,7 @@ function testValue (actual, expected) { function testValues (values) { return done => { const driver = neo4j.driver( - `bolt://${sharedNeo4j.hostname}`, + `bolt://${sharedNeo4j.hostnameWithBoltPort}`, sharedNeo4j.authToken ) const queriesPromise = values.reduce( From ec12757064a4f338abacceada78e336191a96327 Mon Sep 17 00:00:00 2001 From: Antonio Barcelos Date: Fri, 4 Aug 2023 14:45:07 +0200 Subject: [PATCH 02/16] Add missing file --- packages/neo4j-driver/test/internal/shared-neo4j.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/neo4j-driver/test/internal/shared-neo4j.js b/packages/neo4j-driver/test/internal/shared-neo4j.js index 9cd14d007..da9c07eb6 100644 --- a/packages/neo4j-driver/test/internal/shared-neo4j.js +++ b/packages/neo4j-driver/test/internal/shared-neo4j.js @@ -21,11 +21,16 @@ import Neo4jContainer from './neo4j-container' const env = global.__karma__ ? global.__karma__.config.env : process.env +console.error(env) const username = env.TEST_NEO4J_USER || 'neo4j' const password = env.TEST_NEO4J_PASS || 'password' const hostname = env.TEST_NEO4J_HOST || 'localhost' const scheme = env.TEST_NEO4J_SCHEME || 'bolt' const version = env.TEST_NEO4J_VERSION || '5.8' +const testcontainersDisabled = env.TEST_CONTAINERS_DISABLED !== undefined + ? env.TEST_CONTAINERS_DISABLED.toUpperCase() === 'TRUE' + : false + const cluster = env.TEST_NEO4J_IS_CLUSTER !== undefined ? env.TEST_NEO4J_IS_CLUSTER === '1' @@ -42,7 +47,8 @@ const neo4jContainer = new Neo4jContainer({ password, containerLogs: false, version, - edition + edition, + disabled: testcontainersDisabled }) async function start () { From 7eb06eb116d36506b2f25eaf716d303ba93dac3b Mon Sep 17 00:00:00 2001 From: Antonio Barcelos Date: Fri, 4 Aug 2023 14:55:18 +0200 Subject: [PATCH 03/16] Remove colision with testkit Co-Authored-by: Conor Watson --- .../test/internal/neo4j-container.js | 66 +++++++++++++++++++ testkit/integration.py | 7 +- 2 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 packages/neo4j-driver/test/internal/neo4j-container.js diff --git a/packages/neo4j-driver/test/internal/neo4j-container.js b/packages/neo4j-driver/test/internal/neo4j-container.js new file mode 100644 index 000000000..9025dabf1 --- /dev/null +++ b/packages/neo4j-driver/test/internal/neo4j-container.js @@ -0,0 +1,66 @@ + +export default class Neo4jContainer { + constructor ({ user, password, containerLogs, version, edition, disabled }) { + this._user = user + this._password = password + this._containerLogs = containerLogs || false + this._version = version + this._edition = edition + this._container = null + this._disabled = disabled || false + } + + async start () { + if (this._disabled) { + return + } + console.log('Starting container') + if (this._container != null) { + console.log('Container already started') + return + } + + const tag = this._edition != null ? `${this._version}-${this._edition}` : this._version + + const { GenericContainer, Wait } = require('testcontainers') + const { DockerImageName } = require('testcontainers/dist/docker-image-name') + + let container = new GenericContainer(new DockerImageName(null, 'neo4j', tag).toString()) + .withEnv('NEO4J_AUTH', `${this._user}/${this._password}`) + + if (this._edition === 'enterprise') { + container = container.withEnv('NEO4J_ACCEPT_LICENSE_AGREEMENT', 'yes') + } + + this._container = await container.withExposedPorts(7687, 7474) + .withWaitStrategy(Wait.forLogMessage(/Started/)) + .start() + + console.log('Container started at ' + `${this._container.getHost()}:${this._container.getMappedPort(7687)}`) + + if (this._containerLogs) { + const stream = await this._container.logs() + stream + .on('data', line => console.log(line)) + .on('err', line => console.error(line)) + .on('end', () => console.log('Stream closed')) + } + } + + getBoltPort () { + return this.getMappedPort(7687) + } + + getHttpPort () { + return this.getMappedPort(7474) + } + + getMappedPort (port) { + return this._container != null ? this._container.getMappedPort(port) : port + } + + async stop () { + await this._container.stop() + this._container = undefined + } +} diff --git a/testkit/integration.py b/testkit/integration.py index 165d84fb5..17699ffcc 100644 --- a/testkit/integration.py +++ b/testkit/integration.py @@ -9,6 +9,7 @@ if __name__ == "__main__": os.environ["TEST_NEO4J_IPV6_ENABLED"] = "False" + os.environ["TEST_CONTAINERS_DISABLED"] = "True" if is_lite(): ignore = "--ignore=neo4j-driver" @@ -18,6 +19,8 @@ if is_deno(): pass elif is_browser(): - run_in_driver_repo(["npm", "run", "test::browser", "--", ignore]) + run_in_driver_repo(["npm", "run", "test::browser", + "--", ignore], env=os.environ) else: - run_in_driver_repo(["npm", "run", "test::integration", "--", ignore]) + run_in_driver_repo( + ["npm", "run", "test::integration", "--", ignore], env=os.environ) From c4536fe83685837c426576c292f14d5d395bff6e Mon Sep 17 00:00:00 2001 From: Antonio Barcelos Date: Fri, 4 Aug 2023 14:59:55 +0200 Subject: [PATCH 04/16] Remove debug --- packages/neo4j-driver/test/internal/shared-neo4j.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/neo4j-driver/test/internal/shared-neo4j.js b/packages/neo4j-driver/test/internal/shared-neo4j.js index da9c07eb6..fdd8effc8 100644 --- a/packages/neo4j-driver/test/internal/shared-neo4j.js +++ b/packages/neo4j-driver/test/internal/shared-neo4j.js @@ -21,7 +21,6 @@ import Neo4jContainer from './neo4j-container' const env = global.__karma__ ? global.__karma__.config.env : process.env -console.error(env) const username = env.TEST_NEO4J_USER || 'neo4j' const password = env.TEST_NEO4J_PASS || 'password' const hostname = env.TEST_NEO4J_HOST || 'localhost' From 9efdd7dfb9c7be8cfde8fa3ab13eb48e03ee9a44 Mon Sep 17 00:00:00 2001 From: Antonio Barcelos Date: Fri, 4 Aug 2023 16:51:21 +0200 Subject: [PATCH 05/16] Remove direct dependency to testcontainer to enable karma build the tests to run in browser --- packages/neo4j-driver/gulpfile.babel.js | 2 +- .../test/browser/karma-chrome.conf.js | 2 +- .../test/browser/karma-firefox.conf.js | 2 +- .../test/internal/browser/testcontainer.js | 13 +++++++++++++ .../test/internal/neo4j-container.js | 17 +++++++++-------- .../test/internal/node/testcontainer.js | 8 ++++++++ .../neo4j-driver/test/internal/shared-neo4j.js | 9 ++++++++- 7 files changed, 41 insertions(+), 12 deletions(-) create mode 100644 packages/neo4j-driver/test/internal/browser/testcontainer.js create mode 100644 packages/neo4j-driver/test/internal/node/testcontainer.js diff --git a/packages/neo4j-driver/gulpfile.babel.js b/packages/neo4j-driver/gulpfile.babel.js index d1603d85a..543d5b275 100644 --- a/packages/neo4j-driver/gulpfile.babel.js +++ b/packages/neo4j-driver/gulpfile.babel.js @@ -237,7 +237,7 @@ gulp.task('run-ts-declaration-tests', function (done) { gulp.task('all', gulp.series('nodejs', 'browser')) -gulp.task('test-browser', gulp.series('browser', 'run-browser-test')) +gulp.task('test-browser', gulp.series('browser', 'start-neo4j', 'run-browser-test')) gulp.task( 'test', diff --git a/packages/neo4j-driver/test/browser/karma-chrome.conf.js b/packages/neo4j-driver/test/browser/karma-chrome.conf.js index 7ff9cddcf..5ff9fb939 100644 --- a/packages/neo4j-driver/test/browser/karma-chrome.conf.js +++ b/packages/neo4j-driver/test/browser/karma-chrome.conf.js @@ -54,7 +54,7 @@ module.exports = function (config) { concurrency: 1, browserNoActivityTimeout: 30 * 60 * 1000, client: { - env: process.env + env: { ...process.env, TEST_CONTAINERS_DISABLED: 'TRUE' } } }) } diff --git a/packages/neo4j-driver/test/browser/karma-firefox.conf.js b/packages/neo4j-driver/test/browser/karma-firefox.conf.js index 95b64ddfc..d4c50de74 100644 --- a/packages/neo4j-driver/test/browser/karma-firefox.conf.js +++ b/packages/neo4j-driver/test/browser/karma-firefox.conf.js @@ -68,7 +68,7 @@ module.exports = function (config) { } }, client: { - env: process.env + env: { ...process.env, TEST_CONTAINERS_DISABLED: 'TRUE' } } }) } diff --git a/packages/neo4j-driver/test/internal/browser/testcontainer.js b/packages/neo4j-driver/test/internal/browser/testcontainer.js new file mode 100644 index 000000000..bb6df6ea1 --- /dev/null +++ b/packages/neo4j-driver/test/internal/browser/testcontainer.js @@ -0,0 +1,13 @@ +export class GenericContainer { + +} + +export class DockerImageName { + +} + +export class Wait { + static forLogMessage () { + + } +} diff --git a/packages/neo4j-driver/test/internal/neo4j-container.js b/packages/neo4j-driver/test/internal/neo4j-container.js index 9025dabf1..51a8efca2 100644 --- a/packages/neo4j-driver/test/internal/neo4j-container.js +++ b/packages/neo4j-driver/test/internal/neo4j-container.js @@ -22,8 +22,9 @@ export default class Neo4jContainer { const tag = this._edition != null ? `${this._version}-${this._edition}` : this._version - const { GenericContainer, Wait } = require('testcontainers') - const { DockerImageName } = require('testcontainers/dist/docker-image-name') + // Browser does not support testcontainers + const path = globalThis.Window ? './browser/testcontainer' : './node/testcontainer' + const { GenericContainer, DockerImageName, Wait } = require(path) let container = new GenericContainer(new DockerImageName(null, 'neo4j', tag).toString()) .withEnv('NEO4J_AUTH', `${this._user}/${this._password}`) @@ -47,16 +48,16 @@ export default class Neo4jContainer { } } - getBoltPort () { - return this.getMappedPort(7687) + getBoltPort (defaultPort = 7687) { + return this.getMappedPort(7687, defaultPort) } - getHttpPort () { - return this.getMappedPort(7474) + getHttpPort (defaultPort = 7474) { + return this.getMappedPort(7474, defaultPort) } - getMappedPort (port) { - return this._container != null ? this._container.getMappedPort(port) : port + getMappedPort (port, defaultPort) { + return this._container != null ? this._container.getMappedPort(port) : defaultPort } async stop () { diff --git a/packages/neo4j-driver/test/internal/node/testcontainer.js b/packages/neo4j-driver/test/internal/node/testcontainer.js new file mode 100644 index 000000000..941297e48 --- /dev/null +++ b/packages/neo4j-driver/test/internal/node/testcontainer.js @@ -0,0 +1,8 @@ +const { GenericContainer, Wait } = require('testcontainers') +const { DockerImageName } = require('testcontainers/dist/docker-image-name') + +module.exports = { + GenericContainer, + Wait, + DockerImageName +} diff --git a/packages/neo4j-driver/test/internal/shared-neo4j.js b/packages/neo4j-driver/test/internal/shared-neo4j.js index fdd8effc8..779ee250c 100644 --- a/packages/neo4j-driver/test/internal/shared-neo4j.js +++ b/packages/neo4j-driver/test/internal/shared-neo4j.js @@ -26,6 +26,8 @@ const password = env.TEST_NEO4J_PASS || 'password' const hostname = env.TEST_NEO4J_HOST || 'localhost' const scheme = env.TEST_NEO4J_SCHEME || 'bolt' const version = env.TEST_NEO4J_VERSION || '5.8' +const httpPort = env.TEST_NEO4J_HTTP_PORT || 7474 +const boltPort = env.TEST_NEO4J_BOLT_PORT || 7687 const testcontainersDisabled = env.TEST_CONTAINERS_DISABLED !== undefined ? env.TEST_CONTAINERS_DISABLED.toUpperCase() === 'TRUE' : false @@ -52,6 +54,8 @@ const neo4jContainer = new Neo4jContainer({ async function start () { await neo4jContainer.start() + env.TEST_NEO4J_BOLT_PORT = neo4jContainer.getBoltPort(boltPort) + env.TEST_NEO4J_HTTP_PORT = neo4jContainer.getHttpPort(httpPort) } async function stop () { @@ -119,7 +123,10 @@ export default { return `${hostname}:${neo4jContainer.getHttpPort()}` }, get boltPort () { - return neo4jContainer.getBoltPort() + return neo4jContainer.getBoltPort(boltPort) + }, + get httpPort () { + return neo4jContainer.getHttpPort(httpPort) }, isTestContainer: true, ipv6Enabled: ipv6Enabled, From 9b59b3603d8d076b304d18f4a0c71d9387d5c5ae Mon Sep 17 00:00:00 2001 From: Antonio Barcelos Date: Mon, 7 Aug 2023 12:19:49 +0200 Subject: [PATCH 06/16] Enable tests to run on browser --- packages/neo4j-driver/gulpfile.babel.js | 15 +++++++++------ .../test/browser/karma-chrome.conf.js | 3 ++- .../test/browser/karma-firefox.conf.js | 4 +++- .../neo4j-driver/test/internal/shared-neo4j.js | 11 +++++++---- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/packages/neo4j-driver/gulpfile.babel.js b/packages/neo4j-driver/gulpfile.babel.js index 543d5b275..dfa2b3ec9 100644 --- a/packages/neo4j-driver/gulpfile.babel.js +++ b/packages/neo4j-driver/gulpfile.babel.js @@ -144,11 +144,13 @@ gulp.task('test-nodejs-integration', async () => { return runJasmineTests('#integration*') }) -gulp.task('run-browser-test-chrome', function (cb) { +gulp.task('run-browser-test-chrome', async function (cb) { + await sharedNeo4j.start() runKarma('chrome', cb) }) -gulp.task('run-browser-test-firefox', function (cb) { +gulp.task('run-browser-test-firefox', async function (cb) { + await sharedNeo4j.start() runKarma('firefox', cb) }) @@ -191,11 +193,11 @@ gulp.task('set', function () { }) gulp.task('start-neo4j', function (done) { - sharedNeo4j.start().then(done) + sharedNeo4j.start().then(done).catch(error => done.fail(error)) }) gulp.task('stop-neo4j', function (done) { - sharedNeo4j.stop().then(done) + sharedNeo4j.stop().then(done).catch(error => done.fail(error)) }) gulp.task('run-stress-tests', function () { @@ -210,7 +212,8 @@ gulp.task('run-stress-tests', function () { .on('end', logActiveNodeHandles) }) -gulp.task('run-stress-tests-without-jasmine', function () { +gulp.task('run-stress-tests-without-jasmine', async function () { + await sharedNeo4j.start() const stresstest = require('./test/stress-test') return stresstest() }) @@ -237,7 +240,7 @@ gulp.task('run-ts-declaration-tests', function (done) { gulp.task('all', gulp.series('nodejs', 'browser')) -gulp.task('test-browser', gulp.series('browser', 'start-neo4j', 'run-browser-test')) +gulp.task('test-browser', gulp.series('start-neo4j', 'browser', 'run-browser-test')) gulp.task( 'test', diff --git a/packages/neo4j-driver/test/browser/karma-chrome.conf.js b/packages/neo4j-driver/test/browser/karma-chrome.conf.js index 5ff9fb939..be891378f 100644 --- a/packages/neo4j-driver/test/browser/karma-chrome.conf.js +++ b/packages/neo4j-driver/test/browser/karma-chrome.conf.js @@ -17,6 +17,7 @@ * limitations under the License. */ module.exports = function (config) { + process.env.TEST_CONTAINERS_DISABLED = 'TRUE' config.set({ basePath: '../../', karmaTypescriptConfig: { @@ -54,7 +55,7 @@ module.exports = function (config) { concurrency: 1, browserNoActivityTimeout: 30 * 60 * 1000, client: { - env: { ...process.env, TEST_CONTAINERS_DISABLED: 'TRUE' } + env: process.env } }) } diff --git a/packages/neo4j-driver/test/browser/karma-firefox.conf.js b/packages/neo4j-driver/test/browser/karma-firefox.conf.js index d4c50de74..0ef299b63 100644 --- a/packages/neo4j-driver/test/browser/karma-firefox.conf.js +++ b/packages/neo4j-driver/test/browser/karma-firefox.conf.js @@ -16,7 +16,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + module.exports = function (config) { + process.env.TEST_CONTAINERS_DISABLED = 'TRUE' config.set({ basePath: '../../', karmaTypescriptConfig: { @@ -68,7 +70,7 @@ module.exports = function (config) { } }, client: { - env: { ...process.env, TEST_CONTAINERS_DISABLED: 'TRUE' } + env: process.env } }) } diff --git a/packages/neo4j-driver/test/internal/shared-neo4j.js b/packages/neo4j-driver/test/internal/shared-neo4j.js index 779ee250c..d233c3eed 100644 --- a/packages/neo4j-driver/test/internal/shared-neo4j.js +++ b/packages/neo4j-driver/test/internal/shared-neo4j.js @@ -28,6 +28,7 @@ const scheme = env.TEST_NEO4J_SCHEME || 'bolt' const version = env.TEST_NEO4J_VERSION || '5.8' const httpPort = env.TEST_NEO4J_HTTP_PORT || 7474 const boltPort = env.TEST_NEO4J_BOLT_PORT || 7687 + const testcontainersDisabled = env.TEST_CONTAINERS_DISABLED !== undefined ? env.TEST_CONTAINERS_DISABLED.toUpperCase() === 'TRUE' : false @@ -54,8 +55,10 @@ const neo4jContainer = new Neo4jContainer({ async function start () { await neo4jContainer.start() - env.TEST_NEO4J_BOLT_PORT = neo4jContainer.getBoltPort(boltPort) - env.TEST_NEO4J_HTTP_PORT = neo4jContainer.getHttpPort(httpPort) + if (global.process) { + global.process.env.TEST_NEO4J_BOLT_PORT = neo4jContainer.getBoltPort(boltPort) + global.process.env.TEST_NEO4J_HTTP_PORT = neo4jContainer.getHttpPort(httpPort) + } } async function stop () { @@ -117,10 +120,10 @@ export default { getEdition: getEdition, hostname: hostname, get hostnameWithBoltPort () { - return `${hostname}:${neo4jContainer.getBoltPort()}` + return `${hostname}:${neo4jContainer.getBoltPort(boltPort)}` }, get hostnameWithHttpPort () { - return `${hostname}:${neo4jContainer.getHttpPort()}` + return `${hostname}:${neo4jContainer.getHttpPort(httpPort)}` }, get boltPort () { return neo4jContainer.getBoltPort(boltPort) From f7db946d0e5ed11c132089135deba2e236e502f5 Mon Sep 17 00:00:00 2001 From: Antonio Barcelos Date: Mon, 7 Aug 2023 13:05:35 +0200 Subject: [PATCH 07/16] Enable npm run test --- .../neo4j-driver/test/internal/neo4j-container.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/neo4j-driver/test/internal/neo4j-container.js b/packages/neo4j-driver/test/internal/neo4j-container.js index 51a8efca2..e45548667 100644 --- a/packages/neo4j-driver/test/internal/neo4j-container.js +++ b/packages/neo4j-driver/test/internal/neo4j-container.js @@ -8,9 +8,11 @@ export default class Neo4jContainer { this._edition = edition this._container = null this._disabled = disabled || false + this._usages = 0 } async start () { + this._usages++ if (this._disabled) { return } @@ -61,7 +63,13 @@ export default class Neo4jContainer { } async stop () { - await this._container.stop() - this._container = undefined + this._usages-- + if (this._usages <= 0) { + this._usages = 0 + if (this._container != null) { + await this._container.stop() + } + this._container = undefined + } } } From fb35eb8d2b2235c78bb5bd1a36dc35fe62368842 Mon Sep 17 00:00:00 2001 From: Antonio Barcelos Date: Mon, 7 Aug 2023 13:15:27 +0200 Subject: [PATCH 08/16] trying before all/after all --- packages/neo4j-driver/test/internal/shared-neo4j.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/neo4j-driver/test/internal/shared-neo4j.js b/packages/neo4j-driver/test/internal/shared-neo4j.js index d233c3eed..e092d65cf 100644 --- a/packages/neo4j-driver/test/internal/shared-neo4j.js +++ b/packages/neo4j-driver/test/internal/shared-neo4j.js @@ -107,6 +107,16 @@ const debugLogging = { logger: (level, message) => console.warn(`${level}: ${message}`) } +if (global.beforeAll) { + beforeAll(async () => { + await neo4jContainer.start() + }) + + afterAll(async () => { + await neo4jContainer.stop() + }) +} + export default { start: start, stop: stop, From e6d0e9e2a1ca5704dd4a811ebf618457be1f2c1b Mon Sep 17 00:00:00 2001 From: Antonio Barcelos Date: Mon, 7 Aug 2023 14:35:40 +0200 Subject: [PATCH 09/16] Fix stress.py --- testkit/stress.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/testkit/stress.py b/testkit/stress.py index 43332f83e..e734f737d 100644 --- a/testkit/stress.py +++ b/testkit/stress.py @@ -9,6 +9,7 @@ if __name__ == "__main__": os.environ["STRESS_TEST_MODE"] = "fastest" + os.environ["TEST_CONTAINERS_DISABLED"] = "True" os.environ["RUNNING_TIME_IN_SECONDS"] = \ os.environ.get("TEST_NEO4J_STRESS_DURATION", 0) @@ -19,4 +20,5 @@ ignore = "--ignore=neo4j-driver-lite" if not is_deno(): - run_in_driver_repo(["npm", "run", "test::stress", "--", ignore]) + run_in_driver_repo(["npm", "run", "test::stress", "--", ignore], + env=os.environ) From 0107627e8cbe5c46c0435d0fa82dc2b7adf18984 Mon Sep 17 00:00:00 2001 From: Antonio Barcelos Date: Mon, 7 Aug 2023 19:44:39 +0200 Subject: [PATCH 10/16] Add testcontainer to neo4j-driver-lite --- packages/neo4j-driver-lite/package-lock.json | 1271 ++++++++++++++++- packages/neo4j-driver-lite/package.json | 1 + .../test/integration/browser.environment.js | 6 + .../test/integration/browser/testcontainer.js | 13 + .../test/integration/config.ts | 39 +- .../test/integration/driver.test.ts | 28 +- .../test/integration/node/testcontainer.js | 8 + 7 files changed, 1303 insertions(+), 63 deletions(-) create mode 100644 packages/neo4j-driver-lite/test/integration/browser/testcontainer.js create mode 100644 packages/neo4j-driver-lite/test/integration/node/testcontainer.js diff --git a/packages/neo4j-driver-lite/package-lock.json b/packages/neo4j-driver-lite/package-lock.json index 271368b2a..fdda4eaf9 100644 --- a/packages/neo4j-driver-lite/package-lock.json +++ b/packages/neo4j-driver-lite/package-lock.json @@ -20,6 +20,7 @@ "jest": "^27.5.1", "rollup": "^2.77.4-1", "rollup-plugin-polyfill-node": "^0.11.0", + "testcontainers": "^8.16.0", "ts-jest": "^27.1.4", "ts-node": "^10.9.1", "typescript": "^4.9.5", @@ -580,6 +581,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", @@ -1118,6 +1125,15 @@ "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", "dev": true }, + "node_modules/@types/archiver": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-5.3.2.tgz", + "integrity": "sha512-IctHreBuWE5dvBDz/0WeKtyVKVRs4h75IblxOACL92wU66v+HGAfEYAOyXkOFphvRJMhuXdI9huDXpX0FC6lCw==", + "dev": true, + "dependencies": { + "@types/readdir-glob": "*" + } + }, "node_modules/@types/babel__core": { "version": "7.1.20", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz", @@ -1159,6 +1175,26 @@ "@babel/types": "^7.3.0" } }, + "node_modules/@types/docker-modem": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/docker-modem/-/docker-modem-3.0.3.tgz", + "integrity": "sha512-i1A2Etnav7uHizZ87vUf4EqwJehY3JOcTfBS0pGBlO+HQ0jg2lUMCaJRg9VQM8ldZkpYdIfsenxcTOCpwxPXEg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/ssh2": "*" + } + }, + "node_modules/@types/dockerode": { + "version": "3.3.19", + "resolved": "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.3.19.tgz", + "integrity": "sha512-7CC5yIpQi+bHXwDK43b/deYXteP3Lem9gdocVVHJPSRJJLMfbiOchQV3rDmAPkMw+n3GIVj7m1six3JW+VcwwA==", + "dev": true, + "dependencies": { + "@types/docker-modem": "*", + "@types/node": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", @@ -1220,6 +1256,15 @@ "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", "dev": true }, + "node_modules/@types/readdir-glob": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/readdir-glob/-/readdir-glob-1.1.1.tgz", + "integrity": "sha512-ImM6TmoF8bgOwvehGviEj3tRdRBbQujr1N+0ypaln/GWjaerOB26jb93vsRHmdMtvVQZQebOlqt2HROark87mQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -1229,6 +1274,24 @@ "@types/node": "*" } }, + "node_modules/@types/ssh2": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.11.13.tgz", + "integrity": "sha512-08WbG68HvQ2YVi74n2iSUnYHYpUdFc/s2IsI0BHBdJwaqYJpWlVv9elL0tYShTv60yr0ObdxJR5NrCRiGJ/0CQ==", + "dev": true, + "dependencies": { + "@types/node": "^18.11.18" + } + }, + "node_modules/@types/ssh2-streams": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/@types/ssh2-streams/-/ssh2-streams-0.1.9.tgz", + "integrity": "sha512-I2J9jKqfmvXLR5GomDiCoHrEJ58hAOmFrekfFqmCFd+A6gaEStvWnPykoWUwld1PNg4G5ag1LwdA+Lz1doRJqg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -1380,6 +1443,75 @@ "node": ">= 8" } }, + "node_modules/archiver": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz", + "integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==", + "dev": true, + "dependencies": { + "archiver-utils": "^2.1.0", + "async": "^3.2.3", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.0.0", + "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-utils/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/archiver-utils/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/archiver-utils/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -1396,11 +1528,10 @@ } }, "node_modules/asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "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, - "optional": true, "dependencies": { "safer-buffer": "~2.1.0" } @@ -1415,6 +1546,12 @@ "node": ">=0.8" } }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -1732,16 +1869,46 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "dev": true, - "optional": true, "dependencies": { "tweetnacl": "^0.14.3" } }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -1829,12 +1996,55 @@ "node-int64": "^0.4.0" } }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": 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-modules": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", @@ -1847,6 +2057,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1933,6 +2152,12 @@ "@types/node": "*" } }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, "node_modules/ci-info": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", @@ -2014,6 +2239,21 @@ "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true }, + "node_modules/compress-commons": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", + "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", + "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/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2040,6 +2280,46 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, + "node_modules/cpu-features": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.8.tgz", + "integrity": "sha512-BbHBvtYhUhksqTjr6bhNOjGgMnhwhGTQmOoZGD+K7BCaQDCuZl/Ve1ZxUSMRwVC4D/rkCPQ2MAIeYzrWyK7eEg==", + "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.2", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", + "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", + "dev": true, + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -2133,9 +2413,9 @@ } }, "node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -2224,6 +2504,59 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/docker-compose": { + "version": "0.23.19", + "resolved": "https://registry.npmjs.org/docker-compose/-/docker-compose-0.23.19.tgz", + "integrity": "sha512-v5vNLIdUqwj4my80wxFDkNH+4S85zsRuH29SO7dCWVWPCMt/ohZBsGN6g6KXWifT0pzQ7uOxqEKCYCDPJ8Vz4g==", + "dev": true, + "dependencies": { + "yaml": "^1.10.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/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/dom-serializer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", @@ -2315,6 +2648,15 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "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, + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/entities": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", @@ -2887,6 +3229,12 @@ "node": ">= 0.12" } }, + "node_modules/fs-constants": { + "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 + }, "node_modules/fs-extra": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", @@ -2951,6 +3299,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-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", @@ -3116,20 +3476,6 @@ "readable-stream": "^3.1.1" } }, - "node_modules/htmlparser2/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/http-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", @@ -3430,6 +3776,26 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", @@ -3594,6 +3960,12 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -4523,6 +4895,48 @@ "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/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -4587,6 +5001,12 @@ "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", "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.filter": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", @@ -4605,6 +5025,12 @@ "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=", "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.map": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", @@ -4641,6 +5067,12 @@ "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", "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/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -4786,12 +5218,37 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "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 + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/nan": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", + "dev": true, + "optional": true + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -5078,6 +5535,12 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -5091,12 +5554,34 @@ "node": ">= 6" } }, + "node_modules/properties-reader": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/properties-reader/-/properties-reader-2.2.0.tgz", + "integrity": "sha512-CgVcr8MwGoBKK24r9TwHfZkLLaNFHQ6y4wgT9w/XzdpacOOi5ciH4hcuLechSDAwXsfrGQtI2JTutY2djOx2Ow==", + "dev": true, + "dependencies": { + "mkdirp": "^1.0.4" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", "dev": true }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -5128,6 +5613,50 @@ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true }, + "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/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/regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", @@ -5439,12 +5968,56 @@ "deprecated": "Please use @jridgewell/sourcemap-codec instead", "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": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "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.14.0", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.14.0.tgz", + "integrity": "sha512-AqzD1UCqit8tbOKoj6ztDDi1ffJZ2rV2SwlgrVVrHPkV5vWqGJOVp5pmtj18PunkPJAuKQsnInyKV+/Nb2bUnA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "asn1": "^0.2.6", + "bcrypt-pbkdf": "^1.0.2" + }, + "engines": { + "node": ">=10.16.0" + }, + "optionalDependencies": { + "cpu-features": "~0.0.8", + "nan": "^2.17.0" + } + }, "node_modules/sshpk": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", @@ -5619,6 +6192,34 @@ "integrity": "sha1-KtNxaWKUmPylvIQkMJbTzeDsOjQ=", "dev": true }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", @@ -5649,6 +6250,26 @@ "node": ">=8" } }, + "node_modules/testcontainers": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-8.16.0.tgz", + "integrity": "sha512-4wVmnzj4mAVXSQ8kU4uyNiXPs5W8UHdwCRbUuyeOSSODcgmDGQ8Te/YOYuF12HnxyzABEm1nR2I0ZCsQw/GZ/Q==", + "dev": true, + "dependencies": { + "@balena/dockerignore": "^1.0.2", + "@types/archiver": "^5.3.1", + "@types/dockerode": "^3.3.8", + "archiver": "^5.3.1", + "byline": "^5.0.0", + "debug": "^4.3.4", + "docker-compose": "^0.23.17", + "dockerode": "^3.3.1", + "get-port": "^5.1.1", + "properties-reader": "^2.2.0", + "ssh-remote-port-forward": "^1.0.4", + "tar-fs": "^2.1.1" + } + }, "node_modules/throat": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", @@ -5860,8 +6481,7 @@ "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true + "dev": true }, "node_modules/type-check": { "version": "0.3.2", @@ -6202,6 +6822,15 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", @@ -6237,6 +6866,20 @@ "engines": { "node": ">=6" } + }, + "node_modules/zip-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", + "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", + "dev": true, + "dependencies": { + "archiver-utils": "^2.1.0", + "compress-commons": "^4.1.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } } }, "dependencies": { @@ -6656,6 +7299,12 @@ "to-fast-properties": "^2.0.0" } }, + "@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 + }, "@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", @@ -7087,6 +7736,15 @@ "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", "dev": true }, + "@types/archiver": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-5.3.2.tgz", + "integrity": "sha512-IctHreBuWE5dvBDz/0WeKtyVKVRs4h75IblxOACL92wU66v+HGAfEYAOyXkOFphvRJMhuXdI9huDXpX0FC6lCw==", + "dev": true, + "requires": { + "@types/readdir-glob": "*" + } + }, "@types/babel__core": { "version": "7.1.20", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz", @@ -7125,7 +7783,27 @@ "integrity": "sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==", "dev": true, "requires": { - "@babel/types": "^7.3.0" + "@babel/types": "^7.3.0" + } + }, + "@types/docker-modem": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/docker-modem/-/docker-modem-3.0.3.tgz", + "integrity": "sha512-i1A2Etnav7uHizZ87vUf4EqwJehY3JOcTfBS0pGBlO+HQ0jg2lUMCaJRg9VQM8ldZkpYdIfsenxcTOCpwxPXEg==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/ssh2": "*" + } + }, + "@types/dockerode": { + "version": "3.3.19", + "resolved": "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.3.19.tgz", + "integrity": "sha512-7CC5yIpQi+bHXwDK43b/deYXteP3Lem9gdocVVHJPSRJJLMfbiOchQV3rDmAPkMw+n3GIVj7m1six3JW+VcwwA==", + "dev": true, + "requires": { + "@types/docker-modem": "*", + "@types/node": "*" } }, "@types/estree": { @@ -7189,6 +7867,15 @@ "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", "dev": true }, + "@types/readdir-glob": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/readdir-glob/-/readdir-glob-1.1.1.tgz", + "integrity": "sha512-ImM6TmoF8bgOwvehGviEj3tRdRBbQujr1N+0ypaln/GWjaerOB26jb93vsRHmdMtvVQZQebOlqt2HROark87mQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -7198,6 +7885,24 @@ "@types/node": "*" } }, + "@types/ssh2": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.11.13.tgz", + "integrity": "sha512-08WbG68HvQ2YVi74n2iSUnYHYpUdFc/s2IsI0BHBdJwaqYJpWlVv9elL0tYShTv60yr0ObdxJR5NrCRiGJ/0CQ==", + "dev": true, + "requires": { + "@types/node": "^18.11.18" + } + }, + "@types/ssh2-streams": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/@types/ssh2-streams/-/ssh2-streams-0.1.9.tgz", + "integrity": "sha512-I2J9jKqfmvXLR5GomDiCoHrEJ58hAOmFrekfFqmCFd+A6gaEStvWnPykoWUwld1PNg4G5ag1LwdA+Lz1doRJqg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -7311,6 +8016,71 @@ "picomatch": "^2.0.4" } }, + "archiver": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz", + "integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==", + "dev": true, + "requires": { + "archiver-utils": "^2.1.0", + "async": "^3.2.3", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.0.0", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + } + }, + "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, + "requires": { + "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" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -7327,11 +8097,10 @@ } }, "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "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, - "optional": true, "requires": { "safer-buffer": "~2.1.0" } @@ -7343,6 +8112,12 @@ "dev": true, "optional": true }, + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -7614,16 +8389,32 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true + }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "dev": true, - "optional": true, "requires": { "tweetnacl": "^0.14.3" } }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, "boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -7695,18 +8486,47 @@ "node-int64": "^0.4.0" } }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true + }, "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "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 + }, "builtin-modules": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", "dev": true }, + "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 + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -7773,6 +8593,12 @@ } } }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, "ci-info": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", @@ -7844,6 +8670,18 @@ "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true }, + "compress-commons": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", + "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", + "dev": true, + "requires": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -7868,6 +8706,33 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, + "cpu-features": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.8.tgz", + "integrity": "sha512-BbHBvtYhUhksqTjr6bhNOjGgMnhwhGTQmOoZGD+K7BCaQDCuZl/Ve1ZxUSMRwVC4D/rkCPQ2MAIeYzrWyK7eEg==", + "dev": true, + "optional": true, + "requires": { + "buildcheck": "~0.0.6", + "nan": "^2.17.0" + } + }, + "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 + }, + "crc32-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", + "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", + "dev": true, + "requires": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + } + }, "create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -7948,9 +8813,9 @@ } }, "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -8013,6 +8878,52 @@ "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", "dev": true }, + "docker-compose": { + "version": "0.23.19", + "resolved": "https://registry.npmjs.org/docker-compose/-/docker-compose-0.23.19.tgz", + "integrity": "sha512-v5vNLIdUqwj4my80wxFDkNH+4S85zsRuH29SO7dCWVWPCMt/ohZBsGN6g6KXWifT0pzQ7uOxqEKCYCDPJ8Vz4g==", + "dev": true, + "requires": { + "yaml": "^1.10.2" + } + }, + "docker-modem": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-3.0.8.tgz", + "integrity": "sha512-f0ReSURdM3pcKPNS30mxOHSbaFLcknGmQjwSfmbcdOw1XWKXVhukM3NJHhr7NpY9BIyyWQb0EBo3KQvvuU5egQ==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "readable-stream": "^3.5.0", + "split-ca": "^1.0.1", + "ssh2": "^1.11.0" + } + }, + "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, + "requires": { + "@balena/dockerignore": "^1.0.2", + "docker-modem": "^3.0.0", + "tar-fs": "~2.0.1" + }, + "dependencies": { + "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, + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.0.0" + } + } + } + }, "dom-serializer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", @@ -8094,6 +9005,15 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "end-of-stream": { + "version": "1.4.4", + "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, + "requires": { + "once": "^1.4.0" + } + }, "entities": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", @@ -8555,6 +9475,12 @@ "mime-types": "^2.1.12" } }, + "fs-constants": { + "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 + }, "fs-extra": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", @@ -8603,6 +9529,12 @@ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true }, + "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 + }, "get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", @@ -8728,19 +9660,6 @@ "entities": "^1.1.1", "inherits": "^2.0.1", "readable-stream": "^3.1.1" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } } }, "http-proxy-agent": { @@ -9002,6 +9921,12 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, "import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", @@ -9124,6 +10049,12 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -9850,6 +10781,47 @@ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true }, + "lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -9905,6 +10877,12 @@ "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", "dev": true }, + "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 + }, "lodash.filter": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", @@ -9923,6 +10901,12 @@ "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=", "dev": true }, + "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 + }, "lodash.map": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", @@ -9959,6 +10943,12 @@ "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", "dev": true }, + "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 + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -10068,12 +11058,31 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "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 + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "nan": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", + "dev": true, + "optional": true + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -10293,6 +11302,12 @@ } } }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, "prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -10303,12 +11318,31 @@ "sisteransi": "^1.0.5" } }, + "properties-reader": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/properties-reader/-/properties-reader-2.2.0.tgz", + "integrity": "sha512-CgVcr8MwGoBKK24r9TwHfZkLLaNFHQ6y4wgT9w/XzdpacOOi5ciH4hcuLechSDAwXsfrGQtI2JTutY2djOx2Ow==", + "dev": true, + "requires": { + "mkdirp": "^1.0.4" + } + }, "psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", "dev": true }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -10334,6 +11368,46 @@ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true }, + "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, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "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, + "requires": { + "minimatch": "^5.1.0" + }, + "dependencies": { + "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, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", @@ -10566,12 +11640,52 @@ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", "dev": true }, + "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 + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "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, + "requires": { + "@types/ssh2": "^0.5.48", + "ssh2": "^1.4.0" + }, + "dependencies": { + "@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, + "requires": { + "@types/node": "*", + "@types/ssh2-streams": "*" + } + } + } + }, + "ssh2": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.14.0.tgz", + "integrity": "sha512-AqzD1UCqit8tbOKoj6ztDDi1ffJZ2rV2SwlgrVVrHPkV5vWqGJOVp5pmtj18PunkPJAuKQsnInyKV+/Nb2bUnA==", + "dev": true, + "requires": { + "asn1": "^0.2.6", + "bcrypt-pbkdf": "^1.0.2", + "cpu-features": "~0.0.8", + "nan": "^2.17.0" + } + }, "sshpk": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", @@ -10701,6 +11815,31 @@ "integrity": "sha1-KtNxaWKUmPylvIQkMJbTzeDsOjQ=", "dev": true }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } + }, "terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", @@ -10722,6 +11861,26 @@ "minimatch": "^3.0.4" } }, + "testcontainers": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-8.16.0.tgz", + "integrity": "sha512-4wVmnzj4mAVXSQ8kU4uyNiXPs5W8UHdwCRbUuyeOSSODcgmDGQ8Te/YOYuF12HnxyzABEm1nR2I0ZCsQw/GZ/Q==", + "dev": true, + "requires": { + "@balena/dockerignore": "^1.0.2", + "@types/archiver": "^5.3.1", + "@types/dockerode": "^3.3.8", + "archiver": "^5.3.1", + "byline": "^5.0.0", + "debug": "^4.3.4", + "docker-compose": "^0.23.17", + "dockerode": "^3.3.1", + "get-port": "^5.1.1", + "properties-reader": "^2.2.0", + "ssh-remote-port-forward": "^1.0.4", + "tar-fs": "^2.1.1" + } + }, "throat": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", @@ -10860,8 +12019,7 @@ "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true + "dev": true }, "type-check": { "version": "0.3.2", @@ -11127,6 +12285,12 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + }, "yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", @@ -11153,6 +12317,17 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true + }, + "zip-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", + "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", + "dev": true, + "requires": { + "archiver-utils": "^2.1.0", + "compress-commons": "^4.1.0", + "readable-stream": "^3.6.0" + } } } } diff --git a/packages/neo4j-driver-lite/package.json b/packages/neo4j-driver-lite/package.json index 94182c96a..02b9bc594 100644 --- a/packages/neo4j-driver-lite/package.json +++ b/packages/neo4j-driver-lite/package.json @@ -52,6 +52,7 @@ "jest": "^27.5.1", "rollup": "^2.77.4-1", "rollup-plugin-polyfill-node": "^0.11.0", + "testcontainers": "^8.16.0", "ts-jest": "^27.1.4", "ts-node": "^10.9.1", "typescript": "^4.9.5", diff --git a/packages/neo4j-driver-lite/test/integration/browser.environment.js b/packages/neo4j-driver-lite/test/integration/browser.environment.js index 8612ba539..1896e2155 100644 --- a/packages/neo4j-driver-lite/test/integration/browser.environment.js +++ b/packages/neo4j-driver-lite/test/integration/browser.environment.js @@ -18,6 +18,7 @@ */ const NodeEnvironment = require('jest-environment-node') const WebSocket = require('isomorphic-ws') +const Config = require('./config') class BrowserEnvironment extends NodeEnvironment { async setup () { @@ -27,9 +28,14 @@ class BrowserEnvironment extends NodeEnvironment { this.global.window.navigator = { userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36' } + await Config.default.startNeo4j() + this.global.process.env = process.env + this.global.process.env.TEST_CONTAINERS_DISABLED = 'TRUE' } async teardown () { + await Config.default.stopNeo4j() + this.global.process.env.TEST_CONTAINERS_DISABLED = 'FALSE' await super.teardown() } } diff --git a/packages/neo4j-driver-lite/test/integration/browser/testcontainer.js b/packages/neo4j-driver-lite/test/integration/browser/testcontainer.js new file mode 100644 index 000000000..bb6df6ea1 --- /dev/null +++ b/packages/neo4j-driver-lite/test/integration/browser/testcontainer.js @@ -0,0 +1,13 @@ +export class GenericContainer { + +} + +export class DockerImageName { + +} + +export class Wait { + static forLogMessage () { + + } +} diff --git a/packages/neo4j-driver-lite/test/integration/config.ts b/packages/neo4j-driver-lite/test/integration/config.ts index ea7ca6f15..3f8990767 100644 --- a/packages/neo4j-driver-lite/test/integration/config.ts +++ b/packages/neo4j-driver-lite/test/integration/config.ts @@ -16,6 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import Neo4jContainer from './neo4j-container' const env = process.env @@ -23,8 +24,42 @@ const username = env.TEST_NEO4J_USER ?? 'neo4j' const password = env.TEST_NEO4J_PASS ?? 'password' const hostname = env.TEST_NEO4J_HOST ?? 'localhost' const scheme = env.TEST_NEO4J_SCHEME ?? 'bolt' +const version = env.TEST_NEO4J_VERSION ?? '5.8' +const httpPort = env.TEST_NEO4J_HTTP_PORT ?? 7474 +const boltPort = env.TEST_NEO4J_BOLT_PORT ?? 7687 +const edition = env.TEST_NEO4J_EDITION ?? 'enterprise' +const testcontainersDisabled = env.TEST_CONTAINERS_DISABLED !== undefined + ? env.TEST_CONTAINERS_DISABLED.toUpperCase() === 'TRUE' + : false + const cluster = env.TEST_NEO4J_IS_CLUSTER === '1' -const testNonClusterSafe = cluster ? test.skip.bind(test) : test +const neo4jContainer = new Neo4jContainer(username, password, version, edition, testcontainersDisabled, false) -export { username, password, hostname, scheme, cluster, testNonClusterSafe } +export default { + username, + password, + hostname, + scheme, + cluster, + get testNonClusterSafe () { + return cluster ? test.skip.bind(test) : test + }, + get httpPort () { + return neo4jContainer.getHttpPort(httpPort) + }, + get boltPort () { + return neo4jContainer.getBoltPort(boltPort) + }, + async startNeo4j () { + await neo4jContainer.start() + // @ts-expect-error + if (global.window == null) { + process.env.TEST_NEO4J_BOLT_PORT = neo4jContainer.getBoltPort(boltPort).toString() + process.env.TEST_NEO4J_HTTP_PORT = neo4jContainer.getHttpPort(httpPort).toString() + } + }, + async stopNeo4j () { + await neo4jContainer.stop() + } +} diff --git a/packages/neo4j-driver-lite/test/integration/driver.test.ts b/packages/neo4j-driver-lite/test/integration/driver.test.ts index 1bd4b167c..4f6d6750b 100644 --- a/packages/neo4j-driver-lite/test/integration/driver.test.ts +++ b/packages/neo4j-driver-lite/test/integration/driver.test.ts @@ -17,29 +17,31 @@ * limitations under the License. */ import neo4j, { Driver, QueryResult, int } from '../../' -import { - hostname, - password, - scheme, - username, - testNonClusterSafe -} from './config' +import Config from './config' describe('neo4j-driver-lite', () => { let driver: Driver + beforeAll(async () => { + await Config.startNeo4j() + }, 20000) + + afterAll(async () => { + await Config.stopNeo4j() + }, 20000) + beforeEach(() => { driver = neo4j.driver( - `${scheme}://${hostname}`, - neo4j.auth.basic(username, password) + `${Config.scheme}://${Config.hostname}:${Config.boltPort}`, + neo4j.auth.basic(Config.username, Config.password) ) }) afterEach(async () => { - await driver.close() + await driver?.close() }) - testNonClusterSafe('should run a query over a session', async () => { + Config.testNonClusterSafe('should run a query over a session', async () => { const result: QueryResult = await driver.session().run('RETURN 2') expect(result.records.length).toEqual(1) expect(result.records[0].length).toEqual(1) @@ -47,10 +49,10 @@ describe('neo4j-driver-lite', () => { }) test('hasReachableServer success', async () => { - await expect(neo4j.hasReachableServer(`${scheme}://${hostname}`)).resolves.toBe(true) + await expect(neo4j.hasReachableServer(`${Config.scheme}://${Config.hostname}:${Config.boltPort}`)).resolves.toBe(true) }) test('hasReachableServer failure', async () => { - await expect(neo4j.hasReachableServer(`${scheme}://${hostname}:9999`)).rejects.toBeInstanceOf(Error) + await expect(neo4j.hasReachableServer(`${Config.scheme}://${Config.hostname}:12`)).rejects.toBeInstanceOf(Error) }) }) diff --git a/packages/neo4j-driver-lite/test/integration/node/testcontainer.js b/packages/neo4j-driver-lite/test/integration/node/testcontainer.js new file mode 100644 index 000000000..941297e48 --- /dev/null +++ b/packages/neo4j-driver-lite/test/integration/node/testcontainer.js @@ -0,0 +1,8 @@ +const { GenericContainer, Wait } = require('testcontainers') +const { DockerImageName } = require('testcontainers/dist/docker-image-name') + +module.exports = { + GenericContainer, + Wait, + DockerImageName +} From 850bac7f960b0473bb3e0dec49fcd06998f97b95 Mon Sep 17 00:00:00 2001 From: Antonio Barcelos Date: Tue, 8 Aug 2023 10:24:31 +0200 Subject: [PATCH 11/16] Remove runTests.sh and update TESTING.md --- TESTING.md | 31 +++++-------------------------- runTests.sh | 23 ----------------------- 2 files changed, 5 insertions(+), 49 deletions(-) delete mode 100755 runTests.sh diff --git a/TESTING.md b/TESTING.md index 5be93b654..8a8e25990 100644 --- a/TESTING.md +++ b/TESTING.md @@ -66,43 +66,22 @@ More details about how to use Testkit could be found on [its repository](https:/ ## Testing (Legacy) -Tests **require** latest [Boltkit](https://github.com/neo4j-contrib/boltkit) and [Firefox](https://www.mozilla.org/firefox/) to be installed in the system. - -Boltkit is needed to start, stop and configure local test database. Boltkit can be installed with the following command: - -``` -pip3 install --upgrade boltkit -``` +Tests **require** [Docker](https://www.docker.com/) and [Firefox](https://www.mozilla.org/firefox/) to be installed in the system. To run tests against "default" Neo4j version: ``` -./runTests.sh +npm test ``` To run tests against specified Neo4j version: ``` -./runTests.sh '-e 4.2.0' +export TEST_NEO4J_VERSION=5.9 npm test ``` -Simple `npm test` can also be used if you already have a running version of a compatible Neo4j server. - -For development, you can have the build tool rerun the tests each time you change -the source code: +If you already have a running version of a compatible Neo4j server, you can run: ``` -gulp watch-n-test +export TEST_CONTAINERS_DISABLED=true npm test ``` - -If the `gulp` command line tool is not available, you might need to install this globally: - -``` -npm install -g gulp-cli -``` - -### Testing on windows - -To run the same test suite, run `.\runTest.ps1` instead in powershell with admin right. -The admin right is required to start/stop Neo4j properly as a system service. -While there is no need to grab admin right if you are running tests against an existing Neo4j server using `npm test`. diff --git a/runTests.sh b/runTests.sh deleted file mode 100755 index e493e4806..000000000 --- a/runTests.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -function finish { - npm run stop-neo4j -} -trap finish EXIT - -npm ci -npm run build -- --no-private - -# root users could not run the lifecycle scripts -# so it need will need to run the prepare script -if [ "$EUID" -eq 0 ] - then echo "Running prepare by manually" - npm run lerna -- run prepare --no-private -fi - - -if [[ ! -z "$1" ]]; then - export NEOCTRL_ARGS="$1" -fi - -npm run start-neo4j && npm test -- --no-private From 7f146abbbca9532e42de04698ffeb7a5ec78f630 Mon Sep 17 00:00:00 2001 From: Antonio Barcelos Date: Tue, 8 Aug 2023 10:47:06 +0200 Subject: [PATCH 12/16] Adjust testing.md --- TESTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TESTING.md b/TESTING.md index 8a8e25990..e3e01516d 100644 --- a/TESTING.md +++ b/TESTING.md @@ -77,11 +77,11 @@ npm test To run tests against specified Neo4j version: ``` -export TEST_NEO4J_VERSION=5.9 npm test +TEST_NEO4J_VERSION=5.9 npm test ``` If you already have a running version of a compatible Neo4j server, you can run: ``` -export TEST_CONTAINERS_DISABLED=true npm test +TEST_CONTAINERS_DISABLED=true npm test ``` From a40ca727ea5fdf95386506843dd76349ed1f3cdd Mon Sep 17 00:00:00 2001 From: Antonio Barcelos Date: Tue, 8 Aug 2023 12:34:55 +0200 Subject: [PATCH 13/16] Fix package-lock.json --- packages/neo4j-driver-lite/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/neo4j-driver-lite/package-lock.json b/packages/neo4j-driver-lite/package-lock.json index fdda4eaf9..fa6427adf 100644 --- a/packages/neo4j-driver-lite/package-lock.json +++ b/packages/neo4j-driver-lite/package-lock.json @@ -1245,9 +1245,9 @@ } }, "node_modules/@types/node": { - "version": "14.14.41", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.41.tgz", - "integrity": "sha512-dueRKfaJL4RTtSa7bWeTK1M+VH+Gns73oCgzvYfHZywRCoPSd8EkXBL0mZ9unPTveBn+D9phZBaxuzpwjWkW0g==", + "version": "18.17.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.3.tgz", + "integrity": "sha512-2x8HWtFk0S99zqVQABU9wTpr8wPoaDHZUcAkoTKH+nL7kPv3WUI9cRi/Kk5Mz4xdqXSqTkKP7IWNoQQYCnDsTA==", "dev": true }, "node_modules/@types/prettier": { @@ -7856,9 +7856,9 @@ } }, "@types/node": { - "version": "14.14.41", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.41.tgz", - "integrity": "sha512-dueRKfaJL4RTtSa7bWeTK1M+VH+Gns73oCgzvYfHZywRCoPSd8EkXBL0mZ9unPTveBn+D9phZBaxuzpwjWkW0g==", + "version": "18.17.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.3.tgz", + "integrity": "sha512-2x8HWtFk0S99zqVQABU9wTpr8wPoaDHZUcAkoTKH+nL7kPv3WUI9cRi/Kk5Mz4xdqXSqTkKP7IWNoQQYCnDsTA==", "dev": true }, "@types/prettier": { From a0328165b399233e2ba1ca8ff4004fb96000001c Mon Sep 17 00:00:00 2001 From: Antonio Barcelos Date: Tue, 8 Aug 2023 13:18:52 +0200 Subject: [PATCH 14/16] Return port as string since it will be used just to interpolate string --- packages/neo4j-driver-lite/test/integration/config.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/neo4j-driver-lite/test/integration/config.ts b/packages/neo4j-driver-lite/test/integration/config.ts index 3f8990767..6c5aac42a 100644 --- a/packages/neo4j-driver-lite/test/integration/config.ts +++ b/packages/neo4j-driver-lite/test/integration/config.ts @@ -45,11 +45,11 @@ export default { get testNonClusterSafe () { return cluster ? test.skip.bind(test) : test }, - get httpPort () { - return neo4jContainer.getHttpPort(httpPort) + get httpPort (): string { + return neo4jContainer.getHttpPort(httpPort).toString() }, - get boltPort () { - return neo4jContainer.getBoltPort(boltPort) + get boltPort (): string { + return neo4jContainer.getBoltPort(boltPort).toString() }, async startNeo4j () { await neo4jContainer.start() From e45721c8b07fa2cfb233e0911a75315a7bd140d1 Mon Sep 17 00:00:00 2001 From: Antonio Barcelos Date: Tue, 8 Aug 2023 14:46:01 +0200 Subject: [PATCH 15/16] Missing file :D --- .../test/integration/neo4j-container.ts | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 packages/neo4j-driver-lite/test/integration/neo4j-container.ts diff --git a/packages/neo4j-driver-lite/test/integration/neo4j-container.ts b/packages/neo4j-driver-lite/test/integration/neo4j-container.ts new file mode 100644 index 000000000..f3dbd2df0 --- /dev/null +++ b/packages/neo4j-driver-lite/test/integration/neo4j-container.ts @@ -0,0 +1,98 @@ +/** + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type NumberOrString = number | string +export default class Neo4jContainer { + private usages: number = 0 + private container: any | undefined = undefined + + constructor ( + private readonly user: string, + private readonly password: string, + private readonly version: string, + private readonly edition: string | undefined, + private readonly disabled: boolean, + private readonly containerLogs: boolean = false + + ) { + } + + async start (): Promise { + if (this.disabled) { + return + } + this.usages++ + console.log('Starting container') + if (this.container != null) { + console.log('Container already started') + return + } + + const tag = this.edition != null ? `${this.version}-${this.edition}` : this.version + + // Browser does not support testcontainers + // @ts-expect-error + const path = global.window != null ? './browser/testcontainer' : './node/testcontainer' + // eslint-disable-next-line @typescript-eslint/no-var-requires + const { GenericContainer, DockerImageName, Wait } = require(path) + + let container = new GenericContainer(new DockerImageName(undefined, 'neo4j', tag).toString()) + .withEnv('NEO4J_AUTH', `${this.user}/${this.password}`) + + if (this.edition === 'enterprise') { + container = container.withEnv('NEO4J_ACCEPT_LICENSE_AGREEMENT', 'yes') + } + + this.container = await container.withExposedPorts(7687, 7474) + .withWaitStrategy(Wait.forLogMessage(/Started/)) + .start() + + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + console.log('Container started at ' + `${this.container.getHost()}:${this.container.getMappedPort(7687)}`) + + if (this.containerLogs) { + const stream = await this.container.logs() + stream + .on('data', (line: string) => console.log(line)) + .on('err', (line: string) => console.error(line)) + .on('end', () => console.log('Stream closed')) + } + } + + getBoltPort (defaultPort: NumberOrString = 7687): NumberOrString { + return this.getMappedPort(7687, defaultPort) + } + + getHttpPort (defaultPort: NumberOrString = 7474): NumberOrString { + return this.getMappedPort(7474, defaultPort) + } + + getMappedPort (port: number, defaultPort: NumberOrString): NumberOrString { + return this.container != null ? this.container.getMappedPort(port) : defaultPort + } + + async stop (): Promise { + this.usages-- + if (this.usages <= 0) { + this.usages = 0 + await this.container?.stop() + this.container = undefined + } + } +} From c7de61fbac8f64b3eb93643d2cc7e3d35038c226 Mon Sep 17 00:00:00 2001 From: Antonio Barcelos Date: Wed, 9 Aug 2023 14:28:25 +0200 Subject: [PATCH 16/16] Select the lastest 5 as default neo4j version --- packages/neo4j-driver-lite/test/integration/config.ts | 2 +- packages/neo4j-driver/test/internal/shared-neo4j.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/neo4j-driver-lite/test/integration/config.ts b/packages/neo4j-driver-lite/test/integration/config.ts index 6c5aac42a..88b98ef1b 100644 --- a/packages/neo4j-driver-lite/test/integration/config.ts +++ b/packages/neo4j-driver-lite/test/integration/config.ts @@ -24,7 +24,7 @@ const username = env.TEST_NEO4J_USER ?? 'neo4j' const password = env.TEST_NEO4J_PASS ?? 'password' const hostname = env.TEST_NEO4J_HOST ?? 'localhost' const scheme = env.TEST_NEO4J_SCHEME ?? 'bolt' -const version = env.TEST_NEO4J_VERSION ?? '5.8' +const version = env.TEST_NEO4J_VERSION ?? '5' const httpPort = env.TEST_NEO4J_HTTP_PORT ?? 7474 const boltPort = env.TEST_NEO4J_BOLT_PORT ?? 7687 const edition = env.TEST_NEO4J_EDITION ?? 'enterprise' diff --git a/packages/neo4j-driver/test/internal/shared-neo4j.js b/packages/neo4j-driver/test/internal/shared-neo4j.js index e092d65cf..899f95c3b 100644 --- a/packages/neo4j-driver/test/internal/shared-neo4j.js +++ b/packages/neo4j-driver/test/internal/shared-neo4j.js @@ -25,7 +25,7 @@ const username = env.TEST_NEO4J_USER || 'neo4j' const password = env.TEST_NEO4J_PASS || 'password' const hostname = env.TEST_NEO4J_HOST || 'localhost' const scheme = env.TEST_NEO4J_SCHEME || 'bolt' -const version = env.TEST_NEO4J_VERSION || '5.8' +const version = env.TEST_NEO4J_VERSION || '5' const httpPort = env.TEST_NEO4J_HTTP_PORT || 7474 const boltPort = env.TEST_NEO4J_BOLT_PORT || 7687