From 4f28f0299958afab1b0d86804e2322e8b99cb9f6 Mon Sep 17 00:00:00 2001 From: Jan Melcher Date: Wed, 8 Jan 2025 19:54:50 +0100 Subject: [PATCH] feat: update to arangojs 10 Removes the "arangojs instrumentation" code, which was a copy of the core request processing classes of arangojs. The update to arangojs 10 would have required major changes to these files, and they were a code quality problem anyway. Instead of our custom patches, we now rely on beforeRequest and afterResponse. They can be specified once per Database, which is not sufficient for our use case, so we currently call request() directly instead of the proper executeTransaction(). Hopefully, arangojs will add a way to specify these hooks in executeTransaction() as well. See https://github.com/arangodb/arangojs/issues/817 for the feature request. BREAKING CHANGE: arangojs 8 is no longer supported. Update to arangojs 10. BREAKING CHANGE: ArangoJSConfig is no longer exported. Import ConfigOptions from arangojs/configuration directly if needed. --- package-lock.json | 480 +++--------------- package.json | 2 +- .../arangodb/arangodb-adapter.spec.ts | 2 +- spec/database/arangodb/retry.spec.ts | 4 +- spec/regression/initialization.ts | 2 +- src/database/arangodb/arangodb-adapter.ts | 157 +++--- .../arangojs-instrumentation/config.ts | 19 - .../custom-connection.ts | 136 ----- .../custom-database.ts | 11 - .../custom-request.ts | 234 --------- src/database/arangodb/config.ts | 9 +- src/database/arangodb/index.ts | 3 +- .../arangodb/schema-migration/analyzer.ts | 2 +- .../schema-migration/arango-search-helpers.ts | 4 +- .../arangodb/schema-migration/migrations.ts | 4 +- .../arangodb/schema-migration/performer.ts | 2 +- src/database/arangodb/version-helper.ts | 7 +- src/execution/runtime-errors.ts | 4 +- tsconfig.json | 7 +- 19 files changed, 186 insertions(+), 903 deletions(-) delete mode 100644 src/database/arangodb/arangojs-instrumentation/config.ts delete mode 100644 src/database/arangodb/arangojs-instrumentation/custom-connection.ts delete mode 100644 src/database/arangodb/arangojs-instrumentation/custom-database.ts delete mode 100644 src/database/arangodb/arangojs-instrumentation/custom-request.ts diff --git a/package-lock.json b/package-lock.json index 0929777a..cd5bd213 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@js-joda/core": "^5.2.0", "ajv": "^8.11.0", "ansi-styles": "^5.2.0", - "arangojs": "^8.1.0", + "arangojs": "^10.0.0", "deep-equal": "^2.0.5", "graphql-tag": "^2.12.4", "graphql-type-json": "^0.3.2", @@ -979,11 +979,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" - }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -1126,6 +1121,7 @@ "version": "18.19.42", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.42.tgz", "integrity": "sha512-d2ZFc/3lnK2YCYhos8iaNIYu9Vfhr92nHiyJHRltXWjXUBjEE+A4I58Tdbnw4VhggSW+2j5y5gTrLs4biNnubg==", + "dev": true, "dependencies": { "undici-types": "~5.26.4" } @@ -1480,20 +1476,40 @@ } }, "node_modules/arangojs": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/arangojs/-/arangojs-8.1.0.tgz", - "integrity": "sha512-8wrVTq6vJYAMJbJj9s845+vbiKaqzKBOe7Y8K1Ci/oE7qLM1SSfSZanHShItiuTIWxBympRKaNQ3/Xr3hhZwNg==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/arangojs/-/arangojs-10.0.0.tgz", + "integrity": "sha512-CQE9ayDp8f12R+uDIGW9Xrh2bnCA71/lQ2htMItrTJaO0cNNIrfwjRwFvJuqG1gC1JqqBZAEpVyg1vNTXXAVaw==", + "license": "Apache-2.0", "dependencies": { - "@types/node": ">=14", - "multi-part": "^4.0.0", - "path-browserify": "^1.0.1", - "x3-linkedlist": "1.2.0", - "xhr": "^2.4.1" + "@types/node": "^20.11.26" }, "engines": { - "node": ">=14" + "node": ">=20" + }, + "peerDependencies": { + "undici": ">=5.21.0" + }, + "peerDependenciesMeta": { + "undici": { + "optional": true + } + } + }, + "node_modules/arangojs/node_modules/@types/node": { + "version": "20.17.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.12.tgz", + "integrity": "sha512-vo/wmBgMIiEA23A/knMfn/cf37VnuF52nZh5ZoW0GWt4e4sxNquibrMRJ7UQsA06+MBx9r/H1jsI9grYjQCQlw==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" } }, + "node_modules/arangojs/node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, "node_modules/archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", @@ -2376,11 +2392,6 @@ "node": ">=8" } }, - "node_modules/dom-walk": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", - "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" - }, "node_modules/easy-table": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.2.0.tgz", @@ -2779,22 +2790,6 @@ "reusify": "^1.0.4" } }, - "node_modules/file-type": { - "version": "16.5.4", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", - "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", - "dependencies": { - "readable-web-to-node-stream": "^3.0.0", - "strtok3": "^6.2.4", - "token-types": "^4.1.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/file-type?sponsor=1" - } - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -3121,15 +3116,6 @@ "node": ">= 6" } }, - "node_modules/global": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", - "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", - "dependencies": { - "min-document": "^2.19.0", - "process": "^0.11.10" - } - }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -3383,25 +3369,6 @@ "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==", - "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/ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", @@ -3445,7 +3412,8 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "node_modules/internal-slot": { "version": "1.0.3", @@ -3585,11 +3553,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", - "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" - }, "node_modules/is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -4904,26 +4867,16 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, "engines": { "node": ">= 0.6" } }, - "node_modules/mime-kind": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mime-kind/-/mime-kind-4.0.0.tgz", - "integrity": "sha512-qQvglvSpS5mABi30beNFd+uHKtKkxD3dxAmhi2e589XKx+WfVqhg5i5P5LBcVgwwv3BiDpNMBWrHqU+JexW4aA==", - "dependencies": { - "file-type": "^16.5.4", - "mime-types": "^2.1.24" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -4943,14 +4896,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", - "dependencies": { - "dom-walk": "^0.1.0" - } - }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -5313,26 +5258,6 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, - "node_modules/multi-part": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/multi-part/-/multi-part-4.0.0.tgz", - "integrity": "sha512-YT/CS0PAe62kT8EoQXcQj8yIcSu18HhYv0s6ShdAFsoFly3oV5QaxODnkj0u7zH0/RFyH47cdcMVpcGXliEFVA==", - "dependencies": { - "mime-kind": "^4.0.0", - "multi-part-lite": "^1.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/multi-part-lite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/multi-part-lite/-/multi-part-lite-1.0.0.tgz", - "integrity": "sha512-KxIRbBZZ45hoKX1ROD/19wJr0ql1bef1rE8Y1PCwD3PuNXV42pp7Wo8lEHYuAajoT4vfAFcd3rPjlkyEEyt1nw==", - "engines": { - "node": ">=8.3.0" - } - }, "node_modules/multikey-map": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/multikey-map/-/multikey-map-0.2.1.tgz", @@ -5718,11 +5643,6 @@ "node": ">=8" } }, - "node_modules/parse-headers": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.4.tgz", - "integrity": "sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw==" - }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -5762,11 +5682,6 @@ "node": ">= 0.8" } }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -5815,18 +5730,6 @@ "node": "*" } }, - "node_modules/peek-readable": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", - "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==", - "engines": { - "node": ">=8" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -5907,14 +5810,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/process-on-spawn": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", @@ -6166,34 +6061,6 @@ "node": ">=10" } }, - "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==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readable-web-to-node-stream": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", - "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", - "dependencies": { - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -6409,6 +6276,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, "funding": [ { "type": "github", @@ -6761,14 +6629,6 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/string-argv": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", @@ -6880,22 +6740,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strtok3": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", - "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", - "dependencies": { - "@tokenizer/token": "^0.3.0", - "peek-readable": "^4.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/summary": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/summary/-/summary-2.1.0.tgz", @@ -6970,22 +6814,6 @@ "node": ">=0.6" } }, - "node_modules/token-types": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", - "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", - "dependencies": { - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -7155,7 +6983,8 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true }, "node_modules/universalify": { "version": "2.0.0", @@ -7209,11 +7038,6 @@ "punycode": "^2.1.0" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -7421,25 +7245,6 @@ "typedarray-to-buffer": "^3.1.5" } }, - "node_modules/x3-linkedlist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/x3-linkedlist/-/x3-linkedlist-1.2.0.tgz", - "integrity": "sha512-mH/YwxpYSKNa8bDNF1yOuZCMuV+K80LtDN8vcLDUAwNazCxptDNsYt+zA/EJeYiGbdtKposhKLZjErGVOR8mag==", - "engines": { - "node": ">=10" - } - }, - "node_modules/xhr": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", - "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", - "dependencies": { - "global": "~4.4.0", - "is-function": "^1.0.1", - "parse-headers": "^2.0.0", - "xtend": "^4.0.0" - } - }, "node_modules/xss": { "version": "1.0.14", "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.14.tgz", @@ -7456,14 +7261,6 @@ "node": ">= 0.10.0" } }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - }, "node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", @@ -8337,11 +8134,6 @@ } } }, - "@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" - }, "@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -8484,6 +8276,7 @@ "version": "18.19.42", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.42.tgz", "integrity": "sha512-d2ZFc/3lnK2YCYhos8iaNIYu9Vfhr92nHiyJHRltXWjXUBjEE+A4I58Tdbnw4VhggSW+2j5y5gTrLs4biNnubg==", + "dev": true, "requires": { "undici-types": "~5.26.4" } @@ -8746,15 +8539,26 @@ } }, "arangojs": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/arangojs/-/arangojs-8.1.0.tgz", - "integrity": "sha512-8wrVTq6vJYAMJbJj9s845+vbiKaqzKBOe7Y8K1Ci/oE7qLM1SSfSZanHShItiuTIWxBympRKaNQ3/Xr3hhZwNg==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/arangojs/-/arangojs-10.0.0.tgz", + "integrity": "sha512-CQE9ayDp8f12R+uDIGW9Xrh2bnCA71/lQ2htMItrTJaO0cNNIrfwjRwFvJuqG1gC1JqqBZAEpVyg1vNTXXAVaw==", "requires": { - "@types/node": ">=14", - "multi-part": "^4.0.0", - "path-browserify": "^1.0.1", - "x3-linkedlist": "1.2.0", - "xhr": "^2.4.1" + "@types/node": "^20.11.26" + }, + "dependencies": { + "@types/node": { + "version": "20.17.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.12.tgz", + "integrity": "sha512-vo/wmBgMIiEA23A/knMfn/cf37VnuF52nZh5ZoW0GWt4e4sxNquibrMRJ7UQsA06+MBx9r/H1jsI9grYjQCQlw==", + "requires": { + "undici-types": "~6.19.2" + } + }, + "undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + } } }, "archy": { @@ -9415,11 +9219,6 @@ } } }, - "dom-walk": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", - "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" - }, "easy-table": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.2.0.tgz", @@ -9726,16 +9525,6 @@ "reusify": "^1.0.4" } }, - "file-type": { - "version": "16.5.4", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", - "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", - "requires": { - "readable-web-to-node-stream": "^3.0.0", - "strtok3": "^6.2.4", - "token-types": "^4.1.1" - } - }, "fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -9954,15 +9743,6 @@ "is-glob": "^4.0.1" } }, - "global": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", - "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", - "requires": { - "min-document": "^2.19.0", - "process": "^0.11.10" - } - }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -10132,11 +9912,6 @@ "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==" - }, "ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", @@ -10168,7 +9943,8 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "internal-slot": { "version": "1.0.3", @@ -10257,11 +10033,6 @@ "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", "dev": true }, - "is-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", - "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" - }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -11178,21 +10949,14 @@ "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-kind": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mime-kind/-/mime-kind-4.0.0.tgz", - "integrity": "sha512-qQvglvSpS5mABi30beNFd+uHKtKkxD3dxAmhi2e589XKx+WfVqhg5i5P5LBcVgwwv3BiDpNMBWrHqU+JexW4aA==", - "requires": { - "file-type": "^16.5.4", - "mime-types": "^2.1.24" - } + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true }, "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "requires": { "mime-db": "1.52.0" } @@ -11203,14 +10967,6 @@ "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "dev": true }, - "min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", - "requires": { - "dom-walk": "^0.1.0" - } - }, "min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -11477,20 +11233,6 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, - "multi-part": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/multi-part/-/multi-part-4.0.0.tgz", - "integrity": "sha512-YT/CS0PAe62kT8EoQXcQj8yIcSu18HhYv0s6ShdAFsoFly3oV5QaxODnkj0u7zH0/RFyH47cdcMVpcGXliEFVA==", - "requires": { - "mime-kind": "^4.0.0", - "multi-part-lite": "^1.0.0" - } - }, - "multi-part-lite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/multi-part-lite/-/multi-part-lite-1.0.0.tgz", - "integrity": "sha512-KxIRbBZZ45hoKX1ROD/19wJr0ql1bef1rE8Y1PCwD3PuNXV42pp7Wo8lEHYuAajoT4vfAFcd3rPjlkyEEyt1nw==" - }, "multikey-map": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/multikey-map/-/multikey-map-0.2.1.tgz", @@ -11764,11 +11506,6 @@ "release-zalgo": "^1.0.0" } }, - "parse-headers": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.4.tgz", - "integrity": "sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw==" - }, "parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -11793,11 +11530,6 @@ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true }, - "path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" - }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -11834,11 +11566,6 @@ "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true }, - "peek-readable": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", - "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==" - }, "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -11886,11 +11613,6 @@ "parse-ms": "^4.0.0" } }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" - }, "process-on-spawn": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", @@ -12055,24 +11777,6 @@ } } }, - "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==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readable-web-to-node-stream": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", - "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", - "requires": { - "readable-stream": "^3.6.0" - } - }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -12211,7 +11915,8 @@ "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -12482,14 +12187,6 @@ } } }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - }, "string-argv": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", @@ -12570,15 +12267,6 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" }, - "strtok3": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", - "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", - "requires": { - "@tokenizer/token": "^0.3.0", - "peek-readable": "^4.1.0" - } - }, "summary": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/summary/-/summary-2.1.0.tgz", @@ -12632,15 +12320,6 @@ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true }, - "token-types": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", - "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", - "requires": { - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" - } - }, "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -12750,7 +12429,8 @@ "undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true }, "universalify": { "version": "2.0.0", @@ -12782,11 +12462,6 @@ "punycode": "^2.1.0" } }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -12954,22 +12629,6 @@ "typedarray-to-buffer": "^3.1.5" } }, - "x3-linkedlist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/x3-linkedlist/-/x3-linkedlist-1.2.0.tgz", - "integrity": "sha512-mH/YwxpYSKNa8bDNF1yOuZCMuV+K80LtDN8vcLDUAwNazCxptDNsYt+zA/EJeYiGbdtKposhKLZjErGVOR8mag==" - }, - "xhr": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", - "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", - "requires": { - "global": "~4.4.0", - "is-function": "^1.0.1", - "parse-headers": "^2.0.0", - "xtend": "^4.0.0" - } - }, "xss": { "version": "1.0.14", "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.14.tgz", @@ -12980,11 +12639,6 @@ "cssfilter": "0.0.10" } }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, "y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", diff --git a/package.json b/package.json index 54a3d6dc..7fdd59c3 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "@js-joda/core": "^5.2.0", "ajv": "^8.11.0", "ansi-styles": "^5.2.0", - "arangojs": "^8.1.0", + "arangojs": "^10.0.0", "deep-equal": "^2.0.5", "graphql-tag": "^2.12.4", "graphql-type-json": "^0.3.2", diff --git a/spec/database/arangodb/arangodb-adapter.spec.ts b/spec/database/arangodb/arangodb-adapter.spec.ts index afe79144..26bf76ca 100644 --- a/spec/database/arangodb/arangodb-adapter.spec.ts +++ b/spec/database/arangodb/arangodb-adapter.spec.ts @@ -4,7 +4,7 @@ import { ArangoDBAdapter } from '../../../src/database/arangodb'; import { createSimpleModel } from '../../model/model-spec.helper'; import { createTempDatabase, getTempDatabase } from '../../regression/initialization'; import { isArangoDBDisabled } from './arangodb-test-utils'; -import { ArangoSearchViewProperties } from 'arangojs/view'; +import { ArangoSearchViewProperties } from 'arangojs/views'; describe('ArangoDBAdapter', () => { describe('updateSchema', () => { diff --git a/spec/database/arangodb/retry.spec.ts b/spec/database/arangodb/retry.spec.ts index 3cbb2dc6..44ec0c0d 100644 --- a/spec/database/arangodb/retry.spec.ts +++ b/spec/database/arangodb/retry.spec.ts @@ -63,9 +63,7 @@ async function prepareAdapter( const adapter = new ArangoDBAdapter({ ...dbConfig, arangoJSConfig: { - agentOptions: { - maxSockets: PARALLELISM, - }, + poolSize: PARALLELISM, }, retriesOnConflict: maxRetries, }); diff --git a/spec/regression/initialization.ts b/spec/regression/initialization.ts index b4e2d89b..1439db97 100644 --- a/spec/regression/initialization.ts +++ b/spec/regression/initialization.ts @@ -1,5 +1,5 @@ import { Database } from 'arangojs'; -import { Collection } from 'arangojs/collection'; +import { Collection } from 'arangojs/collections'; import { existsSync, readFileSync } from 'fs'; import { ExecutionResult, graphql, GraphQLSchema } from 'graphql'; import stripJsonComments from 'strip-json-comments'; diff --git a/src/database/arangodb/arangodb-adapter.ts b/src/database/arangodb/arangodb-adapter.ts index b54d73eb..cb36c834 100644 --- a/src/database/arangodb/arangodb-adapter.ts +++ b/src/database/arangodb/arangodb-adapter.ts @@ -1,13 +1,15 @@ import { Database } from 'arangojs'; +import { v4 as uuid } from 'uuid'; import { globalContext } from '../../config/global'; import { ProjectOptions } from '../../config/interfaces'; import { Logger } from '../../config/logging'; -import { DefaultClock, ExecutionOptions } from '../../execution/execution-options'; +import { ExecutionOptions } from '../../execution/execution-options'; import { ConflictRetriesExhaustedError, TransactionCancelledError, TransactionTimeoutError, } from '../../execution/runtime-errors'; +import { TransactionError } from '../../execution/transaction-error'; import { Model } from '../../model'; import { ALL_QUERY_RESULT_VALIDATOR_FUNCTION_PROVIDERS, QueryNode } from '../../query-tree'; import { FlexSearchTokenization } from '../../query-tree/flex-search'; @@ -25,10 +27,6 @@ import { } from '../database-adapter'; import { AQLCompoundQuery, aqlConfig, AQLExecutableQuery } from './aql'; import { generateTokenizationQuery, getAQLQuery } from './aql-generator'; -import { - RequestInstrumentation, - RequestInstrumentationPhase, -} from './arangojs-instrumentation/config'; import { CancellationManager } from './cancellation-manager'; import { ArangoDBConfig, @@ -42,11 +40,7 @@ import { hasRevisionAssertions } from './revision-helper'; import { SchemaAnalyzer } from './schema-migration/analyzer'; import { SchemaMigration } from './schema-migration/migrations'; import { MigrationPerformer } from './schema-migration/performer'; -import { TransactionError } from '../../execution/transaction-error'; import { ArangoDBVersion, ArangoDBVersionHelper } from './version-helper'; -import { v4 as uuid } from 'uuid'; - -const requestInstrumentationBodyKey = 'cruddlRequestInstrumentation'; interface ArangoExecutionOptions { readonly queries: ReadonlyArray; @@ -109,7 +103,16 @@ export class ArangoDBAdapter implements DatabaseAdapter { private schemaContext?: ProjectOptions, ) { this.logger = getArangoDBLogger(schemaContext); - this.db = initDatabase(config); + this.db = initDatabase({ + ...config, + arangoJSConfig: { + ...(config.arangoJSConfig ?? { + beforeRequest: (req) => { + req.headers; + }, + }), + }, + }); this.analyzer = new SchemaAnalyzer(config, schemaContext); this.migrationPerformer = new MigrationPerformer(config); this.versionHelper = new ArangoDBVersionHelper(this.db); @@ -611,65 +614,93 @@ export class ArangoDBAdapter implements DatabaseAdapter { } } - // we pass the cancellationToken to the call to Database.transaction(). This will remove the request from the - // http agent's queue. However, it won't cancel the request if already sent because ArangoDB does NOT abort a - // query in this case, so this would not help. In the contrary, it would free up the connection in the arangojs - // http agent so that more queries can be run in parallel than configured (via maxSockets). This would be - // dangerous because it might exhaust ArangoDB threads so that ArangoDB no longer responds, and it might even - // cause too much memory to be allocated. For this reason, we only kill the query (see below) and let that - // killed query also abort the transaction. - // Note: this only works because we use our own version of the arangojs database (CustomDatbase) - (args as any)[requestInstrumentationBodyKey] = { - onPhaseEnded: (phase: RequestInstrumentationPhase) => { - watch.stop(phase); - - if (phase === 'socketInit') { - // start the timeout promise if needed - if (requestSentCallback) { - requestSentCallback(); - } - - if (cancellationToken) { - // delay cancellation a bit for two reasons - // - don't take the effort of finding and killing a query if it's fast anyway - // - the cancellation might occur before the transaction script starts the query - // we only really need this to cancel long-running queries - cancellationToken - .then(() => sleep(30)) - .then(() => { - // don't try to kill the query if the transaction() call finished already - this would mean that it - // either was faster than the delay above, or the request was removed from the request queue - if (!isTransactionFinished) { - this.logger.debug(`Cancelling query ${transactionID}`); - this.cancellationManager - .cancelQuery(transactionID) - .catch((e) => { - this.logger.warn( - `Error cancelling query ${transactionID}: ${e.stack}`, - ); - }); - } - }); - } - } - }, - cancellationToken, - } as RequestInstrumentation; - const dbStartTime = getPreciseTime(); let transactionResult: ArangoTransactionResult; try { - transactionResult = await this.db.executeTransaction( - { - read: aqlQuery.readAccessedCollections.slice(), - write: aqlQuery.writeAccessedCollections.slice(), - }, - this.arangoExecutionFunction, + // Calling request() instead of executeTransaction() so we can pass beforeRequest + // Created a feature request to be able to pass beforeRequest to execute Transaction(): https://github.com/arangodb/arangojs/issues/817 + transactionResult = await this.db.request( { - params: args, - waitForSync: true, + method: 'POST', + pathname: '/_api/transaction', + body: { + collections: { + read: aqlQuery.readAccessedCollections, + write: aqlQuery.writeAccessedCollections, + }, + action: this.arangoExecutionFunction, + params: args, + waitForSync: true, + }, + beforeRequest: (req) => { + watch.stop('queuing'); + + // start the timeout promise if needed (transactionTimeoutMs should not include queue time) + if (requestSentCallback) { + requestSentCallback(); + } + + if (wasCancelled) { + throw new TransactionCancelledError( + 'Transaction was cancelled before it was started', + ); + } + + if (cancellationToken) { + // delay cancellation a bit for two reasons + // - don't take the effort of finding and killing a query if it's fast anyway + // - the cancellation might occur before the transaction script starts the query (so it would not find it) + // we only really need this to cancel long-running queries + // Also, note that we currently have no way to pass the cancellation token to the actual request + // Even if there was a way, we still probably would not want to do this. ArangoDB does not kill a query + // when the request is cancelled, so it would continue to process the request, but our queue would free up + // a slot -> we would effectively execute more queries in parallel than configured, potentially overloading the db + // That's why it is better to kill the query using the CancellationManager, and then let ArangoDB report the erorr to us + cancellationToken + .then(() => sleep(30)) + .then(() => { + // don't try to kill the query if the transaction() call finished already - this would mean that it + // either was faster than the delay above, or the request was removed from the request queue + if (!isTransactionFinished) { + this.logger.debug(`Cancelling query ${transactionID}`); + this.cancellationManager + .cancelQuery(transactionID) + .catch((e) => { + this.logger.warn( + `Error cancelling query ${transactionID}: ${e.stack}`, + ); + }); + } + }); + } + + // TODO figure out if we can get more timings. This is what we did earlier: + // although it's usually not relevant because the connections are using keepalive + /* + req.on('socket', (socket: Socket) => { + notifyAboutPhaseEnd(requestInstrumentation, 'socketInit'); + if (knownSockets.has(socket)) { + return; + } + knownSockets.add(socket); + socket.on('lookup', () => + notifyAboutPhaseEnd(requestInstrumentation, 'lookup'), + ); + socket.on('connect', () => + notifyAboutPhaseEnd(requestInstrumentation, 'connecting'), + ); + }); + */ + }, + afterResponse: () => { + // this is called when we recieved the headers + watch.stop('waiting'); + }, }, + (res) => res.parsedBody.result, ); + // request() resolves after it read and processed the response + watch.stop('receiving'); } catch (e: any) { isTransactionFinished = true; if (e.message.startsWith('RolledBackTransactionError: ')) { diff --git a/src/database/arangodb/arangojs-instrumentation/config.ts b/src/database/arangodb/arangojs-instrumentation/config.ts deleted file mode 100644 index 6939a8a8..00000000 --- a/src/database/arangodb/arangojs-instrumentation/config.ts +++ /dev/null @@ -1,19 +0,0 @@ -export const requestInstrumentationBodyKey = 'cruddlRequestInstrumentation'; - -export type RequestInstrumentationPhase = - | 'queuing' - | 'socketInit' - | 'lookup' - | 'connecting' - | 'waiting' - | 'receiving'; - -export interface RequestInstrumentation { - onPhaseEnded(phase: RequestInstrumentationPhase): void; - - readonly cancellationToken: Promise; - /** - * is set to true by custom-connection on cancellationToken.then() to allow synchronous access to the cancellation state - */ - isCancelled?: boolean; -} diff --git a/src/database/arangodb/arangojs-instrumentation/custom-connection.ts b/src/database/arangodb/arangojs-instrumentation/custom-connection.ts deleted file mode 100644 index 89f49c8b..00000000 --- a/src/database/arangodb/arangojs-instrumentation/custom-connection.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { Config, Connection, RequestOptions } from 'arangojs/connection'; -import { normalizeUrl } from 'arangojs/lib/normalizeUrl'; -import { ArangojsResponse } from 'arangojs/lib/request'; -import { RequestInstrumentation, requestInstrumentationBodyKey } from './config'; -import { createRequest, RequestOptions as CustomRequestOptions } from './custom-request'; -import { isReadonlyArray } from '../../../utils/utils'; - -/** - * @internal - */ -type Task = { - hostUrl?: string; - stack?: () => string; - allowDirtyRead: boolean; - retryOnConflict: number; - resolve: (result: any) => void; - reject: (error: Error) => void; - transform?: (res: ArangojsResponse) => any; - retries: number; - options: CustomRequestOptions; -}; - -export class CustomConnection extends Connection { - constructor(config?: Config) { - super(config); - } - - request( - { - hostUrl, - method = 'GET', - body, - expectBinary = false, - isBinary = false, - allowDirtyRead = false, - retryOnConflict = this._retryOnConflict, - timeout = 0, - headers, - ...urlInfo - }: RequestOptions, - transform?: (res: ArangojsResponse) => T, - ): Promise { - let requestInstrumentation: RequestInstrumentation | undefined; - if ( - typeof body === 'object' && - typeof body.params === 'object' && - requestInstrumentationBodyKey in body.params - ) { - requestInstrumentation = body.params[requestInstrumentationBodyKey]; - delete body.params[requestInstrumentationBodyKey]; - } - - if (requestInstrumentation && requestInstrumentation.cancellationToken) { - let ri = requestInstrumentation; - requestInstrumentation.cancellationToken.then(() => (ri.isCancelled = true)); - } - - return new Promise((resolve, reject) => { - let contentType = 'text/plain'; - if (isBinary) { - contentType = 'application/octet-stream'; - } else if (body) { - if (typeof body === 'object') { - body = JSON.stringify(body); - contentType = 'application/json'; - } else { - body = String(body); - } - } - - const extraHeaders: { [key: string]: string } = { - ...(this as any)._headers, - 'content-type': contentType, - 'x-arango-version': String((this as any)._arangoVersion), - }; - if (this._transactionId) { - extraHeaders['x-arango-trx-id'] = this._transactionId; - } - const task: Task = { - retries: 0, - hostUrl, - allowDirtyRead, - retryOnConflict, - options: { - url: (this as any)._buildUrl(urlInfo), - headers: { ...extraHeaders, ...headers }, - method, - expectBinary, - body, - requestInstrumentation, - }, - reject, - resolve, - transform, - }; - - if (this._precaptureStackTraces) { - if (typeof Error.captureStackTrace === 'function') { - const capture = {} as { readonly stack: string }; - Error.captureStackTrace(capture); - task.stack = () => `\n${capture.stack.split('\n').slice(3).join('\n')}`; - } else { - const capture = generateStackTrace() as { readonly stack: string }; - if (Object.prototype.hasOwnProperty.call(capture, 'stack')) { - task.stack = () => `\n${capture.stack.split('\n').slice(4).join('\n')}`; - } - } - } - - this._queue.push(task as any); - this._runQueue(); - }); - } - - addToHostList(urls: string | ReadonlyArray): string[] { - const cleanUrls = (isReadonlyArray(urls) ? urls : [urls]).map((url) => normalizeUrl(url)); - const newUrls = cleanUrls.filter((url) => this._hostUrls.indexOf(url) === -1); - this._hostUrls.push(...newUrls); - this._hosts.push( - ...newUrls.map((url: string) => createRequest(url, this._agentOptions, this._agent)), - ); - return cleanUrls; - } -} - -function generateStackTrace() { - let err = new Error(); - if (!err.stack) { - try { - throw err; - } catch (e: any) { - err = e; - } - } - return err; -} diff --git a/src/database/arangodb/arangojs-instrumentation/custom-database.ts b/src/database/arangodb/arangojs-instrumentation/custom-database.ts deleted file mode 100644 index 38eecc41..00000000 --- a/src/database/arangodb/arangojs-instrumentation/custom-database.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Database } from 'arangojs'; -import { Config } from 'arangojs/connection'; -import { CustomConnection } from './custom-connection'; - -export class CustomDatabase extends Database { - constructor(config?: Config) { - super(config); - // private field on Database set in super constructor - (this as any)._connection = new CustomConnection(config); - } -} diff --git a/src/database/arangodb/arangojs-instrumentation/custom-request.ts b/src/database/arangodb/arangojs-instrumentation/custom-request.ts deleted file mode 100644 index a2422ab2..00000000 --- a/src/database/arangodb/arangojs-instrumentation/custom-request.ts +++ /dev/null @@ -1,234 +0,0 @@ -/** - * Source: https://github.com/arangodb/arangojs - * - * Originally licensed under Apache License 2.0 - */ - -import { joinPath } from 'arangojs/lib/joinPath'; -import { Errback } from 'arangojs/lib/errback'; -import { omit } from 'arangojs/lib/omit'; -import { - Agent as HttpAgent, - ClientRequest, - ClientRequestArgs, - IncomingMessage, - request as httpRequest, -} from 'http'; -import { Agent as HttpsAgent, request as httpsRequest } from 'https'; -import { Socket } from 'net'; -import { parse as parseUrl, UrlWithStringQuery } from 'url'; -import { RequestInstrumentation, RequestInstrumentationPhase } from './config'; -import { SystemError } from 'arangojs/error'; -import { RequestOptions as ArangoRequestOptions } from 'arangojs/lib/request.node'; - -/** - * @internal - */ -function systemErrorToJSON(this: SystemError) { - return { - error: true, - errno: this.errno, - code: this.code, - syscall: this.syscall, - }; -} - -/** - * @internal - */ -export interface ArangojsResponse extends IncomingMessage { - request: ClientRequest; - body?: any; - arangojsHostUrl?: string; -} - -/** - * @internal - */ -export interface ArangojsError extends Error { - request: ClientRequest; - toJSON: () => Record; -} - -export interface RequestOptions extends ArangoRequestOptions { - requestInstrumentation?: RequestInstrumentation; -} - -/** - * @internal - */ -export type RequestFunction = { - (options: RequestOptions, cb: Errback): void; - close?: () => void; -}; - -/** - * collects sockets we already took the lookup/connect events from - * this is important to not re-add the listeners when sockets are being reused - */ -const knownSockets = new WeakSet(); - -export const isBrowser = false; - -export function createRequest(baseUrl: string, agentOptions: any, agent: any): RequestFunction { - const baseUrlParts = parseUrl(baseUrl) as Partial; - if (!baseUrlParts.protocol) { - throw new Error(`Invalid URL (no protocol): ${baseUrl}`); - } - const isTls = baseUrlParts.protocol === 'https:'; - let socketPath: string | undefined; - if (baseUrl.startsWith(`${baseUrlParts.protocol}//unix:`)) { - if (!baseUrlParts.pathname) { - throw new Error( - `Unix socket URL must be in the format http://unix:/socket/path, http+unix:///socket/path or unix:///socket/path not ${baseUrl}`, - ); - } - const i = baseUrlParts.pathname.indexOf(':'); - if (i === -1) { - socketPath = baseUrlParts.pathname; - delete baseUrlParts.pathname; - } else { - socketPath = baseUrlParts.pathname.slice(0, i); - baseUrlParts.pathname = baseUrlParts.pathname.slice(i + 1); - if (baseUrlParts.pathname === '') { - delete baseUrlParts.pathname; - } - } - } - if (socketPath && !socketPath.replace(/\//g, '').length) { - throw new Error(`Invalid URL (empty unix socket path): ${baseUrl}`); - } - if (!agent) { - const opts = omit(agentOptions, ['before', 'after']); - if (isTls) agent = new HttpsAgent(opts); - else agent = new HttpAgent(opts); - } - - return Object.assign( - function request( - { method, url, headers, body, timeout, requestInstrumentation }: RequestOptions, - callback: Errback, - ) { - // this is the last change we cancel a request - // we don't cancel running requests because arangodb does not kill queries when the request ist terminated - // thus, we keep the request open - // - to get notified if the request completes pretty quickly anyway so we don't need to kill the query - // - to take up a socket so that no new query is sent on it while the query is not yet killed - if (requestInstrumentation && requestInstrumentation.isCancelled) { - return callback( - new Error(`Request has been cancelled by caller before it was sent`), - ); - } - - notifyAboutPhaseEnd(requestInstrumentation, 'queuing'); - - let path = baseUrlParts.pathname - ? url.pathname - ? joinPath(baseUrlParts.pathname, url.pathname) - : baseUrlParts.pathname - : url.pathname; - const search = url.search - ? baseUrlParts.search - ? `${baseUrlParts.search}&${url.search.slice(1)}` - : url.search - : baseUrlParts.search; - if (search) path += search; - if (body && !headers['content-length']) { - headers['content-length'] = String(Buffer.byteLength(body)); - } - if (!headers['authorization']) { - const encoded = Buffer.from(baseUrlParts.auth || 'root:').toString('base64'); - headers['authorization'] = `Basic ${encoded}`; - } - const options: ClientRequestArgs = { path, method, headers, agent }; - if (socketPath) { - options.socketPath = socketPath; - } else { - options.host = baseUrlParts.hostname; - options.port = baseUrlParts.port; - } - let called = false; - - try { - const req = (isTls ? httpsRequest : httpRequest)( - options, - (res: IncomingMessage) => { - notifyAboutPhaseEnd(requestInstrumentation, 'waiting'); - const data: Buffer[] = []; - res.on('data', (chunk) => data.push(chunk as Buffer)); - res.on('end', () => { - const response = res as ArangojsResponse; - response.request = req; - response.body = Buffer.concat(data); - if (called) return; - called = true; - if (agentOptions.after) { - agentOptions.after(null, response); - } - notifyAboutPhaseEnd(requestInstrumentation, 'receiving'); - callback(null, response); - }); - }, - ); - if (requestInstrumentation) { - req.on('socket', (socket: Socket) => { - notifyAboutPhaseEnd(requestInstrumentation, 'socketInit'); - if (knownSockets.has(socket)) { - return; - } - knownSockets.add(socket); - socket.on('lookup', () => - notifyAboutPhaseEnd(requestInstrumentation, 'lookup'), - ); - socket.on('connect', () => - notifyAboutPhaseEnd(requestInstrumentation, 'connecting'), - ); - }); - } - if (timeout) { - req.setTimeout(timeout); - } - req.on('timeout', () => { - req.abort(); - }); - req.on('error', (err) => { - const error = err as ArangojsError; - error.request = req; - error.toJSON = systemErrorToJSON; - if (called) return; - called = true; - if (agentOptions.after) { - agentOptions.after(error); - } - callback(error); - }); - if (body) req.write(body); - if (agentOptions.before) { - agentOptions.before(req); - } - req.end(); - } catch (e: any) { - if (called) return; - called = true; - setTimeout(() => { - callback(e); - }, 0); - } - }, - { - close() { - agent.destroy(); - }, - }, - ); -} - -function notifyAboutPhaseEnd( - requestInstrumentation: RequestInstrumentation | undefined, - phase: RequestInstrumentationPhase, -) { - if (!requestInstrumentation) { - return; - } - requestInstrumentation.onPhaseEnded(phase); -} diff --git a/src/database/arangodb/config.ts b/src/database/arangodb/config.ts index 44eb1b7c..fb3638b6 100644 --- a/src/database/arangodb/config.ts +++ b/src/database/arangodb/config.ts @@ -1,10 +1,9 @@ import { Database } from 'arangojs'; -import { CreateCollectionOptions } from 'arangojs/collection'; -import { Config } from 'arangojs/connection'; +import { CreateCollectionOptions } from 'arangojs/collections'; +import { ConfigOptions } from 'arangojs/configuration'; import { globalContext } from '../../config/global'; import { ProjectOptions } from '../../config/interfaces'; import { Logger } from '../../config/logging'; -import { CustomDatabase } from './arangojs-instrumentation/custom-database'; import { ArangoSearchConfiguration } from './schema-migration/arango-search-helpers'; export declare type KeyGeneratorType = 'traditional' | 'autoincrement' | 'uuid' | 'padded'; @@ -16,7 +15,7 @@ export interface ArangoDBConfig { /** * Additional configuration options that will be passed to the ArangoJS Database constructor */ - readonly arangoJSConfig?: Partial; + readonly arangoJSConfig?: Partial; readonly url: string; readonly user?: string; @@ -77,7 +76,7 @@ export interface ArangoDBConfig { } export function initDatabase(config: ArangoDBConfig): Database { - const db = new CustomDatabase({ + const db = new Database({ ...(config.arangoJSConfig ? config.arangoJSConfig : {}), url: config.url, databaseName: config.databaseName, diff --git a/src/database/arangodb/index.ts b/src/database/arangodb/index.ts index 350cc0f8..9b7c63dc 100644 --- a/src/database/arangodb/index.ts +++ b/src/database/arangodb/index.ts @@ -1,5 +1,4 @@ -export { Config as ArangoJSConfig } from 'arangojs/connection'; -export { CreateCollectionOptions } from 'arangojs/collection'; +export { CreateCollectionOptions } from 'arangojs/collections'; export { ArangoDBAdapter } from './arangodb-adapter'; export { ArangoDBConfig, KeyGeneratorType } from './config'; export * from './schema-migration/migrations'; diff --git a/src/database/arangodb/schema-migration/analyzer.ts b/src/database/arangodb/schema-migration/analyzer.ts index 56d320ef..054c1f2a 100644 --- a/src/database/arangodb/schema-migration/analyzer.ts +++ b/src/database/arangodb/schema-migration/analyzer.ts @@ -1,5 +1,5 @@ import { Database } from 'arangojs'; -import { CollectionType } from 'arangojs/collection'; +import { CollectionType } from 'arangojs/collections'; import { NORM_CI_ANALYZER } from '../../../model/implementation/flex-search'; import { ProjectOptions } from '../../../config/interfaces'; import { Logger } from '../../../config/logging'; diff --git a/src/database/arangodb/schema-migration/arango-search-helpers.ts b/src/database/arangodb/schema-migration/arango-search-helpers.ts index 5f33c09e..0c992578 100644 --- a/src/database/arangodb/schema-migration/arango-search-helpers.ts +++ b/src/database/arangodb/schema-migration/arango-search-helpers.ts @@ -1,5 +1,5 @@ import { Database } from 'arangojs'; -import { AnalyzerDescription, CreateAnalyzerOptions } from 'arangojs/analyzer'; +import { AnalyzerDescription, CreateAnalyzerOptions } from 'arangojs/analyzers'; import { ArangoSearchViewLink, ArangoSearchViewLinkOptions, @@ -7,7 +7,7 @@ import { CreateArangoSearchViewOptions, View, ViewProperties, -} from 'arangojs/view'; +} from 'arangojs/views'; import deepEqual from 'deep-equal'; import { isEqual } from 'lodash'; import { Field, Model, RootEntityType } from '../../../model'; diff --git a/src/database/arangodb/schema-migration/migrations.ts b/src/database/arangodb/schema-migration/migrations.ts index f58d70a8..e7ece3e9 100644 --- a/src/database/arangodb/schema-migration/migrations.ts +++ b/src/database/arangodb/schema-migration/migrations.ts @@ -1,5 +1,5 @@ -import { CreateAnalyzerOptions } from 'arangojs/analyzer'; -import { ArangoSearchViewPropertiesOptions, CreateArangoSearchViewOptions } from 'arangojs/view'; +import { CreateAnalyzerOptions } from 'arangojs/analyzers'; +import { ArangoSearchViewPropertiesOptions, CreateArangoSearchViewOptions } from 'arangojs/views'; import { Relation } from '../../../model/implementation'; import { describeIndex, getIndexDescriptor, IndexDefinition } from './index-helpers'; diff --git a/src/database/arangodb/schema-migration/performer.ts b/src/database/arangodb/schema-migration/performer.ts index 0c769d4d..31173ece 100644 --- a/src/database/arangodb/schema-migration/performer.ts +++ b/src/database/arangodb/schema-migration/performer.ts @@ -1,5 +1,5 @@ import { Database } from 'arangojs'; -import { CollectionType } from 'arangojs/collection'; +import { CollectionType } from 'arangojs/collections'; import { ArangoDBConfig, initDatabase } from '../config'; import { ERROR_ARANGO_DATA_SOURCE_NOT_FOUND, diff --git a/src/database/arangodb/version-helper.ts b/src/database/arangodb/version-helper.ts index f3d96b24..fa5d987d 100644 --- a/src/database/arangodb/version-helper.ts +++ b/src/database/arangodb/version-helper.ts @@ -10,11 +10,8 @@ export class ArangoDBVersionHelper { constructor(private readonly db: Database) {} async getArangoDBVersionAsString(): Promise { - const result = await this.db.route('_api').get('version'); - if (!result || !result.body || !result.body.version) { - return undefined; - } - return result.body.version; + const versionInfo = await this.db.version(); + return versionInfo.version; } async getArangoDBVersion(): Promise { diff --git a/src/execution/runtime-errors.ts b/src/execution/runtime-errors.ts index 319afb54..320c5668 100644 --- a/src/execution/runtime-errors.ts +++ b/src/execution/runtime-errors.ts @@ -21,8 +21,8 @@ export class TransactionTimeoutError extends Error { * Is thrown if a transaction is cancelled via the cancellation token before it completed */ export class TransactionCancelledError extends Error { - constructor() { - super(`Transaction was cancelled and has been rolled back`); + constructor(message = `Transaction was cancelled and has been rolled back`) { + super(message); this.name = this.constructor.name; } } diff --git a/tsconfig.json b/tsconfig.json index 55c8e759..b5f48432 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,7 +14,12 @@ "downlevelIteration": true, "experimentalDecorators": true, "esModuleInterop": true, - "lib": ["ES2022"], + "lib": [ + "ES2022", + + // workaround until https://github.com/arangodb/arangojs/issues/818 is fixed + "DOM" + ], "paths": { "*": ["./src/typings/*"] },