From 3693306488ac319f2281b104e36fff4ff032c20e Mon Sep 17 00:00:00 2001 From: Gajus Date: Thu, 9 May 2024 14:39:16 -0700 Subject: [PATCH 01/22] refactor: port slonik-dataloaders --- package-lock.json | 1604 ++++++++++++++++- packages/slonik-dataloaders/README.md | 134 ++ packages/slonik-dataloaders/package.json | 45 + packages/slonik-dataloaders/src/.eslintrc | 26 + .../src/factories/createConnectionLoader.ts | 43 + .../createConnectionLoaderClass.test.ts | 370 ++++ .../factories/createConnectionLoaderClass.ts | 314 ++++ .../src/factories/createListLoader.ts | 32 + .../src/factories/createNodeByIdLoader.ts | 14 + .../createNodeByIdLoaderClass.test.ts | 104 ++ .../factories/createNodeByIdLoaderClass.ts | 80 + packages/slonik-dataloaders/src/index.ts | 5 + packages/slonik-dataloaders/src/types.ts | 21 + .../src/utilities/fromCursor.ts | 5 + .../src/utilities/getColumnIdentifiers.ts | 15 + .../src/utilities/getRequestedFields.ts | 47 + .../src/utilities/snakeCase.ts | 36 + .../src/utilities/toCursor.ts | 5 + packages/slonik-dataloaders/tsconfig.json | 24 + 19 files changed, 2854 insertions(+), 70 deletions(-) create mode 100644 packages/slonik-dataloaders/README.md create mode 100644 packages/slonik-dataloaders/package.json create mode 100644 packages/slonik-dataloaders/src/.eslintrc create mode 100644 packages/slonik-dataloaders/src/factories/createConnectionLoader.ts create mode 100644 packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts create mode 100644 packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts create mode 100644 packages/slonik-dataloaders/src/factories/createListLoader.ts create mode 100644 packages/slonik-dataloaders/src/factories/createNodeByIdLoader.ts create mode 100644 packages/slonik-dataloaders/src/factories/createNodeByIdLoaderClass.test.ts create mode 100644 packages/slonik-dataloaders/src/factories/createNodeByIdLoaderClass.ts create mode 100644 packages/slonik-dataloaders/src/index.ts create mode 100644 packages/slonik-dataloaders/src/types.ts create mode 100644 packages/slonik-dataloaders/src/utilities/fromCursor.ts create mode 100644 packages/slonik-dataloaders/src/utilities/getColumnIdentifiers.ts create mode 100644 packages/slonik-dataloaders/src/utilities/getRequestedFields.ts create mode 100644 packages/slonik-dataloaders/src/utilities/snakeCase.ts create mode 100644 packages/slonik-dataloaders/src/utilities/toCursor.ts create mode 100644 packages/slonik-dataloaders/tsconfig.json diff --git a/package-lock.json b/package-lock.json index 8ed16308..5964a34e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1310,6 +1310,397 @@ "node": ">=16" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -1879,6 +2270,18 @@ "node": ">=8" } }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", @@ -2087,34 +2490,258 @@ "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.6.tgz", "integrity": "sha512-YBcMfqNSwn3SujUJvAaySy5tlYbYm6tVt9SKoXu8BaTdKGROiJDgPR3TXpZdAKUfklzm3lRapJEAltiMQtBgZg==", "dev": true, - "dependencies": { - "@peculiar/asn1-schema": "^2.3.8", - "@peculiar/json-schema": "^1.1.12", - "pvtsutils": "^1.3.5", - "tslib": "^2.6.2", - "webcrypto-core": "^1.7.9" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.8", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.5", + "tslib": "^2.6.2", + "webcrypto-core": "^1.7.9" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@repeaterjs/repeater": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.5.tgz", + "integrity": "sha512-l3YHBLAol6d/IKnB9LhpD0cEZWAoe3eFKUyTYWmFmCO2Q/WOckxLQAUyMZWwZV2M/m3+4vgRoaolFqaII82/TA==", + "dev": true + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz", + "integrity": "sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.2.tgz", + "integrity": "sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz", + "integrity": "sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.2.tgz", + "integrity": "sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.2.tgz", + "integrity": "sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.2.tgz", + "integrity": "sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz", + "integrity": "sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz", + "integrity": "sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.2.tgz", + "integrity": "sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.2.tgz", + "integrity": "sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.2.tgz", + "integrity": "sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz", + "integrity": "sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz", + "integrity": "sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.2.tgz", + "integrity": "sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==", + "cpu": [ + "arm64" + ], "dev": true, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/@repeaterjs/repeater": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.5.tgz", - "integrity": "sha512-l3YHBLAol6d/IKnB9LhpD0cEZWAoe3eFKUyTYWmFmCO2Q/WOckxLQAUyMZWwZV2M/m3+4vgRoaolFqaII82/TA==", - "dev": true + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.2.tgz", + "integrity": "sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.2.tgz", + "integrity": "sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true }, "node_modules/@rushstack/eslint-patch": { "version": "1.10.2", @@ -2122,6 +2749,12 @@ "integrity": "sha512-hw437iINopmQuxWPSUEvqE56NCPsiU8N4AYtfHmJFckclktzK9YQJieD3XkDCDH4OjL+C7zgPUh73R/nrcHrqw==", "dev": true }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, "node_modules/@sinonjs/commons": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", @@ -2170,6 +2803,10 @@ "resolved": "packages/benchmark", "link": true }, + "node_modules/@slonik/dataloaders": { + "resolved": "packages/slonik-dataloaders", + "link": true + }, "node_modules/@slonik/driver": { "resolved": "packages/driver", "link": true @@ -2290,6 +2927,12 @@ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -2722,6 +3365,111 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "node_modules/@vitest/expect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", + "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==", + "dev": true, + "dependencies": { + "@vitest/spy": "1.6.0", + "@vitest/utils": "1.6.0", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.0.tgz", + "integrity": "sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==", + "dev": true, + "dependencies": { + "@vitest/utils": "1.6.0", + "p-limit": "^5.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner/node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/runner/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/snapshot": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.0.tgz", + "integrity": "sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==", + "dev": true, + "dependencies": { + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot/node_modules/magic-string": { + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "node_modules/@vitest/spy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", + "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==", + "dev": true, + "dependencies": { + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", + "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==", + "dev": true, + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@whatwg-node/events": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.0.3.tgz", @@ -3152,6 +3900,15 @@ "node": ">=10.0.0" } }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/ast-types": { "version": "0.16.1", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", @@ -3521,6 +4278,15 @@ "node": ">=10.16.0" } }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/caching-transform": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", @@ -3645,6 +4411,24 @@ "node": ">=12.19" } }, + "node_modules/chai": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -3720,6 +4504,18 @@ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -4035,6 +4831,12 @@ "node": ">=10.18.0 <11 || >=12.14.0 <13 || >=14" } }, + "node_modules/confbox": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", + "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", + "dev": true + }, "node_modules/configstore": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz", @@ -4545,6 +5347,18 @@ "node": ">=0.10.0" } }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/deep-freeze": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/deep-freeze/-/deep-freeze-0.0.1.tgz", @@ -4641,6 +5455,15 @@ "node": ">=0.3.1" } }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -4952,6 +5775,44 @@ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, + "node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" + } + }, "node_modules/escalade": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", @@ -6300,6 +7161,15 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -6309,6 +7179,68 @@ "node": ">=0.10.0" } }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/execa/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/execa/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/expect-type": { "version": "0.15.0", "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-0.15.0.tgz", @@ -6726,6 +7658,15 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -6797,6 +7738,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-symbol-description": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", @@ -6951,8 +7904,6 @@ "version": "16.8.1", "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz", "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==", - "dev": true, - "peer": true, "engines": { "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } @@ -7174,6 +8125,15 @@ "resolved": "https://registry.npmjs.org/human-id/-/human-id-1.0.2.tgz", "integrity": "sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==" }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, "node_modules/husky": { "version": "9.0.11", "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", @@ -8549,6 +9509,22 @@ "node": ">=4" } }, + "node_modules/local-pkg": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", + "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", + "dev": true, + "dependencies": { + "mlly": "^1.4.2", + "pkg-types": "^1.0.3" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -8714,6 +9690,15 @@ "loose-envify": "cli.js" } }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, "node_modules/lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -8882,6 +9867,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -8995,12 +9986,42 @@ "node": ">= 8.0.0" } }, + "node_modules/mlly": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.0.tgz", + "integrity": "sha512-U9SDaXGEREBYQgfejV97coK0UL1r+qnF2SyO9A3qcI8MzKnsIFKHNVEkrDyNncQTKQQumsasmeq84eNMdBfsNQ==", + "dev": true, + "dependencies": { + "acorn": "^8.11.3", + "pathe": "^1.1.2", + "pkg-types": "^1.1.0", + "ufo": "^1.5.3" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -9110,6 +10131,33 @@ "node": ">=0.10.0" } }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/nyc": { "version": "15.1.0", "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", @@ -9720,6 +10768,21 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/pg": { "version": "8.11.5", "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.5.tgz", @@ -10105,6 +11168,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pkg-types": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.1.1.tgz", + "integrity": "sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==", + "dev": true, + "dependencies": { + "confbox": "^0.1.7", + "mlly": "^1.7.0", + "pathe": "^1.1.2" + } + }, "node_modules/platform": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", @@ -10142,6 +11216,34 @@ "node": ">= 0.4" } }, + "node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/postgres": { "version": "3.4.4", "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.4.tgz", @@ -10300,6 +11402,38 @@ "node": ">=6.0.0" } }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, "node_modules/pretty-ms": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-8.0.0.tgz", @@ -10797,6 +11931,41 @@ "node": ">=18.0" } }, + "node_modules/rollup": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.2.tgz", + "integrity": "sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.17.2", + "@rollup/rollup-android-arm64": "4.17.2", + "@rollup/rollup-darwin-arm64": "4.17.2", + "@rollup/rollup-darwin-x64": "4.17.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.17.2", + "@rollup/rollup-linux-arm-musleabihf": "4.17.2", + "@rollup/rollup-linux-arm64-gnu": "4.17.2", + "@rollup/rollup-linux-arm64-musl": "4.17.2", + "@rollup/rollup-linux-powerpc64le-gnu": "4.17.2", + "@rollup/rollup-linux-riscv64-gnu": "4.17.2", + "@rollup/rollup-linux-s390x-gnu": "4.17.2", + "@rollup/rollup-linux-x64-gnu": "4.17.2", + "@rollup/rollup-linux-x64-musl": "4.17.2", + "@rollup/rollup-win32-arm64-msvc": "4.17.2", + "@rollup/rollup-win32-ia32-msvc": "4.17.2", + "@rollup/rollup-win32-x64-msvc": "4.17.2", + "fsevents": "~2.3.2" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -11004,6 +12173,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -11231,6 +12406,15 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/spawn-wrap": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", @@ -11391,6 +12575,12 @@ "node": ">=8" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, "node_modules/stacktrace-parser": { "version": "0.1.10", "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", @@ -11410,6 +12600,12 @@ "node": ">=8" } }, + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "dev": true + }, "node_modules/stream-transform": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-2.1.3.tgz", @@ -11583,6 +12779,18 @@ "node": ">=10" } }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", @@ -11606,6 +12814,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.0.tgz", + "integrity": "sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==", + "dev": true, + "dependencies": { + "js-tokens": "^9.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/strip-literal/node_modules/js-tokens": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.0.tgz", + "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==", + "dev": true + }, "node_modules/summary": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/summary/-/summary-2.1.0.tgz", @@ -11752,6 +12978,30 @@ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", "dev": true }, + "node_modules/tinybench": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.8.0.tgz", + "integrity": "sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==", + "dev": true + }, + "node_modules/tinypool": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", + "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -12231,6 +13481,12 @@ "node": ">=14.17" } }, + "node_modules/ufo": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", + "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==", + "dev": true + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -12403,6 +13659,157 @@ "node": ">=12" } }, + "node_modules/vite": { + "version": "5.2.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz", + "integrity": "sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==", + "dev": true, + "dependencies": { + "esbuild": "^0.20.1", + "postcss": "^8.4.38", + "rollup": "^4.13.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.0.tgz", + "integrity": "sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==", + "dev": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.0.tgz", + "integrity": "sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==", + "dev": true, + "dependencies": { + "@vitest/expect": "1.6.0", + "@vitest/runner": "1.6.0", + "@vitest/snapshot": "1.6.0", + "@vitest/spy": "1.6.0", + "@vitest/utils": "1.6.0", + "acorn-walk": "^8.3.2", + "chai": "^4.3.10", + "debug": "^4.3.4", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.3", + "vite": "^5.0.0", + "vite-node": "1.6.0", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "1.6.0", + "@vitest/ui": "1.6.0", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/magic-string": { + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, "node_modules/vlq": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", @@ -12585,6 +13992,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/why-is-node-running": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", + "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", + "dev": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -12880,9 +14303,9 @@ } }, "node_modules/zod": { - "version": "3.23.6", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.6.tgz", - "integrity": "sha512-RTHJlZhsRbuA8Hmp/iNL7jnfc4nZishjsanDAfEY1QpDQZCahUp3xDzl+zfweE9BklxMUcgBgS1b7Lvie/ZVwA==", + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -12901,22 +14324,22 @@ }, "packages/benchmark": { "name": "@slonik/benchmark", - "version": "43.0.8", + "version": "44.0.0", "dependencies": { "benny": "^3.7.1", "pg": "^8.11.3", "pg-promise": "^11.5.5", "postgres": "^3.4.4", - "slonik": "^43.0.8" + "slonik": "^44.0.0" } }, "packages/driver": { "name": "@slonik/driver", - "version": "43.0.8", + "version": "44.0.0", "license": "BSD-3-Clause", "dependencies": { - "@slonik/types": "^43.0.8", - "@slonik/utilities": "^43.0.8", + "@slonik/types": "^44.0.0", + "@slonik/utilities": "^44.0.0", "roarr": "^7.21.1", "serialize-error": "^8.0.0", "strict-event-emitter-types": "^2.0.0" @@ -12949,10 +14372,10 @@ }, "packages/errors": { "name": "@slonik/errors", - "version": "43.0.8", + "version": "44.0.0", "license": "BSD-3-Clause", "dependencies": { - "@slonik/types": "^43.0.8" + "@slonik/types": "^44.0.0" }, "devDependencies": { "@types/node": "^18.15.3", @@ -12983,14 +14406,14 @@ }, "packages/pg-driver": { "name": "@slonik/pg-driver", - "version": "43.0.8", + "version": "44.0.0", "license": "BSD-3-Clause", "dependencies": { - "@slonik/driver": "^43.0.8", - "@slonik/errors": "^43.0.8", - "@slonik/sql-tag": "^43.0.8", - "@slonik/types": "^43.0.8", - "@slonik/utilities": "^43.0.8", + "@slonik/driver": "^44.0.0", + "@slonik/errors": "^44.0.0", + "@slonik/sql-tag": "^44.0.0", + "@slonik/types": "^44.0.0", + "@slonik/utilities": "^44.0.0", "pg": "^8.11.5", "pg-query-stream": "^4.5.5", "pg-types": "^4.0.2", @@ -13024,14 +14447,14 @@ } }, "packages/slonik": { - "version": "43.0.8", + "version": "44.0.0", "license": "BSD-3-Clause", "dependencies": { - "@slonik/driver": "^43.0.8", - "@slonik/errors": "^43.0.8", - "@slonik/pg-driver": "^43.0.8", - "@slonik/sql-tag": "^43.0.8", - "@slonik/utilities": "^43.0.8", + "@slonik/driver": "^44.0.0", + "@slonik/errors": "^44.0.0", + "@slonik/pg-driver": "^44.0.0", + "@slonik/sql-tag": "^44.0.0", + "@slonik/utilities": "^44.0.0", "get-stack-trace": "^3.1.1", "iso8601-duration": "^1.3.0", "postgres-interval": "^4.0.2", @@ -13060,8 +14483,49 @@ "zod": "^3" } }, + "packages/slonik-dataloaders": { + "name": "@slonik/dataloaders", + "version": "44.0.0", + "license": "BSD-3-Clause", + "dependencies": { + "dataloader": "^2.2.2", + "graphql": "^16.8.1", + "zod": "^3.23.8" + }, + "devDependencies": { + "eslint": "^8.57.0", + "eslint-config-canonical": "^42.8.1", + "slonik": "^44.0.0", + "typescript": "^4.5.3", + "vitest": "^1.6.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "slonik": ">=44.0.0" + } + }, + "packages/slonik-dataloaders/node_modules/dataloader": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.2.tgz", + "integrity": "sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==" + }, + "packages/slonik-dataloaders/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "packages/slonik-interceptor-field-name-transformation": { - "version": "43.0.8", + "version": "44.0.0", "license": "BSD-3-Clause", "dependencies": { "camelcase": "^6.2.1" @@ -13070,7 +14534,7 @@ "ava": "^5.3.1", "eslint": "^8.57.0", "eslint-config-canonical": "^42.8.1", - "slonik": "^43.0.8", + "slonik": "^44.0.0", "ts-node": "^10.4.0", "typescript": "^4.7.4" }, @@ -13078,7 +14542,7 @@ "node": ">=18" }, "peerDependencies": { - "slonik": ">=43.0.8" + "slonik": ">=44.0.0" } }, "packages/slonik-interceptor-field-name-transformation/node_modules/camelcase": { @@ -13104,7 +14568,7 @@ } }, "packages/slonik-interceptor-query-cache": { - "version": "43.0.8", + "version": "44.0.0", "license": "BSD-3-Clause", "dependencies": { "roarr": "^7.21.1", @@ -13114,7 +14578,7 @@ "ava": "^5.3.1", "eslint": "^8.57.0", "eslint-config-canonical": "^42.8.1", - "slonik": "^43.0.8", + "slonik": "^44.0.0", "ts-node": "^10.4.0", "typescript": "^4.5.3" }, @@ -13122,7 +14586,7 @@ "node": ">=18" }, "peerDependencies": { - "slonik": ">=43.0.8" + "slonik": ">=44.0.0" } }, "packages/slonik-interceptor-query-cache/node_modules/typescript": { @@ -13139,7 +14603,7 @@ } }, "packages/slonik-interceptor-query-logging": { - "version": "43.0.8", + "version": "44.0.0", "license": "BSD-3-Clause", "dependencies": { "crack-json": "^1.3.0", @@ -13150,7 +14614,7 @@ "ava": "^5.3.1", "eslint": "^8.57.0", "eslint-config-canonical": "^42.8.1", - "slonik": "^43.0.8", + "slonik": "^44.0.0", "ts-node": "^10.4.0", "typescript": "^4.5.3" }, @@ -13158,7 +14622,7 @@ "node": ">=18" }, "peerDependencies": { - "slonik": ">=43.0.8" + "slonik": ">=44.0.0" } }, "packages/slonik-interceptor-query-logging/node_modules/parse-ms": { @@ -13194,10 +14658,10 @@ } }, "packages/slonik-sql-tag-raw": { - "version": "43.0.8", + "version": "44.0.0", "license": "BSD-3-Clause", "dependencies": { - "@slonik/sql-tag": "^43.0.8", + "@slonik/sql-tag": "^44.0.0", "lodash": "^4.17.20", "roarr": "^7.21.1" }, @@ -13205,7 +14669,7 @@ "ava": "^5.3.1", "eslint": "^8.57.0", "eslint-config-canonical": "^42.8.1", - "slonik": "^43.0.8", + "slonik": "^44.0.0", "ts-node": "^10.4.0", "typescript": "^4.5.3" }, @@ -13213,7 +14677,7 @@ "node": ">=18" }, "peerDependencies": { - "slonik": ">=43.0.8" + "slonik": ">=44.0.0" } }, "packages/slonik-sql-tag-raw/node_modules/typescript": { @@ -13240,11 +14704,11 @@ }, "packages/sql-tag": { "name": "@slonik/sql-tag", - "version": "43.0.8", + "version": "44.0.0", "license": "BSD-3-Clause", "dependencies": { - "@slonik/errors": "^43.0.8", - "@slonik/types": "^43.0.8", + "@slonik/errors": "^44.0.0", + "@slonik/types": "^44.0.0", "roarr": "^7.21.1", "safe-stable-stringify": "^2.4.3", "serialize-error": "^8.0.0" @@ -13278,7 +14742,7 @@ }, "packages/types": { "name": "@slonik/types", - "version": "43.0.8", + "version": "44.0.0", "license": "BSD-3-Clause", "devDependencies": { "@types/node": "^18.15.3", @@ -13308,10 +14772,10 @@ }, "packages/utilities": { "name": "@slonik/utilities", - "version": "43.0.8", + "version": "44.0.0", "license": "BSD-3-Clause", "dependencies": { - "@slonik/types": "^43.0.8", + "@slonik/types": "^44.0.0", "roarr": "^7.21.1" }, "devDependencies": { diff --git a/packages/slonik-dataloaders/README.md b/packages/slonik-dataloaders/README.md new file mode 100644 index 00000000..c0fe0294 --- /dev/null +++ b/packages/slonik-dataloaders/README.md @@ -0,0 +1,134 @@ +# slonik-dataloaders + +[![NPM version](http://img.shields.io/npm/v/slonik-sql-tag-raw.svg?style=flat-square)](https://www.npmjs.org/package/slonik-sql-tag-raw) +[![Canonical Code Style](https://img.shields.io/badge/code%20style-canonical-blue.svg?style=flat-square)](https://github.com/gajus/canonical) +[![Twitter Follow](https://img.shields.io/twitter/follow/kuizinas.svg?style=social&label=Follow)](https://twitter.com/kuizinas) + +Utilities for creating [DataLoaders](https://github.com/graphql/dataloader) using [Slonik](https://github.com/gajus/slonik). These DataLoaders abstract away some of the complexity of working with cursor-style pagination when working with a SQL database, while still maintaining the flexibility that comes with writing raw SQL statements. + +### `createNodeByIdLoaderClass` + +Example usage: + +```ts +const UserByIdLoader = createNodeByIdLoaderClass({ + query: sql.type(User)` + SELECT + * + FROM user + `, +}); + +const pool = createPool("postgresql://"); +const loader = new UserByIdLoader(pool); +const user = await loader.load(99); +``` + +By default, the loader will look for an integer column named `id` to use as the key. You can specify a different column to use like this: + +```ts +const UserByIdLoader = createNodeByIdLoaderClass({ + column: { + name: 'unique_id', + type: 'text', + } + query: sql.type(User)` + SELECT + * + FROM user + `, +}); +``` + +### `createConnectionLoaderClass` + +Example usage + +```ts +const UserConnectionLoader = createConnectionLoaderClass({ + query: sql.type(User)` + SELECT + * + FROM user + `, +}); + +const pool = createPool("postgresql://"); +const loader = new UserByIdLoader(pool); +const connection = await loader.load({ + where: ({ firstName }) => sql.fragment`${firstName} = 'Susan'`, + orderBy: ({ firstName }) => [[firstName, "ASC"]], +}); +``` + +When calling `load`, you can include `where` and `orderBy` expression factories that will be used to generate each respective clause. These factory functions allow for type-safe loader usage and abstract away the actual table alias used inside the generated SQL query. Note that the column names passed to each factory reflect the type provided when creating the loader class (i.e. `User` in the example above); however, each column name is transformed using `columnNameTransformer` as described below. + +Usage example with forward pagination: + +```ts +const connection = await loader.load({ + orderBy: ({ firstName }) => [[firstName, "ASC"]], + limit: first, + cursor: after, +}); +``` + +Usage example with backward pagination: + +```ts +const connection = await loader.load({ + orderBy: ({ firstName }) => [[firstName, "ASC"]], + limit: last, + cursor: before, + reverse: true, +}); +``` + +#### Conditionally fetching edges and count based on requested fields + +In addition to the standard `edges` and `pageInfo` fields, each connection returned by the loader also includes a `count` field. This field reflects the total number of results that _would_ be returned if no limit was applied. In order to fetch both the edges and the count, the loader makes two separate database queries. However, the loader can determine whether it needs to request only one or both of the queries by looking at the GraphQL fields that were actually requested. To do this, we pass in the `GraphQLResolveInfo` parameter provided to every GraphQL resolver: + +```ts +const connection = await loader.load({ + orderBy: ({ firstName }) => [[firstName, "ASC"]], + limit: first, + cursor: after, + info, +}); +``` + +#### Working with edge fields + +It's possible to request columns that will be exposed as fields on the edge type in your schema, as opposed to on the node type. These fields should be included in your query and the TypeScript type provided to the loader. The loader returns each row of the results as both the `edge` and the `node`, so all requested columns are available inside the resolvers for either type. Note: each requested column should be unique, so if there's a name conflict, you should use an appropriate alias. For example: + +```ts +const UserConnectionLoader = createConnectionLoaderClass< + User & { edgeCreatedAt } +>({ + query: sql.unsafe` + SELECT + user.id, + user.name, + user.created_at, + friend.created_at edge_created_at + FROM user + INNER JOIN friend ON + user.id = friend.user_id + `, +}); +``` + +In the example above, if the field on the Edge type in the schema is named `createdAt`, we just need to write a resolver for it and resolve the value to that of the `edgeCreatedAt` property. + +### `columnNameTransformer` + +Both types of loaders also accept an `columnNameTransformer` option. By default, the transformer used is [snake-case](https://www.npmjs.com/package/snake-case). The default assumes: + +- You're using conventional snake case column names; and +- You're using either [`slonik-interceptor-field-name-transformation`](https://github.com/gajus/slonik-interceptor-field-name-transformation) or the [`slonik-interceptor-preset`](https://github.com/gajus/slonik-interceptor-preset), which means the columns are returned as camelCased in the query results + +By using the `columnNameTransformer` (snake case), fields can be referenced by their names as they appear in the results when calling the loader, while still referencing the correct columns inside the query itself. If your usage doesn't meet the above two criteria, consider providing an alternative transformer, like an identify function. + +## Acknowledgments + +This library has been originally developed by @danielrearden (https://github.com/danielrearden/slonik-dataloaders), and it has been ported (with adjustments) with Daniel's permission to Slonik monorepo. \ No newline at end of file diff --git a/packages/slonik-dataloaders/package.json b/packages/slonik-dataloaders/package.json new file mode 100644 index 00000000..92556103 --- /dev/null +++ b/packages/slonik-dataloaders/package.json @@ -0,0 +1,45 @@ +{ + "author": { + "email": "gajus@gajus.com", + "name": "Gajus Kuizinas", + "url": "http://gajus.com" + }, + "dependencies": { + "dataloader": "^2.2.2", + "graphql": "^16.8.1", + "zod": "^3.23.8" + }, + "description": "Logs Slonik queries.", + "devDependencies": { + "eslint": "^8.57.0", + "eslint-config-canonical": "^42.8.1", + "slonik": "^44.0.0", + "typescript": "^4.5.3", + "vitest": "^1.6.0" + }, + "engines": { + "node": ">=18" + }, + "keywords": [ + "postgresql", + "interceptor", + "logging" + ], + "license": "BSD-3-Clause", + "main": "./dist/index.js", + "name": "@slonik/dataloaders", + "peerDependencies": { + "slonik": ">=44.0.0" + }, + "repository": { + "type": "git", + "url": "https://github.com/gajus/slonik" + }, + "scripts": { + "build": "rm -fr ./dist && tsc", + "lint": "eslint ./src && tsc --noEmit", + "test": "npx vitest run" + }, + "typings": "./dist/index.d.ts", + "version": "44.0.0" +} diff --git a/packages/slonik-dataloaders/src/.eslintrc b/packages/slonik-dataloaders/src/.eslintrc new file mode 100644 index 00000000..a173a3dd --- /dev/null +++ b/packages/slonik-dataloaders/src/.eslintrc @@ -0,0 +1,26 @@ +{ + "extends": "canonical/auto", + "ignorePatterns": [ + "dist", + "package-lock.json" + ], + "overrides": [ + { + "files": "*.ts", + "rules": { + "import/no-cycle": 0, + "no-restricted-imports": ["error", "pg"] + } + }, + { + "files": ["*.test.ts", "**/*.test/*"], + "extends": "canonical/ava", + "rules": { + "@typescript-eslint/no-explicit-any": 0, + "@typescript-eslint/no-unused-expressions": 0, + "ava/no-ignored-test-files": 0 + } + } + ], + "root": true +} \ No newline at end of file diff --git a/packages/slonik-dataloaders/src/factories/createConnectionLoader.ts b/packages/slonik-dataloaders/src/factories/createConnectionLoader.ts new file mode 100644 index 00000000..dafe8e59 --- /dev/null +++ b/packages/slonik-dataloaders/src/factories/createConnectionLoader.ts @@ -0,0 +1,43 @@ +import { createConnectionLoaderClass } from './createConnectionLoaderClass'; +import { type DatabasePool, type QuerySqlToken } from 'slonik'; +import { type ZodTypeAny } from 'zod'; + +export const createConnectionLoader = ( + pool: DatabasePool, + query: QuerySqlToken, +) => { + const Loader = createConnectionLoaderClass({ + columnNameTransformer: (columnName) => { + return columnName; + }, + query, + }); + + const loader = new Loader(pool); + + type LoadParameters = Parameters[0]; + + return { + load: async (args: { + after?: string | null; + before?: string | null; + first?: number | null; + info?: LoadParameters['info']; + last?: number | null; + orderBy?: LoadParameters['orderBy']; + where?: LoadParameters['where']; + }) => { + const limit = args.first ?? args.last; + const reverse = Boolean(args.last ?? args.before); + const cursor = args.after ?? args.before; + + return await loader.load({ + cursor, + limit, + orderBy: args.orderBy, + reverse, + where: args.where, + }); + }, + }; +}; diff --git a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts new file mode 100644 index 00000000..cc0adacf --- /dev/null +++ b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts @@ -0,0 +1,370 @@ +import { createConnectionLoaderClass } from './createConnectionLoaderClass'; +import { + type FieldNode, + type GraphQLResolveInfo, + type OperationDefinitionNode, + parse, +} from 'graphql'; +import { createPool, type DatabasePool, sql } from 'slonik'; +import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'; +import { z } from 'zod'; + +const POSTGRES_DSN = + // eslint-disable-next-line n/no-process-env + process.env.POSTGRES_DSN ?? 'postgres://postgres@localhost:5432'; + +const getInfo = ( + fields: string[], +): Pick => { + const document = parse(`{ connection { ${fields.join(' ')} } }`); + + return { + fieldNodes: [ + (document.definitions[0] as OperationDefinitionNode).selectionSet + .selections[0] as FieldNode, + ], + fragments: {}, + }; +}; + +const BarConnectionLoader = createConnectionLoaderClass({ + query: sql.type( + z.object({ + id: z.number(), + uid: z.string(), + value: z.string(), + }), + )` + SELECT + * + FROM test_table_bar + `, +}); + +describe('createConnectionLoaderClass', () => { + let pool: DatabasePool; + + beforeAll(async () => { + pool = await createPool(POSTGRES_DSN); + + await pool.query(sql.unsafe` + CREATE TABLE IF NOT EXISTS test_table_bar ( + id integer NOT NULL PRIMARY KEY, + uid text NOT NULL, + value text NOT NULL + ); + `); + + await pool.query(sql.unsafe` + INSERT INTO test_table_bar + (id, uid, value) + VALUES + (1, 'z', 'aaa'), + (2, 'y', 'aaa'), + (3, 'x', 'bbb'), + (4, 'w', 'bbb'), + (5, 'v', 'ccc'), + (6, 'u', 'ccc'), + (7, 't', 'ddd'), + (8, 's', 'ddd'), + (9, 'r', 'eee'); + `); + }); + + afterAll(async () => { + if (pool) { + await pool.query(sql.unsafe` + DROP TABLE IF EXISTS test_table_bar; + `); + + await pool.end(); + } + }); + + it('loads all records with no additional options', async () => { + const loader = new BarConnectionLoader(pool, {}); + const result = await loader.load({}); + + expect(result).toMatchObject({ + pageInfo: { + endCursor: result.edges[8].cursor, + hasNextPage: false, + hasPreviousPage: false, + startCursor: result.edges[0].cursor, + }, + }); + expect(result.edges).toHaveLength(9); + }); + + it('loads records in ascending order', async () => { + const loader = new BarConnectionLoader(pool, {}); + const result = await loader.load({ + orderBy: ({ uid }) => [[uid, 'ASC']], + }); + + expect(result.edges[0].node.id).toEqual(9); + expect(result.edges[8].node.id).toEqual(1); + }); + + it('loads records in descending order', async () => { + const loader = new BarConnectionLoader(pool, {}); + const result = await loader.load({ + orderBy: ({ uid }) => [[uid, 'DESC']], + }); + + expect(result.edges[0].node.id).toEqual(1); + expect(result.edges[8].node.id).toEqual(9); + }); + + it('loads records with multiple order by expressions', async () => { + const loader = new BarConnectionLoader(pool, {}); + const result = await loader.load({ + orderBy: ({ uid, value }) => [ + [value, 'DESC'], + [uid, 'DESC'], + ], + }); + + expect(result.edges[0].node.id).toEqual(9); + expect(result.edges[8].node.id).toEqual(2); + }); + + it('loads records with complex order by expression', async () => { + const loader = new BarConnectionLoader(pool, {}); + const result = await loader.load({ + orderBy: ({ uid }) => [[sql.fragment`upper(${uid})`, 'ASC']], + }); + + expect(result.edges[0].node.id).toEqual(9); + expect(result.edges[8].node.id).toEqual(1); + }); + + it('loads records with where expression', async () => { + const loader = new BarConnectionLoader(pool, {}); + const result = await loader.load({ + where: ({ value }) => sql.fragment`upper(${value}) = 'EEE'`, + }); + + expect(result.edges).toHaveLength(1); + expect(result.edges[0].node.id).toEqual(9); + }); + + it('paginates through the records forwards', async () => { + const loader = new BarConnectionLoader(pool, {}); + const firstResult = await loader.load({ + limit: 4, + orderBy: ({ uid }) => [[uid, 'ASC']], + }); + + expect(firstResult.edges).toHaveLength(4); + expect(firstResult.edges[0].node.id).toEqual(9); + expect(firstResult.edges[3].node.id).toEqual(6); + expect(firstResult.pageInfo).toMatchObject({ + hasNextPage: true, + hasPreviousPage: false, + }); + + const secondResult = await loader.load({ + cursor: firstResult.pageInfo.endCursor, + limit: 4, + orderBy: ({ uid }) => [[uid, 'ASC']], + }); + + expect(secondResult.edges).toHaveLength(4); + expect(secondResult.edges[0].node.id).toEqual(5); + expect(secondResult.edges[3].node.id).toEqual(2); + expect(secondResult.pageInfo).toMatchObject({ + hasNextPage: true, + hasPreviousPage: true, + }); + + const thirdResult = await loader.load({ + cursor: secondResult.pageInfo.endCursor, + limit: 4, + orderBy: ({ uid }) => [[uid, 'ASC']], + }); + + expect(thirdResult.edges).toHaveLength(1); + expect(thirdResult.edges[0].node.id).toEqual(1); + expect(thirdResult.pageInfo).toMatchObject({ + hasNextPage: false, + hasPreviousPage: true, + }); + + const fourthResult = await loader.load({ + cursor: thirdResult.pageInfo.endCursor, + limit: 4, + orderBy: ({ uid }) => [[uid, 'ASC']], + }); + + expect(fourthResult.edges).toHaveLength(0); + expect(fourthResult.pageInfo).toMatchObject({ + hasNextPage: false, + hasPreviousPage: true, + }); + }); + + it('paginates through the records backwards', async () => { + const loader = new BarConnectionLoader(pool, {}); + const firstResult = await loader.load({ + limit: 4, + orderBy: ({ value, uid }) => [ + [value, 'ASC'], + [uid, 'ASC'], + ], + reverse: true, + }); + + expect(firstResult.edges).toHaveLength(4); + expect(firstResult.edges[0].node.id).toEqual(5); + expect(firstResult.edges[3].node.id).toEqual(9); + expect(firstResult.pageInfo).toMatchObject({ + hasNextPage: false, + hasPreviousPage: true, + }); + + const secondResult = await loader.load({ + cursor: firstResult.pageInfo.startCursor, + limit: 4, + orderBy: ({ value, uid }) => [ + [value, 'ASC'], + [uid, 'ASC'], + ], + reverse: true, + }); + + expect(secondResult.edges).toHaveLength(4); + expect(secondResult.edges[0].node.id).toEqual(1); + expect(secondResult.edges[3].node.id).toEqual(6); + expect(secondResult.pageInfo).toMatchObject({ + hasNextPage: true, + hasPreviousPage: true, + }); + + const thirdResult = await loader.load({ + cursor: secondResult.pageInfo.startCursor, + limit: 4, + orderBy: ({ value, uid }) => [ + [value, 'ASC'], + [uid, 'ASC'], + ], + reverse: true, + }); + + expect(thirdResult.edges).toHaveLength(1); + expect(thirdResult.edges[0].node.id).toEqual(2); + expect(thirdResult.pageInfo).toMatchObject({ + hasNextPage: true, + hasPreviousPage: false, + }); + + const fourthResult = await loader.load({ + cursor: thirdResult.pageInfo.startCursor, + limit: 4, + orderBy: ({ value, uid }) => [ + [value, 'ASC'], + [uid, 'ASC'], + ], + reverse: true, + }); + + expect(fourthResult.edges).toHaveLength(0); + expect(fourthResult.pageInfo).toMatchObject({ + hasNextPage: true, + hasPreviousPage: false, + }); + }); + + it('batches loaded records', async () => { + const loader = new BarConnectionLoader(pool, {}); + const poolAnySpy = vi.spyOn(pool, 'any'); + poolAnySpy.mockClear(); + const results = await Promise.all([ + loader.load({ + orderBy: ({ uid }) => [[uid, 'ASC']], + }), + loader.load({ + orderBy: ({ uid }) => [[uid, 'DESC']], + }), + ]); + + expect(poolAnySpy).toHaveBeenCalledTimes(2); + expect(results[0].edges[0].node.id).toEqual(9); + expect(results[0].edges[8].node.id).toEqual(1); + expect(results[1].edges[0].node.id).toEqual(1); + expect(results[1].edges[8].node.id).toEqual(9); + }); + + it('caches loaded records', async () => { + const loader = new BarConnectionLoader(pool, {}); + const poolAnySpy = vi.spyOn(pool, 'any'); + poolAnySpy.mockClear(); + const resultsA = await loader.load({ + orderBy: ({ uid }) => [[uid, 'ASC']], + }); + const resultsB = await loader.load({ + orderBy: ({ uid }) => [[uid, 'ASC']], + }); + + expect(poolAnySpy).toHaveBeenCalledTimes(2); + expect(resultsA.edges[0].node.id).toEqual(9); + expect(resultsA.edges[8].node.id).toEqual(1); + expect(resultsB.edges[0].node.id).toEqual(9); + expect(resultsB.edges[8].node.id).toEqual(1); + }); + + it('gets the count', async () => { + const loader = new BarConnectionLoader(pool, {}); + const results = await Promise.all([ + loader.load({ + info: getInfo(['edges', 'count']), + where: ({ value }) => sql.fragment`upper(${value}) = 'CCC'`, + }), + loader.load({ + info: getInfo(['edges', 'count']), + where: ({ value }) => sql.fragment`upper(${value}) = 'EEE'`, + }), + ]); + + expect(results[0].count).toEqual(2n); + expect(results[1].count).toEqual(1n); + }); + + it('gets the count without fetching edges', async () => { + const loader = new BarConnectionLoader(pool, {}); + const results = await Promise.all([ + loader.load({ + info: getInfo(['count']), + where: ({ value }) => sql.fragment`upper(${value}) = 'CCC'`, + }), + loader.load({ + info: getInfo(['count']), + where: ({ value }) => sql.fragment`upper(${value}) = 'EEE'`, + }), + ]); + + expect(results[0].count).toEqual(2n); + expect(results[0].edges.length).toEqual(0); + expect(results[1].count).toEqual(1n); + expect(results[1].edges.length).toEqual(0); + }); + + it('gets the edges without fetching edges', async () => { + const loader = new BarConnectionLoader(pool, {}); + const results = await Promise.all([ + loader.load({ + info: getInfo(['edges']), + where: ({ value }) => sql.fragment`upper(${value}) = 'CCC'`, + }), + loader.load({ + info: getInfo(['pageInfo']), + where: ({ value }) => sql.fragment`upper(${value}) = 'EEE'`, + }), + ]); + + expect(results[0].count).toEqual(0); + expect(results[0].edges.length).toEqual(2); + expect(results[1].count).toEqual(0); + expect(results[1].edges.length).toEqual(1); + }); +}); diff --git a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts new file mode 100644 index 00000000..621dfa7a --- /dev/null +++ b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts @@ -0,0 +1,314 @@ +import { + type ColumnIdentifiers, + type Connection, + type OrderDirection, +} from '../types'; +import { fromCursor } from '../utilities/fromCursor'; +import { getColumnIdentifiers } from '../utilities/getColumnIdentifiers'; +import { getRequestedFields } from '../utilities/getRequestedFields'; +import { snakeCase } from '../utilities/snakeCase'; +import { toCursor } from '../utilities/toCursor.js'; +import DataLoader from 'dataloader'; +import { type GraphQLResolveInfo } from 'graphql'; +import { + type CommonQueryMethods, + type QuerySqlToken, + sql, + type SqlToken, +} from 'slonik'; +import { type AnyZodObject, z, type ZodTypeAny } from 'zod'; + +type DataLoaderKey = { + cursor?: string | null; + info?: Pick; + limit?: number | null; + orderBy?: ( + identifiers: ColumnIdentifiers, + ) => Array<[SqlToken, OrderDirection]>; + reverse?: boolean; + where?: (identifiers: ColumnIdentifiers) => SqlToken; +}; + +const SORT_COLUMN_ALIAS = 's1'; +const TABLE_ALIAS = 't1'; + +export const createConnectionLoaderClass = (config: { + columnNameTransformer?: (column: string) => string; + query: QuerySqlToken; +}) => { + const { columnNameTransformer = snakeCase, query } = config; + const columnIdentifiers = getColumnIdentifiers>( + TABLE_ALIAS, + columnNameTransformer, + ); + + return class ConnectionLoaderClass extends DataLoader< + DataLoaderKey>, + Connection>, + string + > { + public constructor( + pool: CommonQueryMethods, + dataLoaderOptions?: DataLoader.Options< + DataLoaderKey>, + Connection>, + string + >, + ) { + super( + async (loaderKeys) => { + const edgesQueries: QuerySqlToken[] = []; + const countQueries: QuerySqlToken[] = []; + + for (const [index, loaderKey] of loaderKeys.entries()) { + const { + cursor, + info, + limit, + orderBy, + reverse = false, + where, + } = loaderKey; + + // If a GraphQLResolveInfo object was not provided, we will assume both pageInfo and edges were requested + const requestedFields = info + ? getRequestedFields(info) + : new Set(['pageInfo', 'edges', 'count']); + + const conditions: SqlToken[] = where + ? [sql.fragment`(${where(columnIdentifiers)})`] + : []; + const queryKey = String(index); + + const selectExpressions = [sql.fragment`${queryKey} "key"`]; + + if (requestedFields.has('count')) { + countQueries.push( + sql.unsafe`( + SELECT + ${sql.join( + [...selectExpressions, sql.fragment`count(*) count`], + sql.fragment`, `, + )} + FROM ( + ${query} + ) ${sql.identifier([TABLE_ALIAS])} + WHERE ${ + conditions.length + ? sql.fragment`${sql.join( + conditions, + sql.fragment` AND `, + )}` + : sql.fragment`TRUE` + } + )`, + ); + } + + if ( + requestedFields.has('pageInfo') || + requestedFields.has('edges') + ) { + const orderByExpressions: Array<[SqlToken, OrderDirection]> = + orderBy ? orderBy(columnIdentifiers) : []; + + selectExpressions.push( + sql.fragment`${sql.identifier([TABLE_ALIAS])}.*`, + sql.fragment`json_build_array(${ + orderByExpressions.length + ? sql.join( + orderByExpressions.map(([expression]) => expression), + sql.fragment`,`, + ) + : sql.fragment`` + }) ${sql.identifier([SORT_COLUMN_ALIAS])}`, + ); + + const orderByClause = orderByExpressions.length + ? sql.fragment`ORDER BY ${sql.join( + orderByExpressions.map( + ([expression, direction]) => + sql.fragment`${expression} ${ + direction === (reverse ? 'DESC' : 'ASC') + ? sql.fragment`ASC` + : sql.fragment`DESC` + }`, + ), + sql.fragment`,`, + )}` + : sql.fragment``; + + if (cursor) { + const values = fromCursor(cursor); + conditions.push( + sql.fragment`(${sql.join( + orderByExpressions.map((_orderByExpression, outerIndex) => { + const expressions = orderByExpressions.slice( + 0, + outerIndex + 1, + ); + return sql.fragment`(${sql.join( + expressions.map( + ([expression, direction], innerIndex) => { + let comparisonOperator = sql.fragment`=`; + if (innerIndex === expressions.length - 1) { + comparisonOperator = + direction === (reverse ? 'DESC' : 'ASC') + ? sql.fragment`>` + : sql.fragment`<`; + } + + return sql.fragment`${expression} ${comparisonOperator} ${values[innerIndex]}`; + }, + ), + sql.fragment` AND `, + )})`; + }), + sql.fragment` OR `, + )})`, + ); + } + + const whereExpression = conditions.length + ? sql.fragment`${sql.join(conditions, sql.fragment` AND `)}` + : sql.fragment`TRUE`; + + edgesQueries.push( + sql.unsafe`( + SELECT + ${sql.join(selectExpressions, sql.fragment`, `)} + FROM ( + ${query} + ) ${sql.identifier([TABLE_ALIAS])} + WHERE ${whereExpression} + ${orderByClause} + LIMIT ${limit ? limit + 1 : null} + )`, + ); + } + } + + const parser = query.parser as unknown as AnyZodObject; + + const extendedParser = + // @ts-expect-error Accessing internal property to determine if parser is an instance of z.any() + parser._any === true + ? z + .object({ + key: z.union([z.string(), z.number()]), + s1: z.array(z.unknown()), + }) + .passthrough() + : parser.extend({ + key: z.union([z.string(), z.number()]), + s1: z.array(z.unknown()), + }); + + const [edgesRecords, countRecords] = await Promise.all([ + edgesQueries.length + ? pool.any( + sql.type(extendedParser)`${sql.join( + edgesQueries, + sql.fragment`UNION ALL`, + )}`, + ) + : [], + countQueries.length + ? pool.any( + sql.unsafe`${sql.join( + countQueries, + sql.fragment`UNION ALL`, + )}`, + ) + : [], + ]); + + const connections = loaderKeys.map((loaderKey, loaderKeyIndex) => { + const queryKey = String(loaderKeyIndex); + const { cursor, limit, reverse = false } = loaderKey; + + const edges = edgesRecords + .filter((record) => { + return record.key === queryKey; + }) + .map((record) => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { key, ...rest } = record; + const cursorValues: string[] = []; + + let index = 0; + + while (true) { + const value = record[SORT_COLUMN_ALIAS]?.[index]; + if (value === undefined) { + break; + } + + cursorValues.push(value as string); + + index++; + } + + return { + ...rest, + cursor: toCursor(cursorValues), + node: rest, + }; + }); + + const slicedEdges = edges.slice( + 0, + limit === null ? undefined : limit, + ); + + if (reverse) { + slicedEdges.reverse(); + } + + const hasMore = Boolean(edges.length > slicedEdges.length); + const pageInfo = { + endCursor: slicedEdges[slicedEdges.length - 1]?.cursor || null, + hasNextPage: reverse ? Boolean(cursor) : hasMore, + hasPreviousPage: reverse ? hasMore : Boolean(cursor), + startCursor: slicedEdges[0]?.cursor || null, + }; + + const count = + countRecords.find((record) => { + return record.key === queryKey; + })?.count ?? 0; + + return { + count, + edges: slicedEdges, + pageInfo, + }; + }); + + return connections; + }, + { + ...dataLoaderOptions, + cacheKeyFn: ({ + cursor, + info, + limit, + orderBy, + reverse = false, + where, + }) => { + const requestedFields = info + ? getRequestedFields(info) + : new Set(['pageInfo', 'edges']); + + return `${cursor}|${reverse}|${limit}|${JSON.stringify( + orderBy?.(columnIdentifiers), + )}|${JSON.stringify( + where?.(columnIdentifiers), + )}|${requestedFields.values()}`; + }, + }, + ); + } + }; +}; diff --git a/packages/slonik-dataloaders/src/factories/createListLoader.ts b/packages/slonik-dataloaders/src/factories/createListLoader.ts new file mode 100644 index 00000000..0695fb69 --- /dev/null +++ b/packages/slonik-dataloaders/src/factories/createListLoader.ts @@ -0,0 +1,32 @@ +import { createConnectionLoader } from './createConnectionLoader'; +import { type DatabasePool, type QuerySqlToken } from 'slonik'; +import { type ZodTypeAny } from 'zod'; + +export const createListLoader = ( + pool: DatabasePool, + query: QuerySqlToken, +) => { + const loader = createConnectionLoader(pool, query); + + type LoadParameters = Parameters[0]; + + return { + load: async (args: { + orderBy?: LoadParameters['orderBy']; + where?: LoadParameters['where']; + }) => { + const nodes = []; + + const connection = await loader.load({ + orderBy: args.orderBy, + where: args.where, + }); + + for (const edge of connection.edges) { + nodes.push(edge.node); + } + + return nodes; + }, + }; +}; diff --git a/packages/slonik-dataloaders/src/factories/createNodeByIdLoader.ts b/packages/slonik-dataloaders/src/factories/createNodeByIdLoader.ts new file mode 100644 index 00000000..ea8b5149 --- /dev/null +++ b/packages/slonik-dataloaders/src/factories/createNodeByIdLoader.ts @@ -0,0 +1,14 @@ +import { createNodeByIdLoaderClass } from './createNodeByIdLoaderClass'; +import { type DatabasePool, type QuerySqlToken } from 'slonik'; +import { type ZodTypeAny } from 'zod'; + +export const createNodeByIdLoader = ( + pool: DatabasePool, + query: QuerySqlToken, +) => { + const Loader = createNodeByIdLoaderClass({ + query, + }); + + return new Loader(pool); +}; diff --git a/packages/slonik-dataloaders/src/factories/createNodeByIdLoaderClass.test.ts b/packages/slonik-dataloaders/src/factories/createNodeByIdLoaderClass.test.ts new file mode 100644 index 00000000..02969980 --- /dev/null +++ b/packages/slonik-dataloaders/src/factories/createNodeByIdLoaderClass.test.ts @@ -0,0 +1,104 @@ +import { createNodeByIdLoaderClass } from './createNodeByIdLoaderClass.js'; +import { createPool, type DatabasePool, sql } from 'slonik'; +import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'; +import { z } from 'zod'; + +const POSTGRES_DSN = + // eslint-disable-next-line n/no-process-env + process.env.POSTGRES_DSN ?? 'postgres://postgres@localhost:5432'; + +const FooByIdLoader = createNodeByIdLoaderClass({ + query: sql.type( + z.object({ + id: z.number(), + uid: z.string(), + }), + )` + SELECT + * + FROM test_table_foo + `, +}); + +describe('createRecordByUniqueColumnLoader', () => { + let pool: DatabasePool; + + beforeAll(async () => { + pool = await createPool(POSTGRES_DSN); + + await pool.query(sql.unsafe` + CREATE TABLE IF NOT EXISTS test_table_foo ( + id integer NOT NULL PRIMARY KEY, + uid text NOT NULL + ); + `); + + await pool.query(sql.unsafe` + INSERT INTO test_table_foo + (id, uid) + VALUES + (1, 'a'), + (2, 'b'), + (3, 'c'); + `); + }); + + afterAll(async () => { + if (pool) { + await pool.query(sql.unsafe` + DROP TABLE IF EXISTS test_table_foo; + `); + + await pool.end(); + } + }); + + it('loads record by numeric column', async () => { + const loader = new FooByIdLoader(pool, {}); + const result = await loader.load(2); + + expect(result).toMatchObject({ id: 2, uid: 'b' }); + }); + + it("returns null when a match can't be found", async () => { + const loader = new FooByIdLoader(pool, {}); + const result = await loader.load(999); + + expect(result).toEqual(null); + }); + + it('batches and caches loaded records', async () => { + const loader = new FooByIdLoader(pool, {}); + const poolAnySpy = vi.spyOn(pool, 'any'); + const results = await Promise.all([loader.load(3), loader.load(2)]); + + expect(poolAnySpy).toHaveBeenCalledTimes(1); + expect(results).toMatchObject([ + { id: 3, uid: 'c' }, + { id: 2, uid: 'b' }, + ]); + }); + + it('loads record by text column', async () => { + const FooByUidLoader = createNodeByIdLoaderClass({ + column: { + name: 'uid', + type: 'text', + }, + query: sql.type( + z.object({ + id: z.number(), + uid: z.string(), + }), + )` + SELECT + * + FROM test_table_foo + `, + }); + const loader = new FooByUidLoader(pool, {}); + const result = await loader.load('b'); + + expect(result).toMatchObject({ id: 2, uid: 'b' }); + }); +}); diff --git a/packages/slonik-dataloaders/src/factories/createNodeByIdLoaderClass.ts b/packages/slonik-dataloaders/src/factories/createNodeByIdLoaderClass.ts new file mode 100644 index 00000000..f4bafc86 --- /dev/null +++ b/packages/slonik-dataloaders/src/factories/createNodeByIdLoaderClass.ts @@ -0,0 +1,80 @@ +import { snakeCase } from '../utilities/snakeCase'; +import DataLoader from 'dataloader'; +import { + type CommonQueryMethods, + type FragmentSqlToken, + type PrimitiveValueExpression, + type QuerySqlToken, + sql, + type TypeNameIdentifier, +} from 'slonik'; +import { type z, type ZodTypeAny } from 'zod'; + +const TABLE_ALIAS = 't1'; + +export const createNodeByIdLoaderClass = (config: { + column?: { + name?: Extract, string> | undefined; + type?: FragmentSqlToken | TypeNameIdentifier; + }; + columnNameTransformer?: ((column: string) => string) | undefined; + query: QuerySqlToken; +}) => { + const { + column: { name: columnName = 'id', type: columnType = 'int4' } = {}, + columnNameTransformer = snakeCase, + query, + } = config; + + return class NodeLoader extends DataLoader< + PrimitiveValueExpression, + z.infer, + string + > { + public constructor( + pool: CommonQueryMethods, + loaderOptions?: DataLoader.Options< + PrimitiveValueExpression, + z.infer, + string + >, + ) { + super( + async (loaderKeys) => { + const where = sql.fragment`${sql.identifier([ + TABLE_ALIAS, + columnNameTransformer(columnName), + ])} = ANY(${sql.array(loaderKeys, columnType)})`; + + const records = await pool.any( + sql.type(query.parser)` + SELECT * + FROM ( + ${query} + ) ${sql.identifier([TABLE_ALIAS])} + WHERE ${where} + `, + ); + + const recordsByLoaderKey = loaderKeys.map((value) => { + const targetRecord = records.find((record) => { + return String(record[columnName]) === String(value); + }); + + if (targetRecord) { + return targetRecord; + } + + return null; + }); + + return recordsByLoaderKey; + }, + { + ...loaderOptions, + cacheKeyFn: String, + }, + ); + } + }; +}; diff --git a/packages/slonik-dataloaders/src/index.ts b/packages/slonik-dataloaders/src/index.ts new file mode 100644 index 00000000..9d5dfe20 --- /dev/null +++ b/packages/slonik-dataloaders/src/index.ts @@ -0,0 +1,5 @@ +export { createConnectionLoader } from './factories/createConnectionLoader'; +export { createConnectionLoaderClass } from './factories/createConnectionLoaderClass'; +export { createListLoader } from './factories/createListLoader'; +export { createNodeByIdLoader } from './factories/createNodeByIdLoader'; +export { createNodeByIdLoaderClass } from './factories/createNodeByIdLoaderClass'; diff --git a/packages/slonik-dataloaders/src/types.ts b/packages/slonik-dataloaders/src/types.ts new file mode 100644 index 00000000..2690b469 --- /dev/null +++ b/packages/slonik-dataloaders/src/types.ts @@ -0,0 +1,21 @@ +import { type IdentifierSqlToken } from 'slonik'; + +export type OrderDirection = 'ASC' | 'DESC'; + +export type ColumnIdentifiers = Record< + keyof TResult, + IdentifierSqlToken +>; + +type PageInfo = { + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +}; + +export type Connection = { + count: number; + edges: Array; + pageInfo: PageInfo; +}; diff --git a/packages/slonik-dataloaders/src/utilities/fromCursor.ts b/packages/slonik-dataloaders/src/utilities/fromCursor.ts new file mode 100644 index 00000000..2d8d1c89 --- /dev/null +++ b/packages/slonik-dataloaders/src/utilities/fromCursor.ts @@ -0,0 +1,5 @@ +import { type QueryResultRowColumn } from 'slonik'; + +export const fromCursor = (cursor: string): QueryResultRowColumn[] => { + return JSON.parse(Buffer.from(cursor, 'base64').toString()); +}; diff --git a/packages/slonik-dataloaders/src/utilities/getColumnIdentifiers.ts b/packages/slonik-dataloaders/src/utilities/getColumnIdentifiers.ts new file mode 100644 index 00000000..a83b1f4c --- /dev/null +++ b/packages/slonik-dataloaders/src/utilities/getColumnIdentifiers.ts @@ -0,0 +1,15 @@ +import { snakeCase } from './snakeCase'; +import { type IdentifierSqlToken, sql } from 'slonik'; + +export const getColumnIdentifiers = ( + tableAlias: string, + columnNameTransformer: (column: string) => string = snakeCase, +) => { + return new Proxy( + {}, + { + get: (_target, property: string) => + sql.identifier([tableAlias, columnNameTransformer(property)]), + }, + ) as Record; +}; diff --git a/packages/slonik-dataloaders/src/utilities/getRequestedFields.ts b/packages/slonik-dataloaders/src/utilities/getRequestedFields.ts new file mode 100644 index 00000000..03fa6046 --- /dev/null +++ b/packages/slonik-dataloaders/src/utilities/getRequestedFields.ts @@ -0,0 +1,47 @@ +import { + type FragmentDefinitionNode, + type GraphQLResolveInfo, + type SelectionSetNode, +} from 'graphql'; + +const addFieldNamesFromSelectionSet = ( + fieldNames: Set, + selectionSet: SelectionSetNode, + fragments: { [key: string]: FragmentDefinitionNode }, +): void => { + for (const selection of selectionSet.selections) { + if (selection.kind === 'FragmentSpread') { + addFieldNamesFromSelectionSet( + fieldNames, + fragments[selection.name.value].selectionSet, + fragments, + ); + } else if (selection.kind === 'InlineFragment') { + addFieldNamesFromSelectionSet( + fieldNames, + selection.selectionSet, + fragments, + ); + } else { + fieldNames.add(selection.name.value); + } + } +}; + +export const getRequestedFields = ( + info: Pick, +): Set => { + const fieldNames = new Set(); + + for (const fieldNode of info.fieldNodes) { + if (fieldNode.selectionSet) { + addFieldNamesFromSelectionSet( + fieldNames, + fieldNode.selectionSet, + info.fragments, + ); + } + } + + return fieldNames; +}; diff --git a/packages/slonik-dataloaders/src/utilities/snakeCase.ts b/packages/slonik-dataloaders/src/utilities/snakeCase.ts new file mode 100644 index 00000000..08f39355 --- /dev/null +++ b/packages/slonik-dataloaders/src/utilities/snakeCase.ts @@ -0,0 +1,36 @@ +/** + * Adopted from https://npmjs.com/snake-case + */ + +// Regexps involved with splitting words in various case formats. +const SPLIT_LOWER_UPPER_RE = /([\p{Ll}\d])(\p{Lu})/gu; +const SPLIT_UPPER_UPPER_RE = /(\p{Lu})(\p{Lu}\p{Ll})/gu; +// Regexp involved with stripping non-word characters from the result. +const DEFAULT_STRIP_REGEXP = /[^\p{L}\d]+/giu; +// The replacement value for splits. +const SPLIT_REPLACE_VALUE = '$1\0$2'; + +/** + * Split any cased input strings into an array of words. + */ +const split = (input: string): string[] => { + let result = input + .replaceAll(SPLIT_LOWER_UPPER_RE, SPLIT_REPLACE_VALUE) + .replaceAll(SPLIT_UPPER_UPPER_RE, SPLIT_REPLACE_VALUE); + + result = result.replaceAll(DEFAULT_STRIP_REGEXP, '\0'); + let start = 0; + let end = result.length; + // Trim the delimiter from around the output string. + while (result.charAt(start) === '\0') start++; + if (start === end) return []; + while (result.charAt(end - 1) === '\0') end--; + // Transform each token independently. + return result.slice(start, end).split(/\0/gu); +}; + +export const snakeCase = (input: string) => { + return split(input) + .map((fragment) => fragment.toLowerCase()) + .join('_'); +}; diff --git a/packages/slonik-dataloaders/src/utilities/toCursor.ts b/packages/slonik-dataloaders/src/utilities/toCursor.ts new file mode 100644 index 00000000..9de65914 --- /dev/null +++ b/packages/slonik-dataloaders/src/utilities/toCursor.ts @@ -0,0 +1,5 @@ +import { type QueryResultRowColumn } from 'slonik'; + +export const toCursor = (ids: QueryResultRowColumn[]): string => { + return Buffer.from(JSON.stringify(ids)).toString('base64'); +}; diff --git a/packages/slonik-dataloaders/tsconfig.json b/packages/slonik-dataloaders/tsconfig.json new file mode 100644 index 00000000..cefba6aa --- /dev/null +++ b/packages/slonik-dataloaders/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "declaration": true, + "declarationMap": true, + "esModuleInterop": true, + "lib": [ + "es2021" + ], + "module": "commonjs", + "moduleResolution": "node", + "noImplicitAny": false, + "noImplicitReturns": true, + "outDir": "dist", + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "target": "es2020", + "useUnknownInCatchVariables": false + }, + "include": [ + "src" + ] +} \ No newline at end of file From f7b7c439936d4aef79bb1e13718a687366f1034a Mon Sep 17 00:00:00 2001 From: Gajus Date: Thu, 9 May 2024 14:39:56 -0700 Subject: [PATCH 02/22] refactor: port slonik-dataloaders --- .changeset/tame-lizards-punch.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/tame-lizards-punch.md diff --git a/.changeset/tame-lizards-punch.md b/.changeset/tame-lizards-punch.md new file mode 100644 index 00000000..1fcbe442 --- /dev/null +++ b/.changeset/tame-lizards-punch.md @@ -0,0 +1,5 @@ +--- +"@slonik/dataloaders": minor +--- + +porting slonik-dataloaders to Slonik monorepo as @slonik/dataloaders From d4e6b9b3299514fc523a6d60e868c43b775ee9ce Mon Sep 17 00:00:00 2001 From: Gajus Date: Thu, 9 May 2024 14:41:18 -0700 Subject: [PATCH 03/22] refactor: port slonik-dataloaders --- .changeset/tame-lizards-punch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/tame-lizards-punch.md b/.changeset/tame-lizards-punch.md index 1fcbe442..33d5f482 100644 --- a/.changeset/tame-lizards-punch.md +++ b/.changeset/tame-lizards-punch.md @@ -2,4 +2,4 @@ "@slonik/dataloaders": minor --- -porting slonik-dataloaders to Slonik monorepo as @slonik/dataloaders +Porting [slonik-dataloaders](https://github.com/danielrearden/slonik-dataloaders) to Slonik monorepo as @slonik/dataloaders. \ No newline at end of file From e8c188fff8ea25a8077a8d7f035d5fc03ee525f6 Mon Sep 17 00:00:00 2001 From: Gajus Date: Thu, 9 May 2024 14:42:27 -0700 Subject: [PATCH 04/22] refactor: port slonik-dataloaders --- packages/slonik-dataloaders/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/slonik-dataloaders/package.json b/packages/slonik-dataloaders/package.json index 92556103..5a8df683 100644 --- a/packages/slonik-dataloaders/package.json +++ b/packages/slonik-dataloaders/package.json @@ -9,7 +9,7 @@ "graphql": "^16.8.1", "zod": "^3.23.8" }, - "description": "Logs Slonik queries.", + "description": "Utilities for creating DataLoaders using Slonik.", "devDependencies": { "eslint": "^8.57.0", "eslint-config-canonical": "^42.8.1", From fd0c3705b920c8ff71adc083abeed3f894e488b3 Mon Sep 17 00:00:00 2001 From: Gajus Date: Thu, 9 May 2024 14:42:58 -0700 Subject: [PATCH 05/22] refactor: port slonik-dataloaders --- .changeset/tame-lizards-punch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/tame-lizards-punch.md b/.changeset/tame-lizards-punch.md index 33d5f482..62a76699 100644 --- a/.changeset/tame-lizards-punch.md +++ b/.changeset/tame-lizards-punch.md @@ -2,4 +2,4 @@ "@slonik/dataloaders": minor --- -Porting [slonik-dataloaders](https://github.com/danielrearden/slonik-dataloaders) to Slonik monorepo as @slonik/dataloaders. \ No newline at end of file +Porting @danielrearden's [slonik-dataloaders](https://github.com/danielrearden/slonik-dataloaders) to Slonik monorepo as @slonik/dataloaders. \ No newline at end of file From d8be3686f86df94af8c12218060175d8227e4474 Mon Sep 17 00:00:00 2001 From: Gajus Date: Mon, 13 May 2024 10:34:25 -0600 Subject: [PATCH 06/22] refactor test setup --- .../createConnectionLoaderClass.test.ts | 159 +++++++++--------- 1 file changed, 76 insertions(+), 83 deletions(-) diff --git a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts index cc0adacf..7c1e8712 100644 --- a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts +++ b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts @@ -31,16 +31,20 @@ const BarConnectionLoader = createConnectionLoaderClass({ query: sql.type( z.object({ id: z.number(), + name: z.string(), uid: z.string(), - value: z.string(), }), )` SELECT - * - FROM test_table_bar + id, + uid, + name + FROM person `, }); +const getNodeIds = (edges) => edges.map(({ node }) => node.id); + describe('createConnectionLoaderClass', () => { let pool: DatabasePool; @@ -48,33 +52,34 @@ describe('createConnectionLoaderClass', () => { pool = await createPool(POSTGRES_DSN); await pool.query(sql.unsafe` - CREATE TABLE IF NOT EXISTS test_table_bar ( + CREATE TABLE IF NOT EXISTS person ( id integer NOT NULL PRIMARY KEY, uid text NOT NULL, - value text NOT NULL + name text NOT NULL ); `); await pool.query(sql.unsafe` - INSERT INTO test_table_bar - (id, uid, value) + INSERT INTO person + (id, uid, name) VALUES - (1, 'z', 'aaa'), - (2, 'y', 'aaa'), - (3, 'x', 'bbb'), - (4, 'w', 'bbb'), - (5, 'v', 'ccc'), - (6, 'u', 'ccc'), - (7, 't', 'ddd'), - (8, 's', 'ddd'), - (9, 'r', 'eee'); + (1, 'a', 'aaa'), + (2, 'b', 'aaa'), + (3, 'c', 'bbb'), + (4, 'd', 'bbb'), + (5, 'e', 'ccc'), + (6, 'f', 'ccc'), + (7, 'g', 'ddd'), + (8, 'h', 'ddd'), + (9, 'i', 'eee'), + (10, 'j', 'eee'); `); }); afterAll(async () => { if (pool) { await pool.query(sql.unsafe` - DROP TABLE IF EXISTS test_table_bar; + DROP TABLE IF EXISTS person; `); await pool.end(); @@ -87,13 +92,13 @@ describe('createConnectionLoaderClass', () => { expect(result).toMatchObject({ pageInfo: { - endCursor: result.edges[8].cursor, + endCursor: result.edges[9].cursor, hasNextPage: false, hasPreviousPage: false, startCursor: result.edges[0].cursor, }, }); - expect(result.edges).toHaveLength(9); + expect(result.edges).toHaveLength(10); }); it('loads records in ascending order', async () => { @@ -102,8 +107,8 @@ describe('createConnectionLoaderClass', () => { orderBy: ({ uid }) => [[uid, 'ASC']], }); - expect(result.edges[0].node.id).toEqual(9); - expect(result.edges[8].node.id).toEqual(1); + expect(result.edges[0].node.id).toEqual(1); + expect(result.edges[9].node.id).toEqual(10); }); it('loads records in descending order', async () => { @@ -112,21 +117,20 @@ describe('createConnectionLoaderClass', () => { orderBy: ({ uid }) => [[uid, 'DESC']], }); - expect(result.edges[0].node.id).toEqual(1); - expect(result.edges[8].node.id).toEqual(9); + expect(result.edges[0].node.id).toEqual(10); + expect(result.edges[9].node.id).toEqual(1); }); it('loads records with multiple order by expressions', async () => { const loader = new BarConnectionLoader(pool, {}); const result = await loader.load({ - orderBy: ({ uid, value }) => [ - [value, 'DESC'], + orderBy: ({ uid, name }) => [ + [name, 'ASC'], [uid, 'DESC'], ], }); - expect(result.edges[0].node.id).toEqual(9); - expect(result.edges[8].node.id).toEqual(2); + expect(getNodeIds(result.edges)).toEqual([2, 1, 4, 3, 6, 5, 8, 7, 10, 9]); }); it('loads records with complex order by expression', async () => { @@ -135,18 +139,26 @@ describe('createConnectionLoaderClass', () => { orderBy: ({ uid }) => [[sql.fragment`upper(${uid})`, 'ASC']], }); - expect(result.edges[0].node.id).toEqual(9); - expect(result.edges[8].node.id).toEqual(1); + expect(getNodeIds(result.edges)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); }); it('loads records with where expression', async () => { const loader = new BarConnectionLoader(pool, {}); const result = await loader.load({ - where: ({ value }) => sql.fragment`upper(${value}) = 'EEE'`, + where: ({ name }) => sql.fragment`upper(${name}) = 'EEE'`, + }); + + expect(getNodeIds(result.edges)).toEqual([9, 10]); + }); + + it('loads records with limit', async () => { + const loader = new BarConnectionLoader(pool, {}); + const result = await loader.load({ + limit: 4, + orderBy: ({ uid }) => [[uid, 'ASC']], }); - expect(result.edges).toHaveLength(1); - expect(result.edges[0].node.id).toEqual(9); + expect(getNodeIds(result.edges)).toEqual([1, 2, 3, 4]); }); it('paginates through the records forwards', async () => { @@ -156,9 +168,7 @@ describe('createConnectionLoaderClass', () => { orderBy: ({ uid }) => [[uid, 'ASC']], }); - expect(firstResult.edges).toHaveLength(4); - expect(firstResult.edges[0].node.id).toEqual(9); - expect(firstResult.edges[3].node.id).toEqual(6); + expect(getNodeIds(firstResult.edges)).toEqual([1, 2, 3, 4]); expect(firstResult.pageInfo).toMatchObject({ hasNextPage: true, hasPreviousPage: false, @@ -170,9 +180,7 @@ describe('createConnectionLoaderClass', () => { orderBy: ({ uid }) => [[uid, 'ASC']], }); - expect(secondResult.edges).toHaveLength(4); - expect(secondResult.edges[0].node.id).toEqual(5); - expect(secondResult.edges[3].node.id).toEqual(2); + expect(getNodeIds(secondResult.edges)).toEqual([5, 6, 7, 8]); expect(secondResult.pageInfo).toMatchObject({ hasNextPage: true, hasPreviousPage: true, @@ -184,8 +192,7 @@ describe('createConnectionLoaderClass', () => { orderBy: ({ uid }) => [[uid, 'ASC']], }); - expect(thirdResult.edges).toHaveLength(1); - expect(thirdResult.edges[0].node.id).toEqual(1); + expect(getNodeIds(thirdResult.edges)).toEqual([9, 10]); expect(thirdResult.pageInfo).toMatchObject({ hasNextPage: false, hasPreviousPage: true, @@ -197,7 +204,7 @@ describe('createConnectionLoaderClass', () => { orderBy: ({ uid }) => [[uid, 'ASC']], }); - expect(fourthResult.edges).toHaveLength(0); + expect(getNodeIds(fourthResult.edges)).toEqual([]); expect(fourthResult.pageInfo).toMatchObject({ hasNextPage: false, hasPreviousPage: true, @@ -208,16 +215,11 @@ describe('createConnectionLoaderClass', () => { const loader = new BarConnectionLoader(pool, {}); const firstResult = await loader.load({ limit: 4, - orderBy: ({ value, uid }) => [ - [value, 'ASC'], - [uid, 'ASC'], - ], + orderBy: ({ uid }) => [[uid, 'ASC']], reverse: true, }); - expect(firstResult.edges).toHaveLength(4); - expect(firstResult.edges[0].node.id).toEqual(5); - expect(firstResult.edges[3].node.id).toEqual(9); + expect(getNodeIds(firstResult.edges)).toEqual([7, 8, 9, 10]); expect(firstResult.pageInfo).toMatchObject({ hasNextPage: false, hasPreviousPage: true, @@ -226,16 +228,11 @@ describe('createConnectionLoaderClass', () => { const secondResult = await loader.load({ cursor: firstResult.pageInfo.startCursor, limit: 4, - orderBy: ({ value, uid }) => [ - [value, 'ASC'], - [uid, 'ASC'], - ], + orderBy: ({ uid }) => [[uid, 'ASC']], reverse: true, }); - expect(secondResult.edges).toHaveLength(4); - expect(secondResult.edges[0].node.id).toEqual(1); - expect(secondResult.edges[3].node.id).toEqual(6); + expect(getNodeIds(secondResult.edges)).toEqual([3, 4, 5, 6]); expect(secondResult.pageInfo).toMatchObject({ hasNextPage: true, hasPreviousPage: true, @@ -244,15 +241,11 @@ describe('createConnectionLoaderClass', () => { const thirdResult = await loader.load({ cursor: secondResult.pageInfo.startCursor, limit: 4, - orderBy: ({ value, uid }) => [ - [value, 'ASC'], - [uid, 'ASC'], - ], + orderBy: ({ uid }) => [[uid, 'ASC']], reverse: true, }); - expect(thirdResult.edges).toHaveLength(1); - expect(thirdResult.edges[0].node.id).toEqual(2); + expect(getNodeIds(thirdResult.edges)).toEqual([1, 2]); expect(thirdResult.pageInfo).toMatchObject({ hasNextPage: true, hasPreviousPage: false, @@ -261,14 +254,11 @@ describe('createConnectionLoaderClass', () => { const fourthResult = await loader.load({ cursor: thirdResult.pageInfo.startCursor, limit: 4, - orderBy: ({ value, uid }) => [ - [value, 'ASC'], - [uid, 'ASC'], - ], + orderBy: ({ uid }) => [[uid, 'ASC']], reverse: true, }); - expect(fourthResult.edges).toHaveLength(0); + expect(getNodeIds(fourthResult.edges)).toEqual([]); expect(fourthResult.pageInfo).toMatchObject({ hasNextPage: true, hasPreviousPage: false, @@ -278,7 +268,9 @@ describe('createConnectionLoaderClass', () => { it('batches loaded records', async () => { const loader = new BarConnectionLoader(pool, {}); const poolAnySpy = vi.spyOn(pool, 'any'); + poolAnySpy.mockClear(); + const results = await Promise.all([ loader.load({ orderBy: ({ uid }) => [[uid, 'ASC']], @@ -289,10 +281,13 @@ describe('createConnectionLoaderClass', () => { ]); expect(poolAnySpy).toHaveBeenCalledTimes(2); - expect(results[0].edges[0].node.id).toEqual(9); - expect(results[0].edges[8].node.id).toEqual(1); - expect(results[1].edges[0].node.id).toEqual(1); - expect(results[1].edges[8].node.id).toEqual(9); + + expect(getNodeIds(results[0].edges)).toEqual([ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + ]); + expect(getNodeIds(results[1].edges)).toEqual([ + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, + ]); }); it('caches loaded records', async () => { @@ -307,10 +302,8 @@ describe('createConnectionLoaderClass', () => { }); expect(poolAnySpy).toHaveBeenCalledTimes(2); - expect(resultsA.edges[0].node.id).toEqual(9); - expect(resultsA.edges[8].node.id).toEqual(1); - expect(resultsB.edges[0].node.id).toEqual(9); - expect(resultsB.edges[8].node.id).toEqual(1); + expect(getNodeIds(resultsA.edges)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + expect(getNodeIds(resultsB.edges)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); }); it('gets the count', async () => { @@ -318,16 +311,16 @@ describe('createConnectionLoaderClass', () => { const results = await Promise.all([ loader.load({ info: getInfo(['edges', 'count']), - where: ({ value }) => sql.fragment`upper(${value}) = 'CCC'`, + where: ({ name }) => sql.fragment`upper(${name}) = 'CCC'`, }), loader.load({ info: getInfo(['edges', 'count']), - where: ({ value }) => sql.fragment`upper(${value}) = 'EEE'`, + where: ({ name }) => sql.fragment`upper(${name}) = 'EEE'`, }), ]); expect(results[0].count).toEqual(2n); - expect(results[1].count).toEqual(1n); + expect(results[1].count).toEqual(2n); }); it('gets the count without fetching edges', async () => { @@ -335,17 +328,17 @@ describe('createConnectionLoaderClass', () => { const results = await Promise.all([ loader.load({ info: getInfo(['count']), - where: ({ value }) => sql.fragment`upper(${value}) = 'CCC'`, + where: ({ name }) => sql.fragment`upper(${name}) = 'CCC'`, }), loader.load({ info: getInfo(['count']), - where: ({ value }) => sql.fragment`upper(${value}) = 'EEE'`, + where: ({ name }) => sql.fragment`upper(${name}) = 'EEE'`, }), ]); expect(results[0].count).toEqual(2n); expect(results[0].edges.length).toEqual(0); - expect(results[1].count).toEqual(1n); + expect(results[1].count).toEqual(2n); expect(results[1].edges.length).toEqual(0); }); @@ -354,17 +347,17 @@ describe('createConnectionLoaderClass', () => { const results = await Promise.all([ loader.load({ info: getInfo(['edges']), - where: ({ value }) => sql.fragment`upper(${value}) = 'CCC'`, + where: ({ name }) => sql.fragment`upper(${name}) = 'CCC'`, }), loader.load({ info: getInfo(['pageInfo']), - where: ({ value }) => sql.fragment`upper(${value}) = 'EEE'`, + where: ({ name }) => sql.fragment`upper(${name}) = 'EEE'`, }), ]); expect(results[0].count).toEqual(0); expect(results[0].edges.length).toEqual(2); expect(results[1].count).toEqual(0); - expect(results[1].edges.length).toEqual(1); + expect(results[1].edges.length).toEqual(2); }); }); From 5ec9156b220f5c85292ba1c0e1feedae9bcbb53c Mon Sep 17 00:00:00 2001 From: Gajus Date: Mon, 13 May 2024 10:44:53 -0600 Subject: [PATCH 07/22] add offset --- .../src/factories/createConnectionLoaderClass.test.ts | 11 +++++++++++ .../src/factories/createConnectionLoaderClass.ts | 6 +++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts index 7c1e8712..bffd6e32 100644 --- a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts +++ b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts @@ -161,6 +161,17 @@ describe('createConnectionLoaderClass', () => { expect(getNodeIds(result.edges)).toEqual([1, 2, 3, 4]); }); + it('loads records with limit and offset', async () => { + const loader = new BarConnectionLoader(pool, {}); + const result = await loader.load({ + limit: 4, + offset: 4, + orderBy: ({ uid }) => [[uid, 'ASC']], + }); + + expect(getNodeIds(result.edges)).toEqual([5, 6, 7, 8]); + }); + it('paginates through the records forwards', async () => { const loader = new BarConnectionLoader(pool, {}); const firstResult = await loader.load({ diff --git a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts index 621dfa7a..6477a469 100644 --- a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts +++ b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts @@ -22,6 +22,7 @@ type DataLoaderKey = { cursor?: string | null; info?: Pick; limit?: number | null; + offset?: number | null; orderBy?: ( identifiers: ColumnIdentifiers, ) => Array<[SqlToken, OrderDirection]>; @@ -65,6 +66,7 @@ export const createConnectionLoaderClass = (config: { cursor, info, limit, + offset, orderBy, reverse = false, where, @@ -183,6 +185,7 @@ export const createConnectionLoaderClass = (config: { WHERE ${whereExpression} ${orderByClause} LIMIT ${limit ? limit + 1 : null} + OFFSET ${offset || 0} )`, ); } @@ -293,6 +296,7 @@ export const createConnectionLoaderClass = (config: { cursor, info, limit, + offset, orderBy, reverse = false, where, @@ -301,7 +305,7 @@ export const createConnectionLoaderClass = (config: { ? getRequestedFields(info) : new Set(['pageInfo', 'edges']); - return `${cursor}|${reverse}|${limit}|${JSON.stringify( + return `${cursor}|${reverse}|${limit}|${offset}|${JSON.stringify( orderBy?.(columnIdentifiers), )}|${JSON.stringify( where?.(columnIdentifiers), From 8fa2e916fcf9c5e77c0e18f4c5d3bbef7cb07e07 Mon Sep 17 00:00:00 2001 From: Gajus Date: Mon, 13 May 2024 10:47:58 -0600 Subject: [PATCH 08/22] refactor test setup --- .../createConnectionLoaderClass.test.ts | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts index bffd6e32..9e04b1d7 100644 --- a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts +++ b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts @@ -27,7 +27,7 @@ const getInfo = ( }; }; -const BarConnectionLoader = createConnectionLoaderClass({ +const PersonConnectionLoader = createConnectionLoaderClass({ query: sql.type( z.object({ id: z.number(), @@ -87,7 +87,7 @@ describe('createConnectionLoaderClass', () => { }); it('loads all records with no additional options', async () => { - const loader = new BarConnectionLoader(pool, {}); + const loader = new PersonConnectionLoader(pool, {}); const result = await loader.load({}); expect(result).toMatchObject({ @@ -102,7 +102,7 @@ describe('createConnectionLoaderClass', () => { }); it('loads records in ascending order', async () => { - const loader = new BarConnectionLoader(pool, {}); + const loader = new PersonConnectionLoader(pool, {}); const result = await loader.load({ orderBy: ({ uid }) => [[uid, 'ASC']], }); @@ -112,7 +112,7 @@ describe('createConnectionLoaderClass', () => { }); it('loads records in descending order', async () => { - const loader = new BarConnectionLoader(pool, {}); + const loader = new PersonConnectionLoader(pool, {}); const result = await loader.load({ orderBy: ({ uid }) => [[uid, 'DESC']], }); @@ -122,7 +122,7 @@ describe('createConnectionLoaderClass', () => { }); it('loads records with multiple order by expressions', async () => { - const loader = new BarConnectionLoader(pool, {}); + const loader = new PersonConnectionLoader(pool, {}); const result = await loader.load({ orderBy: ({ uid, name }) => [ [name, 'ASC'], @@ -134,7 +134,7 @@ describe('createConnectionLoaderClass', () => { }); it('loads records with complex order by expression', async () => { - const loader = new BarConnectionLoader(pool, {}); + const loader = new PersonConnectionLoader(pool, {}); const result = await loader.load({ orderBy: ({ uid }) => [[sql.fragment`upper(${uid})`, 'ASC']], }); @@ -143,7 +143,7 @@ describe('createConnectionLoaderClass', () => { }); it('loads records with where expression', async () => { - const loader = new BarConnectionLoader(pool, {}); + const loader = new PersonConnectionLoader(pool, {}); const result = await loader.load({ where: ({ name }) => sql.fragment`upper(${name}) = 'EEE'`, }); @@ -152,7 +152,7 @@ describe('createConnectionLoaderClass', () => { }); it('loads records with limit', async () => { - const loader = new BarConnectionLoader(pool, {}); + const loader = new PersonConnectionLoader(pool, {}); const result = await loader.load({ limit: 4, orderBy: ({ uid }) => [[uid, 'ASC']], @@ -162,7 +162,7 @@ describe('createConnectionLoaderClass', () => { }); it('loads records with limit and offset', async () => { - const loader = new BarConnectionLoader(pool, {}); + const loader = new PersonConnectionLoader(pool, {}); const result = await loader.load({ limit: 4, offset: 4, @@ -173,7 +173,7 @@ describe('createConnectionLoaderClass', () => { }); it('paginates through the records forwards', async () => { - const loader = new BarConnectionLoader(pool, {}); + const loader = new PersonConnectionLoader(pool, {}); const firstResult = await loader.load({ limit: 4, orderBy: ({ uid }) => [[uid, 'ASC']], @@ -223,7 +223,7 @@ describe('createConnectionLoaderClass', () => { }); it('paginates through the records backwards', async () => { - const loader = new BarConnectionLoader(pool, {}); + const loader = new PersonConnectionLoader(pool, {}); const firstResult = await loader.load({ limit: 4, orderBy: ({ uid }) => [[uid, 'ASC']], @@ -277,7 +277,7 @@ describe('createConnectionLoaderClass', () => { }); it('batches loaded records', async () => { - const loader = new BarConnectionLoader(pool, {}); + const loader = new PersonConnectionLoader(pool, {}); const poolAnySpy = vi.spyOn(pool, 'any'); poolAnySpy.mockClear(); @@ -302,7 +302,7 @@ describe('createConnectionLoaderClass', () => { }); it('caches loaded records', async () => { - const loader = new BarConnectionLoader(pool, {}); + const loader = new PersonConnectionLoader(pool, {}); const poolAnySpy = vi.spyOn(pool, 'any'); poolAnySpy.mockClear(); const resultsA = await loader.load({ @@ -318,7 +318,7 @@ describe('createConnectionLoaderClass', () => { }); it('gets the count', async () => { - const loader = new BarConnectionLoader(pool, {}); + const loader = new PersonConnectionLoader(pool, {}); const results = await Promise.all([ loader.load({ info: getInfo(['edges', 'count']), @@ -335,7 +335,7 @@ describe('createConnectionLoaderClass', () => { }); it('gets the count without fetching edges', async () => { - const loader = new BarConnectionLoader(pool, {}); + const loader = new PersonConnectionLoader(pool, {}); const results = await Promise.all([ loader.load({ info: getInfo(['count']), @@ -354,7 +354,7 @@ describe('createConnectionLoaderClass', () => { }); it('gets the edges without fetching edges', async () => { - const loader = new BarConnectionLoader(pool, {}); + const loader = new PersonConnectionLoader(pool, {}); const results = await Promise.all([ loader.load({ info: getInfo(['edges']), From fb642f5aaa03e9436fc40623728b2f9fe43574f5 Mon Sep 17 00:00:00 2001 From: Gajus Date: Mon, 13 May 2024 10:53:58 -0600 Subject: [PATCH 09/22] feat: utilize separate queries for connection loader --- .../createConnectionLoaderClass.test.ts | 4 +- .../factories/createConnectionLoaderClass.ts | 116 +++++++----------- 2 files changed, 47 insertions(+), 73 deletions(-) diff --git a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts index 9e04b1d7..2f2dd896 100644 --- a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts +++ b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts @@ -305,6 +305,7 @@ describe('createConnectionLoaderClass', () => { const loader = new PersonConnectionLoader(pool, {}); const poolAnySpy = vi.spyOn(pool, 'any'); poolAnySpy.mockClear(); + const poolOneFirstSpy = vi.spyOn(pool, 'oneFirst'); const resultsA = await loader.load({ orderBy: ({ uid }) => [[uid, 'ASC']], }); @@ -312,7 +313,8 @@ describe('createConnectionLoaderClass', () => { orderBy: ({ uid }) => [[uid, 'ASC']], }); - expect(poolAnySpy).toHaveBeenCalledTimes(2); + expect(poolAnySpy).toHaveBeenCalledTimes(1); + expect(poolOneFirstSpy).toHaveBeenCalledTimes(1); expect(getNodeIds(resultsA.edges)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); expect(getNodeIds(resultsB.edges)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); }); diff --git a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts index 6477a469..2517ac4e 100644 --- a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts +++ b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts @@ -16,7 +16,7 @@ import { sql, type SqlToken, } from 'slonik'; -import { type AnyZodObject, z, type ZodTypeAny } from 'zod'; +import { z, type ZodTypeAny } from 'zod'; type DataLoaderKey = { cursor?: string | null; @@ -61,7 +61,7 @@ export const createConnectionLoaderClass = (config: { const edgesQueries: QuerySqlToken[] = []; const countQueries: QuerySqlToken[] = []; - for (const [index, loaderKey] of loaderKeys.entries()) { + for (const loaderKey of loaderKeys.values()) { const { cursor, info, @@ -80,18 +80,11 @@ export const createConnectionLoaderClass = (config: { const conditions: SqlToken[] = where ? [sql.fragment`(${where(columnIdentifiers)})`] : []; - const queryKey = String(index); - - const selectExpressions = [sql.fragment`${queryKey} "key"`]; if (requestedFields.has('count')) { countQueries.push( sql.unsafe`( - SELECT - ${sql.join( - [...selectExpressions, sql.fragment`count(*) count`], - sql.fragment`, `, - )} + SELECT count(*) count FROM ( ${query} ) ${sql.identifier([TABLE_ALIAS])} @@ -114,7 +107,7 @@ export const createConnectionLoaderClass = (config: { const orderByExpressions: Array<[SqlToken, OrderDirection]> = orderBy ? orderBy(columnIdentifiers) : []; - selectExpressions.push( + const selectExpressions = [ sql.fragment`${sql.identifier([TABLE_ALIAS])}.*`, sql.fragment`json_build_array(${ orderByExpressions.length @@ -124,7 +117,7 @@ export const createConnectionLoaderClass = (config: { ) : sql.fragment`` }) ${sql.identifier([SORT_COLUMN_ALIAS])}`, - ); + ]; const orderByClause = orderByExpressions.length ? sql.fragment`ORDER BY ${sql.join( @@ -191,73 +184,55 @@ export const createConnectionLoaderClass = (config: { } } - const parser = query.parser as unknown as AnyZodObject; + if (!(query.parser instanceof z.ZodObject)) { + throw new TypeError( + 'Invalid query parser. Provided schema must be a ZodObject.', + ); + } - const extendedParser = - // @ts-expect-error Accessing internal property to determine if parser is an instance of z.any() - parser._any === true - ? z - .object({ - key: z.union([z.string(), z.number()]), - s1: z.array(z.unknown()), - }) - .passthrough() - : parser.extend({ - key: z.union([z.string(), z.number()]), - s1: z.array(z.unknown()), - }); + const edgeSchema = query.parser.extend({ + [SORT_COLUMN_ALIAS]: z.array(z.any()), + }); + const countSchema = z.object({ + count: z.number(), + }); - const [edgesRecords, countRecords] = await Promise.all([ - edgesQueries.length - ? pool.any( - sql.type(extendedParser)`${sql.join( - edgesQueries, - sql.fragment`UNION ALL`, - )}`, - ) - : [], - countQueries.length - ? pool.any( - sql.unsafe`${sql.join( - countQueries, - sql.fragment`UNION ALL`, - )}`, - ) - : [], + const [edgeResults, countResults] = await Promise.all([ + Promise.all( + edgesQueries.map((query) => { + return pool.any(sql.type(edgeSchema)`${query}`); + }), + ), + Promise.all( + countQueries.map((query) => { + return pool.oneFirst(sql.type(countSchema)`${query}`); + }), + ), ]); const connections = loaderKeys.map((loaderKey, loaderKeyIndex) => { - const queryKey = String(loaderKeyIndex); const { cursor, limit, reverse = false } = loaderKey; - const edges = edgesRecords - .filter((record) => { - return record.key === queryKey; - }) - .map((record) => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { key, ...rest } = record; - const cursorValues: string[] = []; - - let index = 0; - - while (true) { - const value = record[SORT_COLUMN_ALIAS]?.[index]; - if (value === undefined) { - break; - } - - cursorValues.push(value as string); + const edges = (edgeResults[loaderKeyIndex] ?? []).map((record) => { + const cursorValues: string[] = []; + let index = 0; + while (true) { + const value = record[SORT_COLUMN_ALIAS]?.[index]; + if (value === undefined) { + break; + } else { + cursorValues.push(value); index++; } + } - return { - ...rest, - cursor: toCursor(cursorValues), - node: rest, - }; - }); + return { + ...record, + cursor: toCursor(cursorValues), + node: record, + }; + }); const slicedEdges = edges.slice( 0, @@ -276,10 +251,7 @@ export const createConnectionLoaderClass = (config: { startCursor: slicedEdges[0]?.cursor || null, }; - const count = - countRecords.find((record) => { - return record.key === queryKey; - })?.count ?? 0; + const count = countResults[loaderKeyIndex] ?? 0; return { count, From f9780c5f0f1a8b5722273ad3c9651a1874f993d0 Mon Sep 17 00:00:00 2001 From: Gajus Date: Mon, 13 May 2024 10:55:48 -0600 Subject: [PATCH 10/22] remove instanceof check --- .../factories/createConnectionLoaderClass.ts | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts index 2517ac4e..daa1a68d 100644 --- a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts +++ b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts @@ -184,28 +184,27 @@ export const createConnectionLoaderClass = (config: { } } - if (!(query.parser instanceof z.ZodObject)) { - throw new TypeError( - 'Invalid query parser. Provided schema must be a ZodObject.', - ); - } - - const edgeSchema = query.parser.extend({ + let edgeSchema: z.AnyZodObject = z.object({ [SORT_COLUMN_ALIAS]: z.array(z.any()), }); + + if ('extend' in query.parser) { + edgeSchema = edgeSchema.extend(query.parser as any); + } + const countSchema = z.object({ count: z.number(), }); const [edgeResults, countResults] = await Promise.all([ Promise.all( - edgesQueries.map((query) => { - return pool.any(sql.type(edgeSchema)`${query}`); + edgesQueries.map((edgesQuery) => { + return pool.any(sql.type(edgeSchema)`${edgesQuery}`); }), ), Promise.all( - countQueries.map((query) => { - return pool.oneFirst(sql.type(countSchema)`${query}`); + countQueries.map((countQuery) => { + return pool.oneFirst(sql.type(countSchema)`${countQuery}`); }), ), ]); From 55bc3f33731cf3d0db4f4112dac6120ee025a34e Mon Sep 17 00:00:00 2001 From: Gajus Date: Mon, 13 May 2024 10:57:39 -0600 Subject: [PATCH 11/22] remove __typename from edge fields --- .../src/factories/createConnectionLoaderClass.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts index daa1a68d..0e2b2bb5 100644 --- a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts +++ b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts @@ -216,6 +216,7 @@ export const createConnectionLoaderClass = (config: { const cursorValues: string[] = []; let index = 0; + while (true) { const value = record[SORT_COLUMN_ALIAS]?.[index]; if (value === undefined) { @@ -226,8 +227,14 @@ export const createConnectionLoaderClass = (config: { } } + // TODO add a test for this + // Strip out `__typename`, otherwise if the connection object is returned inside a resolver, + // GraphQL will throw an error because the typename won't match the edge type + // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/naming-convention + const { __typename, ...edgeFields } = record; + return { - ...record, + ...edgeFields, cursor: toCursor(cursorValues), node: record, }; From 7cbfb0a5d0a6a1ff555e65f7fa47951d8e6cb741 Mon Sep 17 00:00:00 2001 From: Gajus Date: Mon, 13 May 2024 11:02:56 -0600 Subject: [PATCH 12/22] support validation --- .../createConnectionLoaderClass.test.ts | 96 ++++++++++++++++++- .../factories/createConnectionLoaderClass.ts | 16 ++-- 2 files changed, 105 insertions(+), 7 deletions(-) diff --git a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts index 2f2dd896..a87452ea 100644 --- a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts +++ b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts @@ -1,11 +1,18 @@ import { createConnectionLoaderClass } from './createConnectionLoaderClass'; +import { type QueryResultRow } from '@slonik/types'; import { type FieldNode, type GraphQLResolveInfo, type OperationDefinitionNode, parse, } from 'graphql'; -import { createPool, type DatabasePool, sql } from 'slonik'; +import { + createPool, + type DatabasePool, + type Interceptor, + SchemaValidationError, + sql, +} from 'slonik'; import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'; import { z } from 'zod'; @@ -374,3 +381,90 @@ describe('createConnectionLoaderClass', () => { expect(results[1].edges.length).toEqual(2); }); }); + +describe('createConnectionLoaderClass (with validation)', () => { + let pool: DatabasePool; + + beforeAll(async () => { + const createResultParserInterceptor = (): Interceptor => { + return { + transformRow: (executionContext, actualQuery, row) => { + const { resultParser } = executionContext; + + // @ts-expect-error _any is not exposed through the zod typings, but does exist on ZodTypeAny + if (!resultParser || resultParser._any) { + return row; + } + + const validationResult = resultParser.safeParse(row); + + if (validationResult.success !== true) { + throw new SchemaValidationError( + actualQuery, + row, + validationResult.error.issues, + ); + } + + return validationResult.data as QueryResultRow; + }, + }; + }; + + pool = await createPool(POSTGRES_DSN, { + interceptors: [createResultParserInterceptor()], + }); + + await pool.query(sql.unsafe` + CREATE TABLE IF NOT EXISTS person ( + id integer NOT NULL PRIMARY KEY, + uid text NOT NULL, + name text NOT NULL + ); + `); + + await pool.query(sql.unsafe` + INSERT INTO person + (id, uid, name) + VALUES + (1, 'a', 'aaa'), + (2, 'b', 'aaa'), + (3, 'c', 'bbb'), + (4, 'd', 'bbb'), + (5, 'e', 'ccc'), + (6, 'f', 'ccc'), + (7, 'g', 'ddd'), + (8, 'h', 'ddd'), + (9, 'i', 'eee'), + (10, 'j', 'eee'); + `); + }); + + afterAll(async () => { + if (pool) { + await pool.query(sql.unsafe` + DROP TABLE IF EXISTS person; + `); + + await pool.end(); + } + }); + + it('fails with schema validation error', async () => { + const BadConnectionLoader = createConnectionLoaderClass({ + query: sql.type( + z.object({ + id: z.number(), + uid: z.string(), + }), + )` + SELECT + * + FROM person + `, + }); + + const loader = new BadConnectionLoader(pool, {}); + await expect(loader.load({})).rejects.toThrowError(SchemaValidationError); + }); +}); diff --git a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts index 0e2b2bb5..724f5599 100644 --- a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts +++ b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts @@ -184,12 +184,16 @@ export const createConnectionLoaderClass = (config: { } } - let edgeSchema: z.AnyZodObject = z.object({ - [SORT_COLUMN_ALIAS]: z.array(z.any()), - }); - - if ('extend' in query.parser) { - edgeSchema = edgeSchema.extend(query.parser as any); + let edgeSchema: ZodTypeAny = z.any(); + + if ('shape' in query.parser) { + edgeSchema = z + .object({ + [SORT_COLUMN_ALIAS]: z.array(z.any()), + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ...(query.parser as any).shape, + }) + .strict(); } const countSchema = z.object({ From 9d122792a0aa271a8e5348213f3cf96f43fd017c Mon Sep 17 00:00:00 2001 From: Gajus Date: Mon, 13 May 2024 11:12:43 -0600 Subject: [PATCH 13/22] correct linting --- package-lock.json | 1 + packages/slonik-dataloaders/package.json | 1 + packages/slonik-dataloaders/src/factories/createListLoader.ts | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 5964a34e..0ab8fe19 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14493,6 +14493,7 @@ "zod": "^3.23.8" }, "devDependencies": { + "@slonik/types": "^44.0.0", "eslint": "^8.57.0", "eslint-config-canonical": "^42.8.1", "slonik": "^44.0.0", diff --git a/packages/slonik-dataloaders/package.json b/packages/slonik-dataloaders/package.json index 5a8df683..f4b6ea61 100644 --- a/packages/slonik-dataloaders/package.json +++ b/packages/slonik-dataloaders/package.json @@ -11,6 +11,7 @@ }, "description": "Utilities for creating DataLoaders using Slonik.", "devDependencies": { + "@slonik/types": "^44.0.0", "eslint": "^8.57.0", "eslint-config-canonical": "^42.8.1", "slonik": "^44.0.0", diff --git a/packages/slonik-dataloaders/src/factories/createListLoader.ts b/packages/slonik-dataloaders/src/factories/createListLoader.ts index 0695fb69..657b5d06 100644 --- a/packages/slonik-dataloaders/src/factories/createListLoader.ts +++ b/packages/slonik-dataloaders/src/factories/createListLoader.ts @@ -15,7 +15,7 @@ export const createListLoader = ( orderBy?: LoadParameters['orderBy']; where?: LoadParameters['where']; }) => { - const nodes = []; + const nodes: T[] = []; const connection = await loader.load({ orderBy: args.orderBy, From 799d16c16cf1aa761e77bf7bd776106b614eb6ad Mon Sep 17 00:00:00 2001 From: Gajus Date: Mon, 13 May 2024 11:24:00 -0600 Subject: [PATCH 14/22] remove unnecessary upper() --- .../createConnectionLoaderClass.test.ts | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts index a87452ea..808a19ef 100644 --- a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts +++ b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts @@ -143,7 +143,7 @@ describe('createConnectionLoaderClass', () => { it('loads records with complex order by expression', async () => { const loader = new PersonConnectionLoader(pool, {}); const result = await loader.load({ - orderBy: ({ uid }) => [[sql.fragment`upper(${uid})`, 'ASC']], + orderBy: ({ uid }) => [[sql.fragment`${uid}`, 'ASC']], }); expect(getNodeIds(result.edges)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); @@ -152,7 +152,7 @@ describe('createConnectionLoaderClass', () => { it('loads records with where expression', async () => { const loader = new PersonConnectionLoader(pool, {}); const result = await loader.load({ - where: ({ name }) => sql.fragment`upper(${name}) = 'EEE'`, + where: ({ name }) => sql.fragment`${name} = 'eee'`, }); expect(getNodeIds(result.edges)).toEqual([9, 10]); @@ -328,19 +328,12 @@ describe('createConnectionLoaderClass', () => { it('gets the count', async () => { const loader = new PersonConnectionLoader(pool, {}); - const results = await Promise.all([ - loader.load({ - info: getInfo(['edges', 'count']), - where: ({ name }) => sql.fragment`upper(${name}) = 'CCC'`, - }), - loader.load({ - info: getInfo(['edges', 'count']), - where: ({ name }) => sql.fragment`upper(${name}) = 'EEE'`, - }), - ]); + const result = await loader.load({ + info: getInfo(['count']), + where: ({ name }) => sql.fragment`${name} = 'ccc'`, + }); - expect(results[0].count).toEqual(2n); - expect(results[1].count).toEqual(2n); + expect(result.count).toEqual(2n); }); it('gets the count without fetching edges', async () => { @@ -348,11 +341,11 @@ describe('createConnectionLoaderClass', () => { const results = await Promise.all([ loader.load({ info: getInfo(['count']), - where: ({ name }) => sql.fragment`upper(${name}) = 'CCC'`, + where: ({ name }) => sql.fragment`${name} = 'ccc'`, }), loader.load({ info: getInfo(['count']), - where: ({ name }) => sql.fragment`upper(${name}) = 'EEE'`, + where: ({ name }) => sql.fragment`${name} = 'eee'`, }), ]); @@ -367,11 +360,11 @@ describe('createConnectionLoaderClass', () => { const results = await Promise.all([ loader.load({ info: getInfo(['edges']), - where: ({ name }) => sql.fragment`upper(${name}) = 'CCC'`, + where: ({ name }) => sql.fragment`${name} = 'ccc'`, }), loader.load({ info: getInfo(['pageInfo']), - where: ({ name }) => sql.fragment`upper(${name}) = 'EEE'`, + where: ({ name }) => sql.fragment`${name} = 'eee'`, }), ]); From 4b4f40c564982db82ddd76d9210db7f7d527e5d7 Mon Sep 17 00:00:00 2001 From: Gajus Date: Mon, 13 May 2024 11:56:01 -0600 Subject: [PATCH 15/22] correctly serialize Set --- .../src/factories/createConnectionLoaderClass.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts index 724f5599..5dc0b138 100644 --- a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts +++ b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts @@ -287,11 +287,15 @@ export const createConnectionLoaderClass = (config: { ? getRequestedFields(info) : new Set(['pageInfo', 'edges']); - return `${cursor}|${reverse}|${limit}|${offset}|${JSON.stringify( - orderBy?.(columnIdentifiers), - )}|${JSON.stringify( - where?.(columnIdentifiers), - )}|${requestedFields.values()}`; + return JSON.stringify({ + cursor, + limit, + offset, + orderBy: orderBy?.(columnIdentifiers), + requestedFields: Array.from(requestedFields), + reverse, + where: where?.(columnIdentifiers), + }); }, }, ); From d20e2055aebf3676ae1b875c71791fa004287497 Mon Sep 17 00:00:00 2001 From: Gajus Date: Mon, 13 May 2024 12:01:51 -0600 Subject: [PATCH 16/22] handle a mix of requested info --- .../createConnectionLoaderClass.test.ts | 29 +++++++++++++++++++ .../factories/createConnectionLoaderClass.ts | 17 ++++++++--- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts index 808a19ef..63084fa3 100644 --- a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts +++ b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts @@ -337,6 +337,17 @@ describe('createConnectionLoaderClass', () => { }); it('gets the count without fetching edges', async () => { + const loader = new PersonConnectionLoader(pool, {}); + const result = await loader.load({ + info: getInfo(['count']), + where: ({ name }) => sql.fragment`${name} = 'ccc'`, + }); + + expect(result.count).toEqual(2n); + expect(result.edges.length).toEqual(0); + }); + + it('gets the count without fetching edges (batch)', async () => { const loader = new PersonConnectionLoader(pool, {}); const results = await Promise.all([ loader.load({ @@ -355,6 +366,24 @@ describe('createConnectionLoaderClass', () => { expect(results[1].edges.length).toEqual(0); }); + it('gets a mix of count and edges', async () => { + const loader = new PersonConnectionLoader(pool, {}); + + const results = await Promise.all([ + loader.load({ + info: getInfo(['edges']), + where: ({ name }) => sql.fragment`${name} = 'eee'`, + }), + loader.load({ + info: getInfo(['count']), + where: ({ name }) => sql.fragment`${name} = 'eee'`, + }), + ]); + + expect(results[0].count).toEqual(0); + expect(results[1].count).toEqual(2n); + }); + it('gets the edges without fetching edges', async () => { const loader = new PersonConnectionLoader(pool, {}); const results = await Promise.all([ diff --git a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts index 5dc0b138..599e7545 100644 --- a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts +++ b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.ts @@ -38,6 +38,7 @@ export const createConnectionLoaderClass = (config: { query: QuerySqlToken; }) => { const { columnNameTransformer = snakeCase, query } = config; + const columnIdentifiers = getColumnIdentifiers>( TABLE_ALIAS, columnNameTransformer, @@ -58,8 +59,8 @@ export const createConnectionLoaderClass = (config: { ) { super( async (loaderKeys) => { - const edgesQueries: QuerySqlToken[] = []; - const countQueries: QuerySqlToken[] = []; + const edgesQueries: Array = []; + const countQueries: Array = []; for (const loaderKey of loaderKeys.values()) { const { @@ -98,6 +99,8 @@ export const createConnectionLoaderClass = (config: { } )`, ); + } else { + countQueries.push(null); } if ( @@ -181,6 +184,8 @@ export const createConnectionLoaderClass = (config: { OFFSET ${offset || 0} )`, ); + } else { + edgesQueries.push(null); } } @@ -203,12 +208,16 @@ export const createConnectionLoaderClass = (config: { const [edgeResults, countResults] = await Promise.all([ Promise.all( edgesQueries.map((edgesQuery) => { - return pool.any(sql.type(edgeSchema)`${edgesQuery}`); + return edgesQuery === null + ? [] + : pool.any(sql.type(edgeSchema)`${edgesQuery}`); }), ), Promise.all( countQueries.map((countQuery) => { - return pool.oneFirst(sql.type(countSchema)`${countQuery}`); + return countQuery === null + ? 0 + : pool.oneFirst(sql.type(countSchema)`${countQuery}`); }), ), ]); From bafe09667a2cdc1cd1c66e5dd9e977ac389a9c2c Mon Sep 17 00:00:00 2001 From: Gajus Date: Mon, 13 May 2024 12:04:51 -0600 Subject: [PATCH 17/22] fix lock --- package-lock.json | 584 ---------------------------------------------- 1 file changed, 584 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0ab8fe19..5a2cae6e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1310,74 +1310,6 @@ "node": ">=16" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", - "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", - "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", - "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", - "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, "node_modules/@esbuild/darwin-arm64": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", @@ -1395,312 +1327,6 @@ "node": ">=12" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", - "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", - "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", - "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", - "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", - "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", - "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", - "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", - "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", - "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", - "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", - "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", - "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", - "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", - "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", - "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", - "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", - "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", - "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -2519,34 +2145,6 @@ "integrity": "sha512-l3YHBLAol6d/IKnB9LhpD0cEZWAoe3eFKUyTYWmFmCO2Q/WOckxLQAUyMZWwZV2M/m3+4vgRoaolFqaII82/TA==", "dev": true }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz", - "integrity": "sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "peer": true - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.2.tgz", - "integrity": "sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "peer": true - }, "node_modules/@rollup/rollup-darwin-arm64": { "version": "4.17.2", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz", @@ -2561,188 +2159,6 @@ ], "peer": true }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.2.tgz", - "integrity": "sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.2.tgz", - "integrity": "sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.2.tgz", - "integrity": "sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz", - "integrity": "sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz", - "integrity": "sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.2.tgz", - "integrity": "sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.2.tgz", - "integrity": "sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.2.tgz", - "integrity": "sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz", - "integrity": "sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz", - "integrity": "sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.2.tgz", - "integrity": "sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "peer": true - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.2.tgz", - "integrity": "sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "peer": true - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.2.tgz", - "integrity": "sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "peer": true - }, "node_modules/@rushstack/eslint-patch": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.2.tgz", From 91257b605e4d758a028f60b5a9a6c7d703f758e6 Mon Sep 17 00:00:00 2001 From: Gajus Date: Mon, 13 May 2024 12:13:21 -0600 Subject: [PATCH 18/22] fix lock --- package-lock.json | 204 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 166 insertions(+), 38 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5a2cae6e..e0fda590 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13740,22 +13740,22 @@ }, "packages/benchmark": { "name": "@slonik/benchmark", - "version": "44.0.0", + "version": "45.0.0", "dependencies": { "benny": "^3.7.1", "pg": "^8.11.3", "pg-promise": "^11.5.5", "postgres": "^3.4.4", - "slonik": "^44.0.0" + "slonik": "^45.0.0" } }, "packages/driver": { "name": "@slonik/driver", - "version": "44.0.0", + "version": "45.0.0", "license": "BSD-3-Clause", "dependencies": { - "@slonik/types": "^44.0.0", - "@slonik/utilities": "^44.0.0", + "@slonik/types": "^45.0.0", + "@slonik/utilities": "^45.0.0", "roarr": "^7.21.1", "serialize-error": "^8.0.0", "strict-event-emitter-types": "^2.0.0" @@ -13788,10 +13788,10 @@ }, "packages/errors": { "name": "@slonik/errors", - "version": "44.0.0", + "version": "45.0.0", "license": "BSD-3-Clause", "dependencies": { - "@slonik/types": "^44.0.0" + "@slonik/types": "^45.0.0" }, "devDependencies": { "@types/node": "^18.15.3", @@ -13822,14 +13822,14 @@ }, "packages/pg-driver": { "name": "@slonik/pg-driver", - "version": "44.0.0", + "version": "45.0.0", "license": "BSD-3-Clause", "dependencies": { - "@slonik/driver": "^44.0.0", - "@slonik/errors": "^44.0.0", - "@slonik/sql-tag": "^44.0.0", - "@slonik/types": "^44.0.0", - "@slonik/utilities": "^44.0.0", + "@slonik/driver": "^45.0.0", + "@slonik/errors": "^45.0.0", + "@slonik/sql-tag": "^45.0.0", + "@slonik/types": "^45.0.0", + "@slonik/utilities": "^45.0.0", "pg": "^8.11.5", "pg-query-stream": "^4.5.5", "pg-types": "^4.0.2", @@ -13863,14 +13863,14 @@ } }, "packages/slonik": { - "version": "44.0.0", + "version": "45.0.0", "license": "BSD-3-Clause", "dependencies": { - "@slonik/driver": "^44.0.0", - "@slonik/errors": "^44.0.0", - "@slonik/pg-driver": "^44.0.0", - "@slonik/sql-tag": "^44.0.0", - "@slonik/utilities": "^44.0.0", + "@slonik/driver": "^45.0.0", + "@slonik/errors": "^45.0.0", + "@slonik/pg-driver": "^45.0.0", + "@slonik/sql-tag": "^45.0.0", + "@slonik/utilities": "^45.0.0", "get-stack-trace": "^3.1.1", "iso8601-duration": "^1.3.0", "postgres-interval": "^4.0.2", @@ -13923,11 +13923,139 @@ "slonik": ">=44.0.0" } }, + "packages/slonik-dataloaders/node_modules/@slonik/driver": { + "version": "44.0.0", + "resolved": "https://registry.npmjs.org/@slonik/driver/-/driver-44.0.0.tgz", + "integrity": "sha512-i16QQLmRezOq5+oUcpXXbNSAB7HEOfOdxHn5e5FDgXOOfP7OJt//ygP0j3hfj3lLa3wu3J5xlbT7eqsf9kqDZg==", + "dev": true, + "dependencies": { + "@slonik/types": "^44.0.0", + "@slonik/utilities": "^44.0.0", + "roarr": "^7.21.1", + "serialize-error": "^8.0.0", + "strict-event-emitter-types": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3" + } + }, + "packages/slonik-dataloaders/node_modules/@slonik/errors": { + "version": "44.0.0", + "resolved": "https://registry.npmjs.org/@slonik/errors/-/errors-44.0.0.tgz", + "integrity": "sha512-tnkzCZ/ujOXnq1K/zC6bT1PyDiAWL5rSY6yChHuQQIIZ2AgenaroxITrVui+lM86Im7RhOnqRMUd5zDQ63DmYw==", + "dev": true, + "dependencies": { + "@slonik/types": "^44.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3" + } + }, + "packages/slonik-dataloaders/node_modules/@slonik/pg-driver": { + "version": "44.0.0", + "resolved": "https://registry.npmjs.org/@slonik/pg-driver/-/pg-driver-44.0.0.tgz", + "integrity": "sha512-8fsVdGOYEhMfqUQzLtaIig847UL0Z8bX5SsDNAdcAJRd+EdSzTRn6i8FEE0Mj5ygqJu4shZtXxtF7oYnEK0vWA==", + "dev": true, + "dependencies": { + "@slonik/driver": "^44.0.0", + "@slonik/errors": "^44.0.0", + "@slonik/sql-tag": "^44.0.0", + "@slonik/types": "^44.0.0", + "@slonik/utilities": "^44.0.0", + "pg": "^8.11.5", + "pg-query-stream": "^4.5.5", + "pg-types": "^4.0.2", + "postgres-array": "^3.0.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3" + } + }, + "packages/slonik-dataloaders/node_modules/@slonik/sql-tag": { + "version": "44.0.0", + "resolved": "https://registry.npmjs.org/@slonik/sql-tag/-/sql-tag-44.0.0.tgz", + "integrity": "sha512-y2SuRe5xqR4ZORuqU5yAGyRC3eg6T6KmVA0HTy+kWIEzSlZQKm+lsuBswbBfY6Wl9SRGwZ4w5yzZuR/e52wzFw==", + "dev": true, + "dependencies": { + "@slonik/errors": "^44.0.0", + "@slonik/types": "^44.0.0", + "roarr": "^7.21.1", + "safe-stable-stringify": "^2.4.3", + "serialize-error": "^8.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3" + } + }, + "packages/slonik-dataloaders/node_modules/@slonik/types": { + "version": "44.0.0", + "resolved": "https://registry.npmjs.org/@slonik/types/-/types-44.0.0.tgz", + "integrity": "sha512-epVRy5QnnyBp2Rwbh+L4+VzWxtGCKN0eOU2njtp5T7h349Ci7Mwza48p8ByeSgJeIUH6BDsrEvhcpQTLvHg9lg==", + "dev": true, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3" + } + }, + "packages/slonik-dataloaders/node_modules/@slonik/utilities": { + "version": "44.0.0", + "resolved": "https://registry.npmjs.org/@slonik/utilities/-/utilities-44.0.0.tgz", + "integrity": "sha512-uyvMKM0h/f8WH6X9PQEo5D/ceyM98ehYfBys6JFL2PN1UfUH/jJKBZ1QIplFHTXbsyqw+ge4B7iV2xU7CkRxEg==", + "dev": true, + "dependencies": { + "@slonik/types": "^44.0.0", + "roarr": "^7.21.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3" + } + }, "packages/slonik-dataloaders/node_modules/dataloader": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.2.tgz", "integrity": "sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==" }, + "packages/slonik-dataloaders/node_modules/slonik": { + "version": "44.0.0", + "resolved": "https://registry.npmjs.org/slonik/-/slonik-44.0.0.tgz", + "integrity": "sha512-FLMqt7FtKDbL8ZRvOuRnY2+8sSLMWqEyRMyVuP8XP9tj78LHuS2VuFsdWflE5B6pEnmqtAQeRMYM5gD5hbkx3A==", + "dev": true, + "dependencies": { + "@slonik/driver": "^44.0.0", + "@slonik/errors": "^44.0.0", + "@slonik/pg-driver": "^44.0.0", + "@slonik/sql-tag": "^44.0.0", + "@slonik/utilities": "^44.0.0", + "get-stack-trace": "^3.1.1", + "iso8601-duration": "^1.3.0", + "postgres-interval": "^4.0.2", + "roarr": "^7.21.1", + "serialize-error": "^8.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3" + } + }, "packages/slonik-dataloaders/node_modules/typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", @@ -13942,7 +14070,7 @@ } }, "packages/slonik-interceptor-field-name-transformation": { - "version": "44.0.0", + "version": "45.0.0", "license": "BSD-3-Clause", "dependencies": { "camelcase": "^6.2.1" @@ -13951,7 +14079,7 @@ "ava": "^5.3.1", "eslint": "^8.57.0", "eslint-config-canonical": "^42.8.1", - "slonik": "^44.0.0", + "slonik": "^45.0.0", "ts-node": "^10.4.0", "typescript": "^4.7.4" }, @@ -13959,7 +14087,7 @@ "node": ">=18" }, "peerDependencies": { - "slonik": ">=44.0.0" + "slonik": ">=45.0.0" } }, "packages/slonik-interceptor-field-name-transformation/node_modules/camelcase": { @@ -13985,7 +14113,7 @@ } }, "packages/slonik-interceptor-query-cache": { - "version": "44.0.0", + "version": "45.0.0", "license": "BSD-3-Clause", "dependencies": { "roarr": "^7.21.1", @@ -13995,7 +14123,7 @@ "ava": "^5.3.1", "eslint": "^8.57.0", "eslint-config-canonical": "^42.8.1", - "slonik": "^44.0.0", + "slonik": "^45.0.0", "ts-node": "^10.4.0", "typescript": "^4.5.3" }, @@ -14003,7 +14131,7 @@ "node": ">=18" }, "peerDependencies": { - "slonik": ">=44.0.0" + "slonik": ">=45.0.0" } }, "packages/slonik-interceptor-query-cache/node_modules/typescript": { @@ -14020,7 +14148,7 @@ } }, "packages/slonik-interceptor-query-logging": { - "version": "44.0.0", + "version": "45.0.0", "license": "BSD-3-Clause", "dependencies": { "crack-json": "^1.3.0", @@ -14031,7 +14159,7 @@ "ava": "^5.3.1", "eslint": "^8.57.0", "eslint-config-canonical": "^42.8.1", - "slonik": "^44.0.0", + "slonik": "^45.0.0", "ts-node": "^10.4.0", "typescript": "^4.5.3" }, @@ -14039,7 +14167,7 @@ "node": ">=18" }, "peerDependencies": { - "slonik": ">=44.0.0" + "slonik": ">=45.0.0" } }, "packages/slonik-interceptor-query-logging/node_modules/parse-ms": { @@ -14075,10 +14203,10 @@ } }, "packages/slonik-sql-tag-raw": { - "version": "44.0.0", + "version": "45.0.0", "license": "BSD-3-Clause", "dependencies": { - "@slonik/sql-tag": "^44.0.0", + "@slonik/sql-tag": "^45.0.0", "lodash": "^4.17.20", "roarr": "^7.21.1" }, @@ -14086,7 +14214,7 @@ "ava": "^5.3.1", "eslint": "^8.57.0", "eslint-config-canonical": "^42.8.1", - "slonik": "^44.0.0", + "slonik": "^45.0.0", "ts-node": "^10.4.0", "typescript": "^4.5.3" }, @@ -14094,7 +14222,7 @@ "node": ">=18" }, "peerDependencies": { - "slonik": ">=44.0.0" + "slonik": ">=45.0.0" } }, "packages/slonik-sql-tag-raw/node_modules/typescript": { @@ -14121,11 +14249,11 @@ }, "packages/sql-tag": { "name": "@slonik/sql-tag", - "version": "44.0.0", + "version": "45.0.0", "license": "BSD-3-Clause", "dependencies": { - "@slonik/errors": "^44.0.0", - "@slonik/types": "^44.0.0", + "@slonik/errors": "^45.0.0", + "@slonik/types": "^45.0.0", "roarr": "^7.21.1", "safe-stable-stringify": "^2.4.3", "serialize-error": "^8.0.0" @@ -14159,7 +14287,7 @@ }, "packages/types": { "name": "@slonik/types", - "version": "44.0.0", + "version": "45.0.0", "license": "BSD-3-Clause", "devDependencies": { "@types/node": "^18.15.3", @@ -14189,10 +14317,10 @@ }, "packages/utilities": { "name": "@slonik/utilities", - "version": "44.0.0", + "version": "45.0.0", "license": "BSD-3-Clause", "dependencies": { - "@slonik/types": "^44.0.0", + "@slonik/types": "^45.0.0", "roarr": "^7.21.1" }, "devDependencies": { From d6b4ba5ac9d29e5fac0bf92dfeeda48c98d706a6 Mon Sep 17 00:00:00 2001 From: Gajus Date: Mon, 13 May 2024 12:27:04 -0600 Subject: [PATCH 19/22] fix lock --- package-lock.json | 1286 +++++++++++++++++++++++++++++++-------------- 1 file changed, 878 insertions(+), 408 deletions(-) diff --git a/package-lock.json b/package-lock.json index e0fda590..e6429ce6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -701,6 +701,12 @@ "node-fetch": "^2.5.0" } }, + "node_modules/@changesets/get-github-info/node_modules/dataloader": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-1.4.0.tgz", + "integrity": "sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==", + "dev": true + }, "node_modules/@changesets/get-release-plan": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-4.0.0.tgz", @@ -796,9 +802,9 @@ } }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.8.0.tgz", - "integrity": "sha512-wK1qGhy6DiCj9LqGnMKutIQcMPD8J9oczM1sr3J+zmh6WggP1xkuCHu8XSxxO4Q2AOLdtcVW/4SXJ7gzT7Azbg==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.8.1.tgz", + "integrity": "sha512-zP/cC7ABk9PM6X1/itEOYa9raWrdUtUXCcUtHLnEr83HhPUHZ8vzaBgMJ176No/7EgZ4BHGXVvA0v079ukXVxw==", "dev": true, "dependencies": { "@cspell/dict-ada": "^4.0.2", @@ -858,30 +864,30 @@ } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.8.0.tgz", - "integrity": "sha512-MlyEMnTXkLJxNSXcS7j9xV/zFS4/38qOoaH0W5xWGAtDgiFSa9/NXVBnZTNWpdhjtm0UNCfIQenl/l7d3O9Luw==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.8.1.tgz", + "integrity": "sha512-HtendGGO0w1gElhSYsD4D9iKT1nMBoUP31y0Ndw3AtQRzH6I31lx6DWnrXIef1bTL4wdq7ocxgG5HGQBQ8PWfA==", "dev": true, "dependencies": { - "@cspell/cspell-types": "8.8.0" + "@cspell/cspell-types": "8.8.1" }, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-pipe": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.8.0.tgz", - "integrity": "sha512-R9YEI8+GVa98mEMCtCHJMqX4xHNwhdHo31lGhmyUpYiuLcD9HZ96n+ExCGbnFBUXyugSHCmTA/lubdfo7CPZrw==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.8.1.tgz", + "integrity": "sha512-AMQ0s7qH71tNnrpX8ILl+OZceDHt//h/T3Yk//qvn69x1Dzfg4Saqv/qhfG1VClQVyV5F4y7tIa4UNd5X6mW4g==", "dev": true, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-resolver": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.8.0.tgz", - "integrity": "sha512-+o1fwkE36Wi8JTnjDHdLScB99U8YtLQ7XbnEe61Hj2ES1G5TsYCZ1r7RFCw2Kzn2qrkE2mnxknKwbf9h0Db4Ng==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.8.1.tgz", + "integrity": "sha512-K5sPp05Pz3tYU9roFGILSB6OdSVYqyr4Y/NW1CxZsXgq+hmwxAJQag/RyhW6cUp/1Jhy5RKYGNy0H0u/jODx3A==", "dev": true, "dependencies": { "global-directory": "^4.0.1" @@ -891,18 +897,18 @@ } }, "node_modules/@cspell/cspell-service-bus": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.8.0.tgz", - "integrity": "sha512-BvQgBbrsXmKmaEXhXSGQPzBTM37EMk696u6+ThuJuIikP54pKJpUc7rOV1NKretxC32Mj37mS750X1YR02Z80w==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.8.1.tgz", + "integrity": "sha512-dxZ/ymwP6XNMGkU5iIUVgFP2JEqEvpJZavpAerB/y5E560Agv1WuUpkZE/PMCmseoLjSiV5yQzcnLNoT5X/w7A==", "dev": true, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-types": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.8.0.tgz", - "integrity": "sha512-CGIYttfpp0M/y4a7vfVQljeJqBcIsGYIM4iwJU+F3MQUqFqvNFeU58S27GfK5VzkMAJumsOnmJqSgm+h/g7n0Q==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.8.1.tgz", + "integrity": "sha512-JEbLN+b3XdHIpEaoZJnpPfL8iTKWraqE7x1VwG7FIQ9wjP6fCPwfNRVM0CUWEmT+85O/zvbYVOlTJn1uIOLnZw==", "dev": true, "engines": { "node": ">=18" @@ -1224,9 +1230,9 @@ "dev": true }, "node_modules/@cspell/dynamic-import": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.8.0.tgz", - "integrity": "sha512-oNe8IPaTDsbfGbGCt7Ss+g8RRI7c9zpTnp/G/eG+PuWvH8Isps4+dWE/4qhxS7e3XTyQwfD89b3H3TAPAuwstQ==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.8.1.tgz", + "integrity": "sha512-IyKEbSaHkw9V4Oc4JDasF96+BHKV8motBrepjLIMUjdJ152fBg8zqbvF769POdCJg0QouZVUV+h9V7zC6v45/g==", "dev": true, "dependencies": { "import-meta-resolve": "^4.1.0" @@ -1236,9 +1242,9 @@ } }, "node_modules/@cspell/strong-weak-map": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.8.0.tgz", - "integrity": "sha512-A0mkSdPiZkbF3e+OGM2eO1k0yrdgohvgO2p3fhb1bGylj8n6po+H6iNh2zpumTtfy1xVIrfpYPdOT7Z6TvvbIw==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.8.1.tgz", + "integrity": "sha512-QNnMY5jKP/ItVYRGS4w3KF+1iXBUUjldZNVtEoQe2dFergxvbIYQ0S++TZb25G/o9nRF5GmOpecJaOvwUBZsiw==", "dev": true, "engines": { "node": ">=18" @@ -1310,6 +1316,74 @@ "node": ">=16" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/darwin-arm64": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", @@ -1327,6 +1401,312 @@ "node": ">=12" } }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -1493,12 +1873,6 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/@graphql-tools/batch-execute/node_modules/dataloader": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.2.tgz", - "integrity": "sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==", - "dev": true - }, "node_modules/@graphql-tools/code-file-loader": { "version": "7.3.23", "resolved": "https://registry.npmjs.org/@graphql-tools/code-file-loader/-/code-file-loader-7.3.23.tgz", @@ -1533,12 +1907,6 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/@graphql-tools/delegate/node_modules/dataloader": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.2.tgz", - "integrity": "sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==", - "dev": true - }, "node_modules/@graphql-tools/executor": { "version": "0.0.20", "resolved": "https://registry.npmjs.org/@graphql-tools/executor/-/executor-0.0.20.tgz", @@ -2104,58 +2472,268 @@ "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", "dev": true, - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=8.0.0" - } + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@peculiar/webcrypto": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.6.tgz", + "integrity": "sha512-YBcMfqNSwn3SujUJvAaySy5tlYbYm6tVt9SKoXu8BaTdKGROiJDgPR3TXpZdAKUfklzm3lRapJEAltiMQtBgZg==", + "dev": true, + "dependencies": { + "@peculiar/asn1-schema": "^2.3.8", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.5", + "tslib": "^2.6.2", + "webcrypto-core": "^1.7.9" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@repeaterjs/repeater": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.6.tgz", + "integrity": "sha512-Javneu5lsuhwNCryN+pXH93VPQ8g0dBX7wItHFgYiwQmzE1sVdg5tWHiOgHywzL2W21XQopa7IwIEnNbmeUJYA==", + "dev": true + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz", + "integrity": "sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.2.tgz", + "integrity": "sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz", + "integrity": "sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.2.tgz", + "integrity": "sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.2.tgz", + "integrity": "sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.2.tgz", + "integrity": "sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz", + "integrity": "sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz", + "integrity": "sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.2.tgz", + "integrity": "sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.2.tgz", + "integrity": "sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.2.tgz", + "integrity": "sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz", + "integrity": "sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true }, - "node_modules/@peculiar/webcrypto": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.6.tgz", - "integrity": "sha512-YBcMfqNSwn3SujUJvAaySy5tlYbYm6tVt9SKoXu8BaTdKGROiJDgPR3TXpZdAKUfklzm3lRapJEAltiMQtBgZg==", + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz", + "integrity": "sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@peculiar/asn1-schema": "^2.3.8", - "@peculiar/json-schema": "^1.1.12", - "pvtsutils": "^1.3.5", - "tslib": "^2.6.2", - "webcrypto-core": "^1.7.9" - }, - "engines": { - "node": ">=10.12.0" - } + "optional": true, + "os": [ + "linux" + ], + "peer": true }, - "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.2.tgz", + "integrity": "sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==", + "cpu": [ + "arm64" + ], "dev": true, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } + "optional": true, + "os": [ + "win32" + ], + "peer": true }, - "node_modules/@repeaterjs/repeater": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.5.tgz", - "integrity": "sha512-l3YHBLAol6d/IKnB9LhpD0cEZWAoe3eFKUyTYWmFmCO2Q/WOckxLQAUyMZWwZV2M/m3+4vgRoaolFqaII82/TA==", - "dev": true + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.2.tgz", + "integrity": "sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true }, - "node_modules/@rollup/rollup-darwin-arm64": { + "node_modules/@rollup/rollup-win32-x64-msvc": { "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz", - "integrity": "sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.2.tgz", + "integrity": "sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==", "cpu": [ - "arm64" + "x64" ], "dev": true, "optional": true, "os": [ - "darwin" + "win32" ], "peer": true }, @@ -2367,9 +2945,9 @@ "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==" }, "node_modules/@types/node": { - "version": "20.12.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.10.tgz", - "integrity": "sha512-Eem5pH9pmWBHoGAT8Dr5fdc5rYA+4NAovdM4EktRPVAAiJhmWWfQrA0cFhAbOsQdSfIHjAud6YdkbL69+zSKjw==", + "version": "20.12.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.11.tgz", + "integrity": "sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -2421,21 +2999,19 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.8.0.tgz", - "integrity": "sha512-gFTT+ezJmkwutUPmB0skOj3GZJtlEGnlssems4AjkVweUPGj7jRwwqg0Hhg7++kPGJqKtTYx+R05Ftww372aIg==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.9.0.tgz", + "integrity": "sha512-6e+X0X3sFe/G/54aC3jt0txuMTURqLyekmEHViqyA2VnxhLMpvA6nqmcjIy+Cr9tLDHPssA74BP5Mx9HQIxBEA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.8.0", - "@typescript-eslint/type-utils": "7.8.0", - "@typescript-eslint/utils": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0", - "debug": "^4.3.4", + "@typescript-eslint/scope-manager": "7.9.0", + "@typescript-eslint/type-utils": "7.9.0", + "@typescript-eslint/utils": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "semver": "^7.6.0", "ts-api-utils": "^1.3.0" }, "engines": { @@ -2597,15 +3173,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.8.0.tgz", - "integrity": "sha512-KgKQly1pv0l4ltcftP59uQZCi4HUYswCLbTqVZEJu7uLX8CTLyswqMLqLN+2QFz4jCptqWVV4SB7vdxcH2+0kQ==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.9.0.tgz", + "integrity": "sha512-qHMJfkL5qvgQB2aLvhUSXxbK7OLnDkwPzFalg458pxQgfxKDfT1ZDbHQM/I6mDIf/svlMkj21kzKuQ2ixJlatQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.8.0", - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/typescript-estree": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0", + "@typescript-eslint/scope-manager": "7.9.0", + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/typescript-estree": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0", "debug": "^4.3.4" }, "engines": { @@ -2625,13 +3201,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.8.0.tgz", - "integrity": "sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.9.0.tgz", + "integrity": "sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0" + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2642,13 +3218,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.8.0.tgz", - "integrity": "sha512-H70R3AefQDQpz9mGv13Uhi121FNMh+WEaRqcXTX09YEDky21km4dV1ZXJIp8QjXc4ZaVkXVdohvWDzbnbHDS+A==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.9.0.tgz", + "integrity": "sha512-6Qy8dfut0PFrFRAZsGzuLoM4hre4gjzWJB6sUvdunCYZsYemTkzZNwF1rnGea326PHPT3zn5Lmg32M/xfJfByA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.8.0", - "@typescript-eslint/utils": "7.8.0", + "@typescript-eslint/typescript-estree": "7.9.0", + "@typescript-eslint/utils": "7.9.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2669,9 +3245,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", - "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.9.0.tgz", + "integrity": "sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2682,13 +3258,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.8.0.tgz", - "integrity": "sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.9.0.tgz", + "integrity": "sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0", + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2734,18 +3310,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.8.0.tgz", - "integrity": "sha512-L0yFqOCflVqXxiZyXrDr80lnahQfSOfc9ELAAZ75sqicqp2i36kEZZGuUymHNFoYOqxRT05up760b4iGsl02nQ==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.9.0.tgz", + "integrity": "sha512-5KVRQCzZajmT4Ep+NEgjXCvjuypVvYHUW7RHlXzNPuak2oWpVoD1jf5xCP0dPAuNIchjC7uQyvbdaSTFaLqSdA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.15", - "@types/semver": "^7.5.8", - "@typescript-eslint/scope-manager": "7.8.0", - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/typescript-estree": "7.8.0", - "semver": "^7.6.0" + "@typescript-eslint/scope-manager": "7.9.0", + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/typescript-estree": "7.9.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2759,12 +3332,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", - "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz", + "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/types": "7.9.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -3796,9 +4369,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001616", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001616.tgz", - "integrity": "sha512-RHVYKov7IcdNjVHJFNY/78RdG4oGVjbayxv8u5IO74Wv7Hlq4PnJE6mo/OjFijjVFNy5ijnCt6H3IIo4t+wfEw==", + "version": "1.0.30001617", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001617.tgz", + "integrity": "sha512-mLyjzNI9I+Pix8zwcrpxEbGlfqOkF9kM3ptzmKNw5tizSyYwMe+nGLTqMK9cO+0E+Bh6TsBxNAaHWEM8xwSsmA==", "dev": true, "funding": [ { @@ -4253,37 +4826,6 @@ "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", "dev": true }, - "node_modules/configstore": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz", - "integrity": "sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==", - "dev": true, - "dependencies": { - "dot-prop": "^6.0.1", - "graceful-fs": "^4.2.6", - "unique-string": "^3.0.0", - "write-file-atomic": "^3.0.3", - "xdg-basedir": "^5.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/yeoman/configstore?sponsor=1" - } - }, - "node_modules/configstore/node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -4389,55 +4931,28 @@ "node": ">= 8" } }, - "node_modules/crypto-random-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", - "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", - "dev": true, - "dependencies": { - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/crypto-random-string/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/cspell": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.8.0.tgz", - "integrity": "sha512-WDysxJ1IVbPSK+bO0coGDgaA2+on9ubS+Ya2sw7opKEVpp5a0T+Fd7rEkaAmvD0ipsn8hm/S60tVNz4+m2kRUg==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.8.1.tgz", + "integrity": "sha512-YDJ62Q400LqxKTQV5Nk+Ub2IZGm5L0p832KbFUMy7FXDwkPLaxp3mfcLFV677FRiTcnGUtGYD+SnPkFJ2hiqsg==", "dev": true, "dependencies": { - "@cspell/cspell-json-reporter": "8.8.0", - "@cspell/cspell-pipe": "8.8.0", - "@cspell/cspell-types": "8.8.0", - "@cspell/dynamic-import": "8.8.0", + "@cspell/cspell-json-reporter": "8.8.1", + "@cspell/cspell-pipe": "8.8.1", + "@cspell/cspell-types": "8.8.1", + "@cspell/dynamic-import": "8.8.1", "chalk": "^5.3.0", "chalk-template": "^1.1.0", "commander": "^12.0.0", - "cspell-gitignore": "8.8.0", - "cspell-glob": "8.8.0", - "cspell-io": "8.8.0", - "cspell-lib": "8.8.0", + "cspell-gitignore": "8.8.1", + "cspell-glob": "8.8.1", + "cspell-io": "8.8.1", + "cspell-lib": "8.8.1", "fast-glob": "^3.3.2", "fast-json-stable-stringify": "^2.1.0", "file-entry-cache": "^8.0.0", "get-stdin": "^9.0.0", - "semver": "^7.6.0", + "semver": "^7.6.1", "strip-ansi": "^7.1.0", "vscode-uri": "^3.0.8" }, @@ -4453,12 +4968,12 @@ } }, "node_modules/cspell-config-lib": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.8.0.tgz", - "integrity": "sha512-Sz+bKXV9qpEVdi0e+MSUVMwbJ5Kin3m+6tyJp/Rk2rXKjBIXVmFBmnixv964rhr6c5GzbblV7GuMn94B2p7B3Q==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.8.1.tgz", + "integrity": "sha512-NTFfwL7Si1jp+0TINS9miXGdtPtDq95PhSbZKF9jnuBwnsnAURHCGALryLHlkRvj5JZk6dpkDfw4WxqQXdULNw==", "dev": true, "dependencies": { - "@cspell/cspell-types": "8.8.0", + "@cspell/cspell-types": "8.8.1", "comment-json": "^4.2.3", "yaml": "^2.4.2" }, @@ -4467,14 +4982,14 @@ } }, "node_modules/cspell-dictionary": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.8.0.tgz", - "integrity": "sha512-Iloe3GBJV3sVkZG0j0rmxwuNxIcuOHy+eLhFfSHKiLK62FyOBL3T2Rm50h2Q6fCiLONu/3CNp0Z3BKbQ8cZxZg==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.8.1.tgz", + "integrity": "sha512-WJqCLR/icyZc0rphEO6dZZDlSIaWIXd95QjZu3agL7a1LRLjorqhVJty6WZrV4zkOLT6PPB+qcjMxcCCxIlWiw==", "dev": true, "dependencies": { - "@cspell/cspell-pipe": "8.8.0", - "@cspell/cspell-types": "8.8.0", - "cspell-trie-lib": "8.8.0", + "@cspell/cspell-pipe": "8.8.1", + "@cspell/cspell-types": "8.8.1", + "cspell-trie-lib": "8.8.1", "fast-equals": "^5.0.1", "gensequence": "^7.0.0" }, @@ -4483,12 +4998,12 @@ } }, "node_modules/cspell-gitignore": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.8.0.tgz", - "integrity": "sha512-djM1Z0SnA1MehJHLiSRnfhY9sMPvJgQ9Gbnuub/l4VZeC0YDKIf+nAu+GPMQPtsL4QBvqj/oSy0GmUNWiMhbew==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.8.1.tgz", + "integrity": "sha512-j7wbz/VT/uZ+7oL8xwtxfA05FCv41ZrEKh1aNuMa4BI1xv/VRBmv6thOTz7aq7UcDYPNr8K5VVfBlXT/SvkEvA==", "dev": true, "dependencies": { - "cspell-glob": "8.8.0", + "cspell-glob": "8.8.1", "find-up-simple": "^1.0.0" }, "bin": { @@ -4499,9 +5014,9 @@ } }, "node_modules/cspell-glob": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.8.0.tgz", - "integrity": "sha512-LAq4PrE92vvuKoIbZN6B6HqmNlSEw9yds6pkmugYYpd6vLMBvzMbtTGjIEq0o+KhfoJPOnfOxRssPoiezwvIhA==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.8.1.tgz", + "integrity": "sha512-x2rS6gJzaF3KZB6FuNkuS3Kb3ynYns0zfC0uG/QJb9V/xc0DmAjQGQhiLIDx6XmvvDvowKmyQ/kBjY/K4VjCvQ==", "dev": true, "dependencies": { "micromatch": "^4.0.5" @@ -4511,13 +5026,13 @@ } }, "node_modules/cspell-grammar": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.8.0.tgz", - "integrity": "sha512-sB9IvSQ89Q5TgmAwXwXubs5U8dfZFvvaMT5LGKKW/XMGO4gVSBTAwRwGP2INZXdHHzFXUaVhEd+Tf4S3djoOdw==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.8.1.tgz", + "integrity": "sha512-YTyrutwIkiPH9t255l+BQtneGAkgE3uZXmnRHeIi6X+qdmnf61i8XYaSaO66VKQJX6VPZG18hBVMSUPZmYtoSw==", "dev": true, "dependencies": { - "@cspell/cspell-pipe": "8.8.0", - "@cspell/cspell-types": "8.8.0" + "@cspell/cspell-pipe": "8.8.1", + "@cspell/cspell-types": "8.8.1" }, "bin": { "cspell-grammar": "bin.mjs" @@ -4527,57 +5042,58 @@ } }, "node_modules/cspell-io": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.8.0.tgz", - "integrity": "sha512-98sPDQiwLTI3eNqGe6ksJv6ue5BJCMjM6CDF686Sxx2GlYe50saJK1XizM1yuhBcaHPZysSYHzbsLTMb7aSzWQ==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.8.1.tgz", + "integrity": "sha512-qwKEV2kfwT9gbq6EpYt6gcEs0oe0sDPG1YJunt8niuX4YoBe7/9ZHBfUyqNOEA+sBmvI/tjY/Wy6g9mmSRaOYA==", "dev": true, "dependencies": { - "@cspell/cspell-service-bus": "8.8.0" + "@cspell/cspell-service-bus": "8.8.1" }, "engines": { "node": ">=18" } }, "node_modules/cspell-lib": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.8.0.tgz", - "integrity": "sha512-P6WBilxNOXFWBgAFtTJn8VIBgBwn39v/TuA7d9uUWiRI/bhcMddEMCwVyjSZ3YYW/OmDEyN/c+R/4HjOw1Ny8A==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.8.1.tgz", + "integrity": "sha512-xntkgDGwDtUehM+fZudp4GbB87a2tY29G6ZqDF7WBcQsg3eyDVK/nc9KzbIfCvdWUCrsB9p+SGBoOmjYTwcocg==", "dev": true, "dependencies": { - "@cspell/cspell-bundled-dicts": "8.8.0", - "@cspell/cspell-pipe": "8.8.0", - "@cspell/cspell-resolver": "8.8.0", - "@cspell/cspell-types": "8.8.0", - "@cspell/dynamic-import": "8.8.0", - "@cspell/strong-weak-map": "8.8.0", + "@cspell/cspell-bundled-dicts": "8.8.1", + "@cspell/cspell-pipe": "8.8.1", + "@cspell/cspell-resolver": "8.8.1", + "@cspell/cspell-types": "8.8.1", + "@cspell/dynamic-import": "8.8.1", + "@cspell/strong-weak-map": "8.8.1", "clear-module": "^4.1.2", "comment-json": "^4.2.3", - "configstore": "^6.0.0", - "cspell-config-lib": "8.8.0", - "cspell-dictionary": "8.8.0", - "cspell-glob": "8.8.0", - "cspell-grammar": "8.8.0", - "cspell-io": "8.8.0", - "cspell-trie-lib": "8.8.0", + "cspell-config-lib": "8.8.1", + "cspell-dictionary": "8.8.1", + "cspell-glob": "8.8.1", + "cspell-grammar": "8.8.1", + "cspell-io": "8.8.1", + "cspell-trie-lib": "8.8.1", + "env-paths": "^3.0.0", "fast-equals": "^5.0.1", "gensequence": "^7.0.0", "import-fresh": "^3.3.0", "resolve-from": "^5.0.0", "vscode-languageserver-textdocument": "^1.0.11", - "vscode-uri": "^3.0.8" + "vscode-uri": "^3.0.8", + "xdg-basedir": "^5.1.0" }, "engines": { "node": ">=18" } }, "node_modules/cspell-trie-lib": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.8.0.tgz", - "integrity": "sha512-0UJp2Y5QMaBdapyIWtZ5DTH9BlM0tMcAYxOeqwmbnsdyfe2Ix8w9Ur3ZSQAAVnHEFhPJA83D0D1rMsKdYdQ4zQ==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.8.1.tgz", + "integrity": "sha512-S84XzQYGqKGApjVgamMp8tbHfKCeGZFxMwqedb4vxEJTYnUuCHaVPX2BK2SKaLSv/Vrd8mrJ/57sx5f8C44cFg==", "dev": true, "dependencies": { - "@cspell/cspell-pipe": "8.8.0", - "@cspell/cspell-types": "8.8.0", + "@cspell/cspell-pipe": "8.8.1", + "@cspell/cspell-types": "8.8.1", "gensequence": "^7.0.0" }, "engines": { @@ -4692,10 +5208,9 @@ } }, "node_modules/dataloader": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-1.4.0.tgz", - "integrity": "sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==", - "dev": true + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.2.tgz", + "integrity": "sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==" }, "node_modules/date-time": { "version": "3.1.0", @@ -4903,21 +5418,6 @@ "node": ">=6.0.0" } }, - "node_modules/dot-prop": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", - "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", - "dev": true, - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/dotenv": { "version": "8.6.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", @@ -4955,9 +5455,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.757", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.757.tgz", - "integrity": "sha512-jftDaCknYSSt/+KKeXzH3LX5E2CvRLm75P3Hj+J/dv3CL0qUYcOt13d5FN1NiL5IJbbhzHrb3BomeG2tkSlZmw==", + "version": "1.4.764", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.764.tgz", + "integrity": "sha512-ZXbPV46Y4dNCA+k7YHB+BYlzcoMtZ1yH6V0tQ1ul0wmA7RiwJfS29LSdRlE1myWBXRzEgm/Lz6tryj5WVQiLmg==", "dev": true }, "node_modules/emittery": { @@ -4991,9 +5491,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", - "integrity": "sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==", + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.1.tgz", + "integrity": "sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -5026,6 +5526,18 @@ "node": ">=8" } }, + "node_modules/env-paths": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", + "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -6630,21 +7142,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/execa/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/execa/node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -7183,9 +7680,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.4.tgz", - "integrity": "sha512-ofbkKj+0pjXjhejr007J/fLf+sW+8H7K5GCm+msC8q3IpvgjobpyPqSRFemNyIMxklC0zeJpi7VDFna19FacvQ==", + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", + "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", "dev": true, "dependencies": { "resolve-pkg-maps": "^1.0.0" @@ -8011,15 +8508,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-obj-prop": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-obj-prop/-/is-obj-prop-1.0.0.tgz", @@ -8696,9 +9184,9 @@ } }, "node_modules/knip": { - "version": "5.12.3", - "resolved": "https://registry.npmjs.org/knip/-/knip-5.12.3.tgz", - "integrity": "sha512-LL+NsE+3H0TkUnQW6icHQ+5qSrPENmjHJyMHgzjiZPmunstrIsaRG+QjahnzoH/FjMjVJwrdwVOSvksa8ixFbw==", + "version": "5.15.1", + "resolved": "https://registry.npmjs.org/knip/-/knip-5.15.1.tgz", + "integrity": "sha512-v6/Bf2qUmZ7pMJb2GjTficHyEjhP2ysIifjM1wgJr2psFbK6Vbxw2/DpeDAcgK9d99kTGh1PUQwoiFd6LHtI6A==", "dev": true, "funding": [ { @@ -9920,27 +10408,20 @@ } }, "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, "dependencies": { - "mimic-fn": "^2.1.0" + "mimic-fn": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/onetime/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "engines": { - "node": ">=6" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -10323,14 +10804,6 @@ "node": ">=10" } }, - "node_modules/pg-types/node_modules/postgres-interval": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", - "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", - "engines": { - "node": ">=12" - } - }, "node_modules/pg/node_modules/pg-types": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", @@ -10700,9 +11173,9 @@ } }, "node_modules/postgres-interval": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-4.0.2.tgz", - "integrity": "sha512-EMsphSQ1YkQqKZL2cuG0zHkmjCCzQqQ71l2GXITqRwjhRleCdv00bDk/ktaSi0LnlaPzAc3535KTrjXsTdtx7A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", + "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", "engines": { "node": ">=12" } @@ -11056,9 +11529,9 @@ } }, "node_modules/recast": { - "version": "0.23.6", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.6.tgz", - "integrity": "sha512-9FHoNjX1yjuesMwuthAmPKabxYQdOgihFYmT5ebXfYGBcnqXZf3WOVz+5foEZ8Y83P4ZY6yQD5GMmtV+pgCCAQ==", + "version": "0.23.7", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.7.tgz", + "integrity": "sha512-MpQlLZVpqbbxYcqEjwpRWo88sGvjOYoXptySz710RuddNMHx+wPkoNX6YyLZJlXAh5VZr1qmPrTwcTuFMh0Lag==", "dev": true, "dependencies": { "ast-types": "^0.16.1", @@ -11304,6 +11777,28 @@ "node": ">=8" } }, + "node_modules/restore-cursor/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -11462,12 +11957,9 @@ } }, "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "bin": { "semver": "bin/semver.js" }, @@ -11480,22 +11972,6 @@ "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==" }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/serialize-error": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz", @@ -12932,21 +13408,6 @@ "string.fromcodepoint": "^0.2.1" } }, - "node_modules/unique-string": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", - "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", - "dev": true, - "dependencies": { - "crypto-random-string": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -13727,9 +14188,9 @@ } }, "node_modules/zod-validation-error": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.2.0.tgz", - "integrity": "sha512-cYlPR6zuyrgmu2wRTdumEAJGuwI7eHVHGT+VyneAQxmRAKtGRL1/7pjz4wfLhz4J05f5qoSZc3rGacswgyTjjw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.3.0.tgz", + "integrity": "sha512-Syib9oumw1NTqEv4LT0e6U83Td9aVRk9iTXPUQr1otyV1PuXQKOvOwhMNqZIq5hluzHP2pMgnOmHEo7kPdI2mw==", "dev": true, "engines": { "node": ">=18.0.0" @@ -13739,7 +14200,6 @@ } }, "packages/benchmark": { - "name": "@slonik/benchmark", "version": "45.0.0", "dependencies": { "benny": "^3.7.1", @@ -13750,7 +14210,6 @@ } }, "packages/driver": { - "name": "@slonik/driver", "version": "45.0.0", "license": "BSD-3-Clause", "dependencies": { @@ -13778,16 +14237,15 @@ } }, "packages/driver/node_modules/@types/node": { - "version": "18.19.32", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.32.tgz", - "integrity": "sha512-2bkg93YBSDKk8DLmmHnmj/Rwr18TLx7/n+I23BigFwgexUJoMHZOd8X1OFxuF/W3NN0S2W2E5sVabI5CPinNvA==", + "version": "18.19.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.33.tgz", + "integrity": "sha512-NR9+KrpSajr2qBVp/Yt5TU/rp+b5Mayi3+OlMlcg2cVCfRmcG5PWZ7S4+MG9PZ5gWBoc9Pd0BKSRViuBCRPu0A==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, "packages/errors": { - "name": "@slonik/errors", "version": "45.0.0", "license": "BSD-3-Clause", "dependencies": { @@ -13812,16 +14270,15 @@ } }, "packages/errors/node_modules/@types/node": { - "version": "18.19.32", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.32.tgz", - "integrity": "sha512-2bkg93YBSDKk8DLmmHnmj/Rwr18TLx7/n+I23BigFwgexUJoMHZOd8X1OFxuF/W3NN0S2W2E5sVabI5CPinNvA==", + "version": "18.19.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.33.tgz", + "integrity": "sha512-NR9+KrpSajr2qBVp/Yt5TU/rp+b5Mayi3+OlMlcg2cVCfRmcG5PWZ7S4+MG9PZ5gWBoc9Pd0BKSRViuBCRPu0A==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, "packages/pg-driver": { - "name": "@slonik/pg-driver", "version": "45.0.0", "license": "BSD-3-Clause", "dependencies": { @@ -13854,9 +14311,9 @@ } }, "packages/pg-driver/node_modules/@types/node": { - "version": "18.19.32", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.32.tgz", - "integrity": "sha512-2bkg93YBSDKk8DLmmHnmj/Rwr18TLx7/n+I23BigFwgexUJoMHZOd8X1OFxuF/W3NN0S2W2E5sVabI5CPinNvA==", + "version": "18.19.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.33.tgz", + "integrity": "sha512-NR9+KrpSajr2qBVp/Yt5TU/rp+b5Mayi3+OlMlcg2cVCfRmcG5PWZ7S4+MG9PZ5gWBoc9Pd0BKSRViuBCRPu0A==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -13900,7 +14357,6 @@ } }, "packages/slonik-dataloaders": { - "name": "@slonik/dataloaders", "version": "44.0.0", "license": "BSD-3-Clause", "dependencies": { @@ -14027,10 +14483,14 @@ "zod": "^3" } }, - "packages/slonik-dataloaders/node_modules/dataloader": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.2.tgz", - "integrity": "sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==" + "packages/slonik-dataloaders/node_modules/postgres-interval": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-4.0.2.tgz", + "integrity": "sha512-EMsphSQ1YkQqKZL2cuG0zHkmjCCzQqQ71l2GXITqRwjhRleCdv00bDk/ktaSi0LnlaPzAc3535KTrjXsTdtx7A==", + "dev": true, + "engines": { + "node": ">=12" + } }, "packages/slonik-dataloaders/node_modules/slonik": { "version": "44.0.0", @@ -14092,7 +14552,8 @@ }, "packages/slonik-interceptor-field-name-transformation/node_modules/camelcase": { "version": "6.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "engines": { "node": ">=10" }, @@ -14102,8 +14563,9 @@ }, "packages/slonik-interceptor-field-name-transformation/node_modules/typescript": { "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true, - "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -14172,14 +14634,16 @@ }, "packages/slonik-interceptor-query-logging/node_modules/parse-ms": { "version": "2.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", + "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", "engines": { "node": ">=6" } }, "packages/slonik-interceptor-query-logging/node_modules/pretty-ms": { "version": "7.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", + "integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==", "dependencies": { "parse-ms": "^2.1.0" }, @@ -14192,8 +14656,9 @@ }, "packages/slonik-interceptor-query-logging/node_modules/typescript": { "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true, - "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -14239,16 +14704,23 @@ } }, "packages/slonik/node_modules/@types/node": { - "version": "18.19.32", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.32.tgz", - "integrity": "sha512-2bkg93YBSDKk8DLmmHnmj/Rwr18TLx7/n+I23BigFwgexUJoMHZOd8X1OFxuF/W3NN0S2W2E5sVabI5CPinNvA==", + "version": "18.19.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.33.tgz", + "integrity": "sha512-NR9+KrpSajr2qBVp/Yt5TU/rp+b5Mayi3+OlMlcg2cVCfRmcG5PWZ7S4+MG9PZ5gWBoc9Pd0BKSRViuBCRPu0A==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, + "packages/slonik/node_modules/postgres-interval": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-4.0.2.tgz", + "integrity": "sha512-EMsphSQ1YkQqKZL2cuG0zHkmjCCzQqQ71l2GXITqRwjhRleCdv00bDk/ktaSi0LnlaPzAc3535KTrjXsTdtx7A==", + "engines": { + "node": ">=12" + } + }, "packages/sql-tag": { - "name": "@slonik/sql-tag", "version": "45.0.0", "license": "BSD-3-Clause", "dependencies": { @@ -14277,16 +14749,15 @@ } }, "packages/sql-tag/node_modules/@types/node": { - "version": "18.19.32", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.32.tgz", - "integrity": "sha512-2bkg93YBSDKk8DLmmHnmj/Rwr18TLx7/n+I23BigFwgexUJoMHZOd8X1OFxuF/W3NN0S2W2E5sVabI5CPinNvA==", + "version": "18.19.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.33.tgz", + "integrity": "sha512-NR9+KrpSajr2qBVp/Yt5TU/rp+b5Mayi3+OlMlcg2cVCfRmcG5PWZ7S4+MG9PZ5gWBoc9Pd0BKSRViuBCRPu0A==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, "packages/types": { - "name": "@slonik/types", "version": "45.0.0", "license": "BSD-3-Clause", "devDependencies": { @@ -14307,16 +14778,15 @@ } }, "packages/types/node_modules/@types/node": { - "version": "18.19.32", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.32.tgz", - "integrity": "sha512-2bkg93YBSDKk8DLmmHnmj/Rwr18TLx7/n+I23BigFwgexUJoMHZOd8X1OFxuF/W3NN0S2W2E5sVabI5CPinNvA==", + "version": "18.19.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.33.tgz", + "integrity": "sha512-NR9+KrpSajr2qBVp/Yt5TU/rp+b5Mayi3+OlMlcg2cVCfRmcG5PWZ7S4+MG9PZ5gWBoc9Pd0BKSRViuBCRPu0A==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, "packages/utilities": { - "name": "@slonik/utilities", "version": "45.0.0", "license": "BSD-3-Clause", "dependencies": { @@ -14342,9 +14812,9 @@ } }, "packages/utilities/node_modules/@types/node": { - "version": "18.19.32", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.32.tgz", - "integrity": "sha512-2bkg93YBSDKk8DLmmHnmj/Rwr18TLx7/n+I23BigFwgexUJoMHZOd8X1OFxuF/W3NN0S2W2E5sVabI5CPinNvA==", + "version": "18.19.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.33.tgz", + "integrity": "sha512-NR9+KrpSajr2qBVp/Yt5TU/rp+b5Mayi3+OlMlcg2cVCfRmcG5PWZ7S4+MG9PZ5gWBoc9Pd0BKSRViuBCRPu0A==", "dev": true, "dependencies": { "undici-types": "~5.26.4" From 15c39a38d0753a2b09b15c5dcc3ea571b536ab6a Mon Sep 17 00:00:00 2001 From: Gajus Date: Mon, 13 May 2024 12:32:18 -0600 Subject: [PATCH 20/22] wip --- .github/workflows/feature.yaml | 2 +- .github/workflows/main.yaml | 2 +- .../src/factories/createConnectionLoaderClass.test.ts | 2 +- .../src/factories/createNodeByIdLoaderClass.test.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/feature.yaml b/.github/workflows/feature.yaml index c1955b94..99edf720 100644 --- a/.github/workflows/feature.yaml +++ b/.github/workflows/feature.yaml @@ -80,7 +80,7 @@ jobs: - run: npm ci - run: npm run build --workspaces --if-present - env: - POSTGRES_DSN: postgres:postgres@localhost:5432 + POSTGRES_DSN: postgres://postgres:postgres@localhost:5432 TEST_ONLY: '${{ matrix.test_only }}' run: npm run test --workspaces --if-present strategy: diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index ada52756..4a14680f 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -88,7 +88,7 @@ jobs: - run: npm ci - run: npm run build --workspaces --if-present - env: - POSTGRES_DSN: postgres:postgres@localhost:5432 + POSTGRES_DSN: postgres://postgres:postgres@localhost:5432 TEST_ONLY: '${{ matrix.test_only }}' run: npm run test --workspaces --if-present strategy: diff --git a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts index 63084fa3..1ce50b10 100644 --- a/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts +++ b/packages/slonik-dataloaders/src/factories/createConnectionLoaderClass.test.ts @@ -18,7 +18,7 @@ import { z } from 'zod'; const POSTGRES_DSN = // eslint-disable-next-line n/no-process-env - process.env.POSTGRES_DSN ?? 'postgres://postgres@localhost:5432'; + process.env.POSTGRES_DSN ?? 'postgres://postgres:postgres@localhost:5432'; const getInfo = ( fields: string[], diff --git a/packages/slonik-dataloaders/src/factories/createNodeByIdLoaderClass.test.ts b/packages/slonik-dataloaders/src/factories/createNodeByIdLoaderClass.test.ts index 02969980..f0d9c846 100644 --- a/packages/slonik-dataloaders/src/factories/createNodeByIdLoaderClass.test.ts +++ b/packages/slonik-dataloaders/src/factories/createNodeByIdLoaderClass.test.ts @@ -5,7 +5,7 @@ import { z } from 'zod'; const POSTGRES_DSN = // eslint-disable-next-line n/no-process-env - process.env.POSTGRES_DSN ?? 'postgres://postgres@localhost:5432'; + process.env.POSTGRES_DSN ?? 'postgres://postgres:postgres@localhost:5432'; const FooByIdLoader = createNodeByIdLoaderClass({ query: sql.type( From b4932bc9ee44c9f0d578b0dbed5c36c540845296 Mon Sep 17 00:00:00 2001 From: Gajus Date: Mon, 13 May 2024 12:36:11 -0600 Subject: [PATCH 21/22] wip --- .github/workflows/feature.yaml | 2 +- .github/workflows/main.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/feature.yaml b/.github/workflows/feature.yaml index 99edf720..96fef9f8 100644 --- a/.github/workflows/feature.yaml +++ b/.github/workflows/feature.yaml @@ -80,7 +80,7 @@ jobs: - run: npm ci - run: npm run build --workspaces --if-present - env: - POSTGRES_DSN: postgres://postgres:postgres@localhost:5432 + POSTGRES_DSN: 'postgres://postgres:postgres@localhost:5432' TEST_ONLY: '${{ matrix.test_only }}' run: npm run test --workspaces --if-present strategy: diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 4a14680f..cf4b0d60 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -88,7 +88,7 @@ jobs: - run: npm ci - run: npm run build --workspaces --if-present - env: - POSTGRES_DSN: postgres://postgres:postgres@localhost:5432 + POSTGRES_DSN: 'postgres://postgres:postgres@localhost:5432' TEST_ONLY: '${{ matrix.test_only }}' run: npm run test --workspaces --if-present strategy: From 4d5925865ff6202d6b63dae34313cca6546ca1a8 Mon Sep 17 00:00:00 2001 From: Gajus Date: Mon, 13 May 2024 12:40:37 -0600 Subject: [PATCH 22/22] wip --- .../src/factories/helpers.test/createTestRunner.ts | 9 +++++---- packages/slonik/src/helpers.test/createTestRunner.ts | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/slonik-sql-tag-raw/src/factories/helpers.test/createTestRunner.ts b/packages/slonik-sql-tag-raw/src/factories/helpers.test/createTestRunner.ts index a2eadf39..1f58a16a 100644 --- a/packages/slonik-sql-tag-raw/src/factories/helpers.test/createTestRunner.ts +++ b/packages/slonik-sql-tag-raw/src/factories/helpers.test/createTestRunner.ts @@ -3,8 +3,9 @@ import { createPool, sql } from 'slonik'; // TODO deduplicate with slonik/src/factories/createTestRunner.ts -// eslint-disable-next-line n/no-process-env -const POSTGRES_DSN = process.env.POSTGRES_DSN ?? 'postgres@localhost:5432'; +const POSTGRES_DSN = + // eslint-disable-next-line n/no-process-env + process.env.POSTGRES_DSN ?? 'postgresql://postgres:postgres@localhost:5432'; type TestContextType = { dsn: string; @@ -25,11 +26,11 @@ export const createTestRunner = () => { const TEST_DATABASE_NAME = ['slonik_test', String(testId)].join('_'); t.context = { - dsn: 'postgresql://' + POSTGRES_DSN + '/' + TEST_DATABASE_NAME, + dsn: POSTGRES_DSN + '/' + TEST_DATABASE_NAME, testDatabaseName: TEST_DATABASE_NAME, }; - const pool0 = await createPool('postgresql://' + POSTGRES_DSN, { + const pool0 = await createPool(POSTGRES_DSN, { maximumPoolSize: 1, }); diff --git a/packages/slonik/src/helpers.test/createTestRunner.ts b/packages/slonik/src/helpers.test/createTestRunner.ts index da77596a..28100333 100644 --- a/packages/slonik/src/helpers.test/createTestRunner.ts +++ b/packages/slonik/src/helpers.test/createTestRunner.ts @@ -3,8 +3,9 @@ import { createPool } from '../factories/createPool'; import { type DriverFactory } from '@slonik/driver'; import anyTest, { type TestFn } from 'ava'; -// eslint-disable-next-line n/no-process-env -const POSTGRES_DSN = process.env.POSTGRES_DSN ?? 'postgres@localhost:5432'; +const POSTGRES_DSN = + // eslint-disable-next-line n/no-process-env + process.env.POSTGRES_DSN ?? 'postgresql://postgres:postgres@localhost:5432'; export type TestContextType = { dsn: string; @@ -28,11 +29,11 @@ export const createTestRunner = ( const TEST_DATABASE_NAME = ['slonik_test', name, String(testId)].join('_'); t.context = { - dsn: 'postgresql://' + POSTGRES_DSN + '/' + TEST_DATABASE_NAME, + dsn: POSTGRES_DSN + '/' + TEST_DATABASE_NAME, testDatabaseName: TEST_DATABASE_NAME, }; - const pool0 = await createPool('postgresql://' + POSTGRES_DSN, { + const pool0 = await createPool(POSTGRES_DSN, { driverFactory, maximumPoolSize: 1, });