From ad99e1f9708546a09e9164a53f7cfe5d752b5858 Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Wed, 3 May 2023 15:19:53 -0700 Subject: [PATCH 01/11] add serde for pnpm lockfile --- .../fixtures/pnpm6-workspace.yaml | 1704 ++++++++ .../fixtures/pnpm7-workspace.yaml | 3445 +++++++++++++++++ .../turborepo-lockfiles/fixtures/pnpm8.yaml | 107 + crates/turborepo-lockfiles/src/lib.rs | 1 + crates/turborepo-lockfiles/src/pnpm/mod.rs | 190 + 5 files changed, 5447 insertions(+) create mode 100644 crates/turborepo-lockfiles/fixtures/pnpm6-workspace.yaml create mode 100644 crates/turborepo-lockfiles/fixtures/pnpm7-workspace.yaml create mode 100644 crates/turborepo-lockfiles/fixtures/pnpm8.yaml create mode 100644 crates/turborepo-lockfiles/src/pnpm/mod.rs diff --git a/crates/turborepo-lockfiles/fixtures/pnpm6-workspace.yaml b/crates/turborepo-lockfiles/fixtures/pnpm6-workspace.yaml new file mode 100644 index 0000000000000..daf92b79118b0 --- /dev/null +++ b/crates/turborepo-lockfiles/fixtures/pnpm6-workspace.yaml @@ -0,0 +1,1704 @@ +lockfileVersion: 5.3 + +importers: + .: + specifiers: + "@pnpm/make-dedicated-lockfile": ^0.3.19 + devDependencies: + "@pnpm/make-dedicated-lockfile": 0.3.19 + + packages/a: + specifiers: + b: workspace:* + express: ^4.18.1 + dependencies: + b: link:../b + express: 4.18.1 + + packages/b: + specifiers: + c: workspace:* + lodash: ^4.17.21 + dependencies: + c: link:../c + lodash: 4.17.21 + + packages/c: + specifiers: + chalk: ^5.0.1 + dependencies: + chalk: 5.0.1 + +packages: + /@babel/code-frame/7.18.6: + resolution: + { + integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==, + } + engines: { node: ">=6.9.0" } + dependencies: + "@babel/highlight": 7.18.6 + dev: true + + /@babel/helper-validator-identifier/7.18.6: + resolution: + { + integrity: sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==, + } + engines: { node: ">=6.9.0" } + dev: true + + /@babel/highlight/7.18.6: + resolution: + { + integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==, + } + engines: { node: ">=6.9.0" } + dependencies: + "@babel/helper-validator-identifier": 7.18.6 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + + /@pnpm/constants/6.1.0: + resolution: + { + integrity: sha512-L6AiU3OXv9kjKGTJN9j8n1TeJGDcLX9atQlZvAkthlvbXjvKc5SKNWESc/eXhr5nEfuMWhQhiKHDJCpYejmeCQ==, + } + engines: { node: ">=14.19" } + dev: true + + /@pnpm/crypto.base32-hash/1.0.1: + resolution: + { + integrity: sha512-pzAXNn6KxTA3kbcI3iEnYs4vtH51XEVqmK/1EiD18MaPKylhqy8UvMJK3zKG+jeP82cqQbozcTGm4yOQ8i3vNw==, + } + engines: { node: ">=14.6" } + dependencies: + rfc4648: 1.5.2 + dev: true + + /@pnpm/error/3.0.1: + resolution: + { + integrity: sha512-hMlbWbFcfcfolNfSjKjpeaZFow71kNg438LZ8rAd01swiVIYRUf/sRv8gGySru6AijYfz5UqslpIJRDbYBkgQA==, + } + engines: { node: ">=14.19" } + dependencies: + "@pnpm/constants": 6.1.0 + dev: true + + /@pnpm/exec/2.0.0: + resolution: + { + integrity: sha512-b5ALfWEOFQprWKntN7MF8XWCyslBk2c8u20GEDcDDQOs6c0HyHlWxX5lig8riQKdS000U6YyS4L4b32NOleXAQ==, + } + engines: { node: ">=10" } + dependencies: + "@pnpm/self-installer": 2.2.1 + command-exists: 1.2.9 + cross-spawn: 7.0.3 + dev: true + + /@pnpm/exportable-manifest/3.1.2: + resolution: + { + integrity: sha512-IvTBwt3n73pXsU6iS1Y4OipBg3GBN37I/mUR8t3q5N0c5TkVxj9xAsra5/m7mX4dsYCv9BPL6Rw+MuKSV5P1hA==, + } + engines: { node: ">=14.6" } + dependencies: + "@pnpm/error": 3.0.1 + "@pnpm/read-project-manifest": 3.0.9 + "@pnpm/types": 8.5.0 + ramda: /@pnpm/ramda/0.28.1 + dev: true + + /@pnpm/find-workspace-dir/4.0.2: + resolution: + { + integrity: sha512-gU7ycFSWuEGJh7RE/STa33Ch27geODTXIfc+ntiE1BietxfpJIAk34zz51kTUuCFthBkpHlO6yV7jgHD2Tuc3g==, + } + engines: { node: ">=14.6" } + dependencies: + "@pnpm/error": 3.0.1 + find-up: 5.0.0 + dev: true + + /@pnpm/git-utils/0.1.0: + resolution: + { + integrity: sha512-W3zsG9585cKL+FqgcT+IfTgZX5C+CbNkFjOnJN+qbysT1N30+BbvEByCcDMsTy7QDrAk6oS7WU1Rym3U2xlh2Q==, + } + engines: { node: ">=14.6" } + dependencies: + execa: /safe-execa/0.1.2 + dev: true + + /@pnpm/graceful-fs/2.0.0: + resolution: + { + integrity: sha512-ogUZCGf0/UILZt6d8PsO4gA4pXh7f0BumXeFkcCe4AQ65PXPKfAkHC0C30Lheh2EgFOpLZm3twDP1Eiww18gew==, + } + engines: { node: ">=14.19" } + dependencies: + graceful-fs: 4.2.10 + dev: true + + /@pnpm/lockfile-file/5.3.3_@pnpm+logger@4.0.0: + resolution: + { + integrity: sha512-IOvjeMRX+++osG9VsfSd7+hVa/sIzhqdrm/nFcL7AexFhC7wjXbWW3YMlN5Cw4v0fwm93fgRZlikIKJ7BmkBBA==, + } + engines: { node: ">=14.6" } + peerDependencies: + "@pnpm/logger": ^4.0.0 + dependencies: + "@pnpm/constants": 6.1.0 + "@pnpm/error": 3.0.1 + "@pnpm/git-utils": 0.1.0 + "@pnpm/lockfile-types": 4.3.1 + "@pnpm/logger": 4.0.0 + "@pnpm/merge-lockfile-changes": 3.0.9 + "@pnpm/types": 8.5.0 + "@zkochan/rimraf": 2.1.2 + comver-to-semver: 1.0.0 + js-yaml: /@zkochan/js-yaml/0.0.6 + normalize-path: 3.0.0 + ramda: /@pnpm/ramda/0.28.1 + semver: 7.3.7 + sort-keys: 4.2.0 + strip-bom: 4.0.0 + write-file-atomic: 3.0.3 + dev: true + + /@pnpm/lockfile-types/4.3.1: + resolution: + { + integrity: sha512-xoorF+CuuUvpjfi8Uw/xkf8LI9VDzs9W1gjSxkKS8UwK60zU5fu4agILJfVVGlHO1tnjJeGRuspBjp7UZ8ufMA==, + } + engines: { node: ">=14.6" } + dependencies: + "@pnpm/types": 8.5.0 + dev: true + + /@pnpm/logger/4.0.0: + resolution: + { + integrity: sha512-SIShw+k556e7S7tLZFVSIHjCdiVog1qWzcKW2RbLEHPItdisAFVNIe34kYd9fMSswTlSRLS/qRjw3ZblzWmJ9Q==, + } + engines: { node: ">=12.17" } + dependencies: + bole: 4.0.1 + ndjson: 2.0.0 + dev: true + + /@pnpm/make-dedicated-lockfile/0.3.19: + resolution: + { + integrity: sha512-VHllqMh5zviSHds2kOlWSiwmxos3LLGWCVIHpo+HX45D3TXx+oMOgE8k6WB0dSOTVIuGKduoCNTGeSW4p2bD2w==, + } + engines: { node: ">=14.6" } + hasBin: true + dependencies: + "@pnpm/error": 3.0.1 + "@pnpm/exec": 2.0.0 + "@pnpm/exportable-manifest": 3.1.2 + "@pnpm/find-workspace-dir": 4.0.2 + "@pnpm/lockfile-file": 5.3.3_@pnpm+logger@4.0.0 + "@pnpm/logger": 4.0.0 + "@pnpm/prune-lockfile": 4.0.14 + "@pnpm/read-project-manifest": 3.0.9 + "@pnpm/types": 8.5.0 + ramda: /@pnpm/ramda/0.28.1 + rename-overwrite: 4.0.2 + dev: true + + /@pnpm/merge-lockfile-changes/3.0.9: + resolution: + { + integrity: sha512-UOl3AYsi13R8bvQNJPNUml8sZYKBRns0xjAcPQomoX3WTU0dv+KzVyv86Iv86YlApP0aJj9MS8Vq++JOC10RKg==, + } + engines: { node: ">=14.6" } + dependencies: + "@pnpm/lockfile-types": 4.3.1 + comver-to-semver: 1.0.0 + ramda: /@pnpm/ramda/0.28.1 + semver: 7.3.7 + dev: true + + /@pnpm/prune-lockfile/4.0.14: + resolution: + { + integrity: sha512-lICCgm9j3e2Bu75zK4PA1FKjpu9pCcagRbZWruONBf44byyEkHcnTf8b8a9M1MvtoiArhmKOmyOVJ2OFyBBRyA==, + } + engines: { node: ">=14.6" } + dependencies: + "@pnpm/constants": 6.1.0 + "@pnpm/lockfile-types": 4.3.1 + "@pnpm/types": 8.5.0 + dependency-path: 9.2.4 + ramda: /@pnpm/ramda/0.28.1 + dev: true + + /@pnpm/ramda/0.28.1: + resolution: + { + integrity: sha512-zcAG+lvU0fMziNeGXpPyCyCJYp5ZVrPElEE4t14jAmViaihohocZ+dDkcRIyAomox8pQsuZnv1EyHR+pOhmUWw==, + } + dev: true + + /@pnpm/read-project-manifest/3.0.9: + resolution: + { + integrity: sha512-27j40C48hA/tqsCiqk9ApJxp2g6WGrrj2RSs0NKhsSHynxAuA1tIvwatNISQbAiMjZiu1lfhzhq8m1QdblyNmA==, + } + engines: { node: ">=14.6" } + dependencies: + "@pnpm/error": 3.0.1 + "@pnpm/graceful-fs": 2.0.0 + "@pnpm/types": 8.5.0 + "@pnpm/write-project-manifest": 3.0.7 + detect-indent: 6.1.0 + fast-deep-equal: 3.1.3 + is-windows: 1.0.2 + json5: 2.2.1 + parse-json: 5.2.0 + read-yaml-file: 2.1.0 + sort-keys: 4.2.0 + strip-bom: 4.0.0 + dev: true + + /@pnpm/self-installer/2.2.1: + resolution: + { + integrity: sha512-aefLe96wAWghkx6q1PwbVS1Iz1iGE+HKwkTmtzWLFXeGhbknaIdG2voMwaBGIYGCSxm8sDKR1uLO4aRRAYuc+Q==, + } + engines: { node: ">=4" } + hasBin: true + dev: true + + /@pnpm/types/8.5.0: + resolution: + { + integrity: sha512-PSKnhkwgiZtp9dcWZR9mPz2W9UopmADr9o8FTqazo5kjUSh2xQmDUSJOJ/ZWcfNziO64Ix/VbcxKIZeplhog1Q==, + } + engines: { node: ">=14.6" } + dev: true + + /@pnpm/write-project-manifest/3.0.7: + resolution: + { + integrity: sha512-rMgIWR52asESg1D7Cp/vBi3dBsv18iUWPvvtYNynrcOjRdE3NsH5CAdfZP/XN6HJF6CSY8rS9W4YC5Q3JGtxiw==, + } + engines: { node: ">=14.6" } + dependencies: + "@pnpm/types": 8.5.0 + json5: 2.2.1 + write-file-atomic: 3.0.3 + write-yaml-file: 4.2.0 + dev: true + + /@zkochan/js-yaml/0.0.6: + resolution: + { + integrity: sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==, + } + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /@zkochan/rimraf/2.1.2: + resolution: + { + integrity: sha512-Lc2oK51J6aQWcLWTloobJun5ZF41BbTDdLvE+aMcexoVWFoFqvZmnZoyXR2IZk6NJEVoZW8tjgtvQLfTsmRs2Q==, + } + engines: { node: ">=12.10" } + dependencies: + rimraf: 3.0.2 + dev: true + + /@zkochan/which/2.0.3: + resolution: + { + integrity: sha512-C1ReN7vt2/2O0fyTsx5xnbQuxBrmG5NMSbcIkPKCCfCTJgpZBsuRYzFXHj3nVq8vTfK7vxHUmzfCpSHgO7j4rg==, + } + engines: { node: ">= 8" } + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /accepts/1.3.8: + resolution: + { + integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==, + } + engines: { node: ">= 0.6" } + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + dev: false + + /ansi-styles/3.2.1: + resolution: + { + integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==, + } + engines: { node: ">=4" } + dependencies: + color-convert: 1.9.3 + dev: true + + /argparse/2.0.1: + resolution: + { + integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==, + } + dev: true + + /array-flatten/1.1.1: + resolution: + { + integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==, + } + dev: false + + /balanced-match/1.0.2: + resolution: + { + integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==, + } + dev: true + + /body-parser/1.20.0: + resolution: + { + integrity: sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==, + } + engines: { node: ">= 0.8", npm: 1.2.8000 || >= 1.4.16 } + dependencies: + bytes: 3.1.2 + content-type: 1.0.4 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.10.3 + raw-body: 2.5.1 + type-is: 1.6.18 + unpipe: 1.0.0 + dev: false + + /bole/4.0.1: + resolution: + { + integrity: sha512-42r0aSOJFJti2l6LasBHq2BuWJzohGs349olQnH/ETlJo87XnoWw7UT8pGE6UstjxzOKkwz7tjoFcmSr6L16vg==, + } + dependencies: + fast-safe-stringify: 2.1.1 + individual: 3.0.0 + dev: true + + /brace-expansion/1.1.11: + resolution: + { + integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==, + } + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /bytes/3.1.2: + resolution: + { + integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==, + } + engines: { node: ">= 0.8" } + dev: false + + /call-bind/1.0.2: + resolution: + { + integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==, + } + dependencies: + function-bind: 1.1.1 + get-intrinsic: 1.1.2 + dev: false + + /chalk/2.4.2: + resolution: + { + integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==, + } + engines: { node: ">=4" } + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk/5.0.1: + resolution: + { + integrity: sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==, + } + engines: { node: ^12.17.0 || ^14.13 || >=16.0.0 } + dev: false + + /color-convert/1.9.3: + resolution: + { + integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==, + } + dependencies: + color-name: 1.1.3 + dev: true + + /color-name/1.1.3: + resolution: + { + integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==, + } + dev: true + + /command-exists/1.2.9: + resolution: + { + integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==, + } + dev: true + + /comver-to-semver/1.0.0: + resolution: + { + integrity: sha512-gcGtbRxjwROQOdXLUWH1fQAXqThUVRZ219aAwgtX3KfYw429/Zv6EIJRf5TBSzWdAGwePmqH7w70WTaX4MDqag==, + } + engines: { node: ">=12.17" } + dev: true + + /concat-map/0.0.1: + resolution: + { + integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==, + } + dev: true + + /content-disposition/0.5.4: + resolution: + { + integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==, + } + engines: { node: ">= 0.6" } + dependencies: + safe-buffer: 5.2.1 + dev: false + + /content-type/1.0.4: + resolution: + { + integrity: sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==, + } + engines: { node: ">= 0.6" } + dev: false + + /cookie-signature/1.0.6: + resolution: + { + integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==, + } + dev: false + + /cookie/0.5.0: + resolution: + { + integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==, + } + engines: { node: ">= 0.6" } + dev: false + + /cross-spawn/7.0.3: + resolution: + { + integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==, + } + engines: { node: ">= 8" } + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /debug/2.6.9: + resolution: + { + integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==, + } + dependencies: + ms: 2.0.0 + dev: false + + /depd/2.0.0: + resolution: + { + integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==, + } + engines: { node: ">= 0.8" } + dev: false + + /dependency-path/9.2.4: + resolution: + { + integrity: sha512-bH29ZcKyo/i5nr4SgnVZGksuoZzroOWpHtKbq8fKdKgJDr0SdUIPu2EwjJkjzbw9SqRzWd912e0opHYJTkFf6w==, + } + engines: { node: ">=14.6" } + dependencies: + "@pnpm/crypto.base32-hash": 1.0.1 + "@pnpm/types": 8.5.0 + encode-registry: 3.0.0 + semver: 7.3.7 + dev: true + + /destroy/1.2.0: + resolution: + { + integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==, + } + engines: { node: ">= 0.8", npm: 1.2.8000 || >= 1.4.16 } + dev: false + + /detect-indent/6.1.0: + resolution: + { + integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==, + } + engines: { node: ">=8" } + dev: true + + /ee-first/1.1.1: + resolution: + { + integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==, + } + dev: false + + /encode-registry/3.0.0: + resolution: + { + integrity: sha512-2fRYji8K6FwYuQ6EPBKR/J9mcqb7kIoNqt1vGvJr3NrvKfncRiNm00Oxo6gi/YJF8R5Sp2bNFSFdGKTG0rje1Q==, + } + engines: { node: ">=10" } + dependencies: + mem: 8.1.1 + dev: true + + /encodeurl/1.0.2: + resolution: + { + integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==, + } + engines: { node: ">= 0.8" } + dev: false + + /error-ex/1.3.2: + resolution: + { + integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==, + } + dependencies: + is-arrayish: 0.2.1 + dev: true + + /escape-html/1.0.3: + resolution: + { + integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==, + } + dev: false + + /escape-string-regexp/1.0.5: + resolution: + { + integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==, + } + engines: { node: ">=0.8.0" } + dev: true + + /etag/1.8.1: + resolution: + { + integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==, + } + engines: { node: ">= 0.6" } + dev: false + + /execa/5.1.1: + resolution: + { + integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==, + } + engines: { node: ">=10" } + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + + /express/4.18.1: + resolution: + { + integrity: sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==, + } + engines: { node: ">= 0.10.0" } + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.0 + content-disposition: 0.5.4 + content-type: 1.0.4 + cookie: 0.5.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.7 + qs: 6.10.3 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + dev: false + + /fast-deep-equal/3.1.3: + resolution: + { + integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, + } + dev: true + + /fast-safe-stringify/2.1.1: + resolution: + { + integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==, + } + dev: true + + /finalhandler/1.2.0: + resolution: + { + integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==, + } + engines: { node: ">= 0.8" } + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + dev: false + + /find-up/5.0.0: + resolution: + { + integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==, + } + engines: { node: ">=10" } + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /forwarded/0.2.0: + resolution: + { + integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==, + } + engines: { node: ">= 0.6" } + dev: false + + /fresh/0.5.2: + resolution: + { + integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==, + } + engines: { node: ">= 0.6" } + dev: false + + /fs.realpath/1.0.0: + resolution: + { + integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==, + } + dev: true + + /function-bind/1.1.1: + resolution: + { + integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==, + } + dev: false + + /get-intrinsic/1.1.2: + resolution: + { + integrity: sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==, + } + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-symbols: 1.0.3 + dev: false + + /get-stream/6.0.1: + resolution: + { + integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==, + } + engines: { node: ">=10" } + dev: true + + /glob/7.2.3: + resolution: + { + integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==, + } + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /graceful-fs/4.2.10: + resolution: + { + integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==, + } + dev: true + + /has-flag/3.0.0: + resolution: + { + integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==, + } + engines: { node: ">=4" } + dev: true + + /has-symbols/1.0.3: + resolution: + { + integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==, + } + engines: { node: ">= 0.4" } + dev: false + + /has/1.0.3: + resolution: + { + integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==, + } + engines: { node: ">= 0.4.0" } + dependencies: + function-bind: 1.1.1 + dev: false + + /http-errors/2.0.0: + resolution: + { + integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==, + } + engines: { node: ">= 0.8" } + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + dev: false + + /human-signals/2.1.0: + resolution: + { + integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==, + } + engines: { node: ">=10.17.0" } + dev: true + + /iconv-lite/0.4.24: + resolution: + { + integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==, + } + engines: { node: ">=0.10.0" } + dependencies: + safer-buffer: 2.1.2 + dev: false + + /imurmurhash/0.1.4: + resolution: + { + integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==, + } + engines: { node: ">=0.8.19" } + dev: true + + /individual/3.0.0: + resolution: + { + integrity: sha512-rUY5vtT748NMRbEMrTNiFfy29BgGZwGXUi2NFUVMWQrogSLzlJvQV9eeMWi+g1aVaQ53tpyLAQtd5x/JH0Nh1g==, + } + dev: true + + /inflight/1.0.6: + resolution: + { + integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==, + } + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits/2.0.4: + resolution: + { + integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, + } + dev: false + + /ipaddr.js/1.9.1: + resolution: + { + integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==, + } + engines: { node: ">= 0.10" } + dev: false + + /is-arrayish/0.2.1: + resolution: + { + integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==, + } + dev: true + + /is-plain-obj/2.1.0: + resolution: + { + integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==, + } + engines: { node: ">=8" } + dev: true + + /is-stream/2.0.1: + resolution: + { + integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==, + } + engines: { node: ">=8" } + dev: true + + /is-typedarray/1.0.0: + resolution: + { + integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==, + } + dev: true + + /is-windows/1.0.2: + resolution: + { + integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==, + } + engines: { node: ">=0.10.0" } + dev: true + + /isexe/2.0.0: + resolution: + { + integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, + } + dev: true + + /js-tokens/4.0.0: + resolution: + { + integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==, + } + dev: true + + /js-yaml/4.1.0: + resolution: + { + integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==, + } + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /json-parse-even-better-errors/2.3.1: + resolution: + { + integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==, + } + dev: true + + /json-stringify-safe/5.0.1: + resolution: + { + integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==, + } + dev: true + + /json5/2.2.1: + resolution: + { + integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==, + } + engines: { node: ">=6" } + hasBin: true + dev: true + + /lines-and-columns/1.2.4: + resolution: + { + integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==, + } + dev: true + + /locate-path/6.0.0: + resolution: + { + integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==, + } + engines: { node: ">=10" } + dependencies: + p-locate: 5.0.0 + dev: true + + /lodash/4.17.21: + resolution: + { + integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==, + } + dev: false + + /lru-cache/6.0.0: + resolution: + { + integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==, + } + engines: { node: ">=10" } + dependencies: + yallist: 4.0.0 + dev: true + + /map-age-cleaner/0.1.3: + resolution: + { + integrity: sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==, + } + engines: { node: ">=6" } + dependencies: + p-defer: 1.0.0 + dev: true + + /media-typer/0.3.0: + resolution: + { + integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==, + } + engines: { node: ">= 0.6" } + dev: false + + /mem/8.1.1: + resolution: + { + integrity: sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==, + } + engines: { node: ">=10" } + dependencies: + map-age-cleaner: 0.1.3 + mimic-fn: 3.1.0 + dev: true + + /merge-descriptors/1.0.1: + resolution: + { + integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==, + } + dev: false + + /merge-stream/2.0.0: + resolution: + { + integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==, + } + dev: true + + /methods/1.1.2: + resolution: + { + integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==, + } + engines: { node: ">= 0.6" } + dev: false + + /mime-db/1.52.0: + resolution: + { + integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==, + } + engines: { node: ">= 0.6" } + dev: false + + /mime-types/2.1.35: + resolution: + { + integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==, + } + engines: { node: ">= 0.6" } + dependencies: + mime-db: 1.52.0 + dev: false + + /mime/1.6.0: + resolution: + { + integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==, + } + engines: { node: ">=4" } + hasBin: true + dev: false + + /mimic-fn/2.1.0: + resolution: + { + integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==, + } + engines: { node: ">=6" } + dev: true + + /mimic-fn/3.1.0: + resolution: + { + integrity: sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==, + } + engines: { node: ">=8" } + dev: true + + /minimatch/3.1.2: + resolution: + { + integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==, + } + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimist/1.2.6: + resolution: + { + integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==, + } + dev: true + + /ms/2.0.0: + resolution: + { + integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==, + } + dev: false + + /ms/2.1.3: + resolution: + { + integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, + } + dev: false + + /ndjson/2.0.0: + resolution: + { + integrity: sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==, + } + engines: { node: ">=10" } + hasBin: true + dependencies: + json-stringify-safe: 5.0.1 + minimist: 1.2.6 + readable-stream: 3.6.0 + split2: 3.2.2 + through2: 4.0.2 + dev: true + + /negotiator/0.6.3: + resolution: + { + integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==, + } + engines: { node: ">= 0.6" } + dev: false + + /normalize-path/3.0.0: + resolution: + { + integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==, + } + engines: { node: ">=0.10.0" } + dev: true + + /npm-run-path/4.0.1: + resolution: + { + integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==, + } + engines: { node: ">=8" } + dependencies: + path-key: 3.1.1 + dev: true + + /object-inspect/1.12.2: + resolution: + { + integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==, + } + dev: false + + /on-finished/2.4.1: + resolution: + { + integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==, + } + engines: { node: ">= 0.8" } + dependencies: + ee-first: 1.1.1 + dev: false + + /once/1.4.0: + resolution: + { + integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==, + } + dependencies: + wrappy: 1.0.2 + dev: true + + /onetime/5.1.2: + resolution: + { + integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==, + } + engines: { node: ">=6" } + dependencies: + mimic-fn: 2.1.0 + dev: true + + /p-defer/1.0.0: + resolution: + { + integrity: sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==, + } + engines: { node: ">=4" } + dev: true + + /p-limit/3.1.0: + resolution: + { + integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==, + } + engines: { node: ">=10" } + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate/5.0.0: + resolution: + { + integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==, + } + engines: { node: ">=10" } + dependencies: + p-limit: 3.1.0 + dev: true + + /parse-json/5.2.0: + resolution: + { + integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==, + } + engines: { node: ">=8" } + dependencies: + "@babel/code-frame": 7.18.6 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /parseurl/1.3.3: + resolution: + { + integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==, + } + engines: { node: ">= 0.8" } + dev: false + + /path-exists/4.0.0: + resolution: + { + integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==, + } + engines: { node: ">=8" } + dev: true + + /path-is-absolute/1.0.1: + resolution: + { + integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==, + } + engines: { node: ">=0.10.0" } + dev: true + + /path-key/3.1.1: + resolution: + { + integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==, + } + engines: { node: ">=8" } + dev: true + + /path-name/1.0.0: + resolution: + { + integrity: sha512-/dcAb5vMXH0f51yvMuSUqFpxUcA8JelbRmE5mW/p4CUJxrNgK24IkstnV7ENtg2IDGBOu6izKTG6eilbnbNKWQ==, + } + dev: true + + /path-to-regexp/0.1.7: + resolution: + { + integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==, + } + dev: false + + /proxy-addr/2.0.7: + resolution: + { + integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==, + } + engines: { node: ">= 0.10" } + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + dev: false + + /qs/6.10.3: + resolution: + { + integrity: sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==, + } + engines: { node: ">=0.6" } + dependencies: + side-channel: 1.0.4 + dev: false + + /range-parser/1.2.1: + resolution: + { + integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==, + } + engines: { node: ">= 0.6" } + dev: false + + /raw-body/2.5.1: + resolution: + { + integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==, + } + engines: { node: ">= 0.8" } + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: false + + /read-yaml-file/2.1.0: + resolution: + { + integrity: sha512-UkRNRIwnhG+y7hpqnycCL/xbTk7+ia9VuVTC0S+zVbwd65DI9eUpRMfsWIGrCWxTU/mi+JW8cHQCrv+zfCbEPQ==, + } + engines: { node: ">=10.13" } + dependencies: + js-yaml: 4.1.0 + strip-bom: 4.0.0 + dev: true + + /readable-stream/3.6.0: + resolution: + { + integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==, + } + engines: { node: ">= 6" } + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: true + + /rename-overwrite/4.0.2: + resolution: + { + integrity: sha512-L1sgBgagVgOgb1Z6QZr1yJgSMHI4SXQqAH0l/UbeyHnLKxECvKIlyVEmBo4BqsCAZGg0SBSyjCh68lis5PgC7g==, + } + engines: { node: ">=12.10" } + dependencies: + "@zkochan/rimraf": 2.1.2 + dev: true + + /rfc4648/1.5.2: + resolution: + { + integrity: sha512-tLOizhR6YGovrEBLatX1sdcuhoSCXddw3mqNVAcKxGJ+J0hFeJ+SjeWCv5UPA/WU3YzWPPuCVYgXBKZUPGpKtg==, + } + dev: true + + /rimraf/3.0.2: + resolution: + { + integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==, + } + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /safe-buffer/5.2.1: + resolution: + { + integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==, + } + dev: false + + /safe-execa/0.1.2: + resolution: + { + integrity: sha512-vdTshSQ2JsRCgT8eKZWNJIL26C6bVqy1SOmuCMlKHegVeo8KYRobRrefOdUq9OozSPUUiSxrylteeRmLOMFfWg==, + } + engines: { node: ">=12" } + dependencies: + "@zkochan/which": 2.0.3 + execa: 5.1.1 + path-name: 1.0.0 + dev: true + + /safer-buffer/2.1.2: + resolution: + { + integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==, + } + dev: false + + /semver/7.3.7: + resolution: + { + integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==, + } + engines: { node: ">=10" } + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /send/0.18.0: + resolution: + { + integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==, + } + engines: { node: ">= 0.8.0" } + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + dev: false + + /serve-static/1.15.0: + resolution: + { + integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==, + } + engines: { node: ">= 0.8.0" } + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.18.0 + dev: false + + /setprototypeof/1.2.0: + resolution: + { + integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==, + } + dev: false + + /shebang-command/2.0.0: + resolution: + { + integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==, + } + engines: { node: ">=8" } + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex/3.0.0: + resolution: + { + integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==, + } + engines: { node: ">=8" } + dev: true + + /side-channel/1.0.4: + resolution: + { + integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==, + } + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.1.2 + object-inspect: 1.12.2 + dev: false + + /signal-exit/3.0.7: + resolution: + { + integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==, + } + dev: true + + /sort-keys/4.2.0: + resolution: + { + integrity: sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==, + } + engines: { node: ">=8" } + dependencies: + is-plain-obj: 2.1.0 + dev: true + + /split2/3.2.2: + resolution: + { + integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==, + } + dependencies: + readable-stream: 3.6.0 + dev: true + + /statuses/2.0.1: + resolution: + { + integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==, + } + engines: { node: ">= 0.8" } + dev: false + + /string_decoder/1.3.0: + resolution: + { + integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==, + } + dependencies: + safe-buffer: 5.2.1 + dev: true + + /strip-bom/4.0.0: + resolution: + { + integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==, + } + engines: { node: ">=8" } + dev: true + + /strip-final-newline/2.0.0: + resolution: + { + integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==, + } + engines: { node: ">=6" } + dev: true + + /supports-color/5.5.0: + resolution: + { + integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==, + } + engines: { node: ">=4" } + dependencies: + has-flag: 3.0.0 + dev: true + + /through2/4.0.2: + resolution: + { + integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==, + } + dependencies: + readable-stream: 3.6.0 + dev: true + + /toidentifier/1.0.1: + resolution: + { + integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==, + } + engines: { node: ">=0.6" } + dev: false + + /type-is/1.6.18: + resolution: + { + integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==, + } + engines: { node: ">= 0.6" } + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + dev: false + + /typedarray-to-buffer/3.1.5: + resolution: + { + integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==, + } + dependencies: + is-typedarray: 1.0.0 + dev: true + + /unpipe/1.0.0: + resolution: + { + integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==, + } + engines: { node: ">= 0.8" } + dev: false + + /util-deprecate/1.0.2: + resolution: + { + integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==, + } + dev: true + + /utils-merge/1.0.1: + resolution: + { + integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==, + } + engines: { node: ">= 0.4.0" } + dev: false + + /vary/1.1.2: + resolution: + { + integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==, + } + engines: { node: ">= 0.8" } + dev: false + + /which/2.0.2: + resolution: + { + integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==, + } + engines: { node: ">= 8" } + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /wrappy/1.0.2: + resolution: + { + integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, + } + dev: true + + /write-file-atomic/3.0.3: + resolution: + { + integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==, + } + dependencies: + imurmurhash: 0.1.4 + is-typedarray: 1.0.0 + signal-exit: 3.0.7 + typedarray-to-buffer: 3.1.5 + dev: true + + /write-yaml-file/4.2.0: + resolution: + { + integrity: sha512-LwyucHy0uhWqbrOkh9cBluZBeNVxzHjDaE9mwepZG3n3ZlbM4v3ndrFw51zW/NXYFFqP+QWZ72ihtLWTh05e4Q==, + } + engines: { node: ">=10.13" } + dependencies: + js-yaml: 4.1.0 + write-file-atomic: 3.0.3 + dev: true + + /yallist/4.0.0: + resolution: + { + integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==, + } + dev: true + + /yocto-queue/0.1.0: + resolution: + { + integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==, + } + engines: { node: ">=10" } + dev: true diff --git a/crates/turborepo-lockfiles/fixtures/pnpm7-workspace.yaml b/crates/turborepo-lockfiles/fixtures/pnpm7-workspace.yaml new file mode 100644 index 0000000000000..2f7b66319bcbc --- /dev/null +++ b/crates/turborepo-lockfiles/fixtures/pnpm7-workspace.yaml @@ -0,0 +1,3445 @@ +lockfileVersion: 5.4 + +patchedDependencies: + lodash@4.17.21: + hash: ehchni3mpmovsvjxesffg2i5a4 + path: patches/lodash@4.17.21.patch + underscore@1.13.4: + hash: 3pbfs36izefyn2uycmknwkvuuy + path: patches/underscore@1.13.4.patch + +importers: + .: + specifiers: + eslint-config-custom: workspace:* + prettier: latest + turbo: latest + devDependencies: + eslint-config-custom: link:packages/eslint-config-custom + prettier: 2.7.1 + turbo: 1.4.6 + + apps/docs: + specifiers: + "@babel/core": ^7.0.0 + "@types/node": ^17.0.12 + "@types/react": 18.0.17 + dashboard-icons: github:peerigon/dashboard-icons + eslint: 7.32.0 + eslint-config-custom: workspace:* + next: 12.2.5 + next-transpile-modules: 9.0.0 + react: 18.2.0 + react-dom: 18.2.0 + tsconfig: workspace:* + typescript: ^4.5.3 + ui: workspace:* + underscore: ^1.13.4 + dependencies: + dashboard-icons: github.com/peerigon/dashboard-icons/ce27ef933144e09cef3911025f3649040a8571b6 + next: 12.2.5_ir3quccc6i62x6qn6jjhyjjiey + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + ui: file:packages/ui + underscore: 1.13.4_3pbfs36izefyn2uycmknwkvuuy + devDependencies: + "@babel/core": 7.19.1 + "@types/node": 17.0.45 + "@types/react": 18.0.17 + eslint: 7.32.0 + eslint-config-custom: link:../../packages/eslint-config-custom + next-transpile-modules: 9.0.0 + tsconfig: link:../../packages/tsconfig + typescript: 4.8.3 + dependenciesMeta: + ui: + injected: true + + apps/web: + specifiers: + "@babel/core": ^7.0.0 + "@types/node": ^17.0.12 + "@types/react": 18.0.17 + eslint: 7.32.0 + eslint-config-custom: workspace:* + lodash: ^4.17.21 + next: 12.2.5 + next-transpile-modules: 9.0.0 + react: 18.2.0 + react-dom: 18.2.0 + tsconfig: workspace:* + typescript: ^4.5.3 + ui: workspace:* + dependencies: + lodash: 4.17.21_ehchni3mpmovsvjxesffg2i5a4 + next: 12.2.5_ir3quccc6i62x6qn6jjhyjjiey + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + ui: link:../../packages/ui + devDependencies: + "@babel/core": 7.19.1 + "@types/node": 17.0.45 + "@types/react": 18.0.17 + eslint: 7.32.0 + eslint-config-custom: link:../../packages/eslint-config-custom + next-transpile-modules: 9.0.0 + tsconfig: link:../../packages/tsconfig + typescript: 4.8.3 + + packages/eslint-config-custom: + specifiers: + eslint: ^7.23.0 + eslint-config-next: ^12.0.8 + eslint-config-prettier: ^8.3.0 + eslint-config-turbo: latest + eslint-plugin-react: 7.31.7 + typescript: ^4.7.4 + dependencies: + eslint: 7.32.0 + eslint-config-next: 12.3.0_dyxdave6dwjbccc5dgiifcmuza + eslint-config-prettier: 8.5.0_eslint@7.32.0 + eslint-config-turbo: 0.0.3_eslint@7.32.0 + eslint-plugin-react: 7.31.7_eslint@7.32.0 + devDependencies: + typescript: 4.8.3 + + packages/tsconfig: + specifiers: {} + + packages/ui: + specifiers: + "@types/react": ^18.0.17 + "@types/react-dom": ^18.0.6 + eslint: ^7.32.0 + eslint-config-custom: workspace:* + react: ^18.2.0 + tsconfig: workspace:* + typescript: ^4.5.2 + devDependencies: + "@types/react": 18.0.20 + "@types/react-dom": 18.0.6 + eslint: 7.32.0 + eslint-config-custom: link:../eslint-config-custom + react: 18.2.0 + tsconfig: link:../tsconfig + typescript: 4.8.3 + +packages: + /@ampproject/remapping/2.2.0: + resolution: + { + integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==, + } + engines: { node: ">=6.0.0" } + dependencies: + "@jridgewell/gen-mapping": 0.1.1 + "@jridgewell/trace-mapping": 0.3.15 + + /@babel/code-frame/7.12.11: + resolution: + { + integrity: sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==, + } + dependencies: + "@babel/highlight": 7.18.6 + + /@babel/code-frame/7.18.6: + resolution: + { + integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==, + } + engines: { node: ">=6.9.0" } + dependencies: + "@babel/highlight": 7.18.6 + + /@babel/compat-data/7.19.1: + resolution: + { + integrity: sha512-72a9ghR0gnESIa7jBN53U32FOVCEoztyIlKaNoU05zRhEecduGK9L9c3ww7Mp06JiR+0ls0GBPFJQwwtjn9ksg==, + } + engines: { node: ">=6.9.0" } + + /@babel/core/7.19.1: + resolution: + { + integrity: sha512-1H8VgqXme4UXCRv7/Wa1bq7RVymKOzC7znjyFM8KiEzwFqcKUKYNoQef4GhdklgNvoBXyW4gYhuBNCM5o1zImw==, + } + engines: { node: ">=6.9.0" } + dependencies: + "@ampproject/remapping": 2.2.0 + "@babel/code-frame": 7.18.6 + "@babel/generator": 7.19.0 + "@babel/helper-compilation-targets": 7.19.1_@babel+core@7.19.1 + "@babel/helper-module-transforms": 7.19.0 + "@babel/helpers": 7.19.0 + "@babel/parser": 7.19.1 + "@babel/template": 7.18.10 + "@babel/traverse": 7.19.1 + "@babel/types": 7.19.0 + convert-source-map: 1.8.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.1 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + + /@babel/generator/7.19.0: + resolution: + { + integrity: sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==, + } + engines: { node: ">=6.9.0" } + dependencies: + "@babel/types": 7.19.0 + "@jridgewell/gen-mapping": 0.3.2 + jsesc: 2.5.2 + + /@babel/helper-compilation-targets/7.19.1_@babel+core@7.19.1: + resolution: + { + integrity: sha512-LlLkkqhCMyz2lkQPvJNdIYU7O5YjWRgC2R4omjCTpZd8u8KMQzZvX4qce+/BluN1rcQiV7BoGUpmQ0LeHerbhg==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0 + dependencies: + "@babel/compat-data": 7.19.1 + "@babel/core": 7.19.1 + "@babel/helper-validator-option": 7.18.6 + browserslist: 4.21.3 + semver: 6.3.0 + + /@babel/helper-environment-visitor/7.18.9: + resolution: + { + integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==, + } + engines: { node: ">=6.9.0" } + + /@babel/helper-function-name/7.19.0: + resolution: + { + integrity: sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==, + } + engines: { node: ">=6.9.0" } + dependencies: + "@babel/template": 7.18.10 + "@babel/types": 7.19.0 + + /@babel/helper-hoist-variables/7.18.6: + resolution: + { + integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==, + } + engines: { node: ">=6.9.0" } + dependencies: + "@babel/types": 7.19.0 + + /@babel/helper-module-imports/7.18.6: + resolution: + { + integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==, + } + engines: { node: ">=6.9.0" } + dependencies: + "@babel/types": 7.19.0 + + /@babel/helper-module-transforms/7.19.0: + resolution: + { + integrity: sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==, + } + engines: { node: ">=6.9.0" } + dependencies: + "@babel/helper-environment-visitor": 7.18.9 + "@babel/helper-module-imports": 7.18.6 + "@babel/helper-simple-access": 7.18.6 + "@babel/helper-split-export-declaration": 7.18.6 + "@babel/helper-validator-identifier": 7.19.1 + "@babel/template": 7.18.10 + "@babel/traverse": 7.19.1 + "@babel/types": 7.19.0 + transitivePeerDependencies: + - supports-color + + /@babel/helper-simple-access/7.18.6: + resolution: + { + integrity: sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==, + } + engines: { node: ">=6.9.0" } + dependencies: + "@babel/types": 7.19.0 + + /@babel/helper-split-export-declaration/7.18.6: + resolution: + { + integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==, + } + engines: { node: ">=6.9.0" } + dependencies: + "@babel/types": 7.19.0 + + /@babel/helper-string-parser/7.18.10: + resolution: + { + integrity: sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==, + } + engines: { node: ">=6.9.0" } + + /@babel/helper-validator-identifier/7.19.1: + resolution: + { + integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==, + } + engines: { node: ">=6.9.0" } + + /@babel/helper-validator-option/7.18.6: + resolution: + { + integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==, + } + engines: { node: ">=6.9.0" } + + /@babel/helpers/7.19.0: + resolution: + { + integrity: sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==, + } + engines: { node: ">=6.9.0" } + dependencies: + "@babel/template": 7.18.10 + "@babel/traverse": 7.19.1 + "@babel/types": 7.19.0 + transitivePeerDependencies: + - supports-color + + /@babel/highlight/7.18.6: + resolution: + { + integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==, + } + engines: { node: ">=6.9.0" } + dependencies: + "@babel/helper-validator-identifier": 7.19.1 + chalk: 2.4.2 + js-tokens: 4.0.0 + + /@babel/parser/7.19.1: + resolution: + { + integrity: sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==, + } + engines: { node: ">=6.0.0" } + hasBin: true + dependencies: + "@babel/types": 7.19.0 + + /@babel/runtime-corejs3/7.19.1: + resolution: + { + integrity: sha512-j2vJGnkopRzH+ykJ8h68wrHnEUmtK//E723jjixiAl/PPf6FhqY/vYRcMVlNydRKQjQsTsYEjpx+DZMIvnGk/g==, + } + engines: { node: ">=6.9.0" } + dependencies: + core-js-pure: 3.25.1 + regenerator-runtime: 0.13.9 + dev: false + + /@babel/runtime/7.19.0: + resolution: + { + integrity: sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==, + } + engines: { node: ">=6.9.0" } + dependencies: + regenerator-runtime: 0.13.9 + dev: false + + /@babel/template/7.18.10: + resolution: + { + integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==, + } + engines: { node: ">=6.9.0" } + dependencies: + "@babel/code-frame": 7.18.6 + "@babel/parser": 7.19.1 + "@babel/types": 7.19.0 + + /@babel/traverse/7.19.1: + resolution: + { + integrity: sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA==, + } + engines: { node: ">=6.9.0" } + dependencies: + "@babel/code-frame": 7.18.6 + "@babel/generator": 7.19.0 + "@babel/helper-environment-visitor": 7.18.9 + "@babel/helper-function-name": 7.19.0 + "@babel/helper-hoist-variables": 7.18.6 + "@babel/helper-split-export-declaration": 7.18.6 + "@babel/parser": 7.19.1 + "@babel/types": 7.19.0 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + /@babel/types/7.19.0: + resolution: + { + integrity: sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==, + } + engines: { node: ">=6.9.0" } + dependencies: + "@babel/helper-string-parser": 7.18.10 + "@babel/helper-validator-identifier": 7.19.1 + to-fast-properties: 2.0.0 + + /@eslint/eslintrc/0.4.3: + resolution: + { + integrity: sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==, + } + engines: { node: ^10.12.0 || >=12.0.0 } + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 7.3.1 + globals: 13.17.0 + ignore: 4.0.6 + import-fresh: 3.3.0 + js-yaml: 3.14.1 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + /@humanwhocodes/config-array/0.5.0: + resolution: + { + integrity: sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==, + } + engines: { node: ">=10.10.0" } + dependencies: + "@humanwhocodes/object-schema": 1.2.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + /@humanwhocodes/object-schema/1.2.1: + resolution: + { + integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==, + } + + /@jridgewell/gen-mapping/0.1.1: + resolution: + { + integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==, + } + engines: { node: ">=6.0.0" } + dependencies: + "@jridgewell/set-array": 1.1.2 + "@jridgewell/sourcemap-codec": 1.4.14 + + /@jridgewell/gen-mapping/0.3.2: + resolution: + { + integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==, + } + engines: { node: ">=6.0.0" } + dependencies: + "@jridgewell/set-array": 1.1.2 + "@jridgewell/sourcemap-codec": 1.4.14 + "@jridgewell/trace-mapping": 0.3.15 + + /@jridgewell/resolve-uri/3.1.0: + resolution: + { + integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==, + } + engines: { node: ">=6.0.0" } + + /@jridgewell/set-array/1.1.2: + resolution: + { + integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==, + } + engines: { node: ">=6.0.0" } + + /@jridgewell/sourcemap-codec/1.4.14: + resolution: + { + integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==, + } + + /@jridgewell/trace-mapping/0.3.15: + resolution: + { + integrity: sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==, + } + dependencies: + "@jridgewell/resolve-uri": 3.1.0 + "@jridgewell/sourcemap-codec": 1.4.14 + + /@next/env/12.2.5: + resolution: + { + integrity: sha512-vLPLV3cpPGjUPT3PjgRj7e3nio9t6USkuew3JE/jMeon/9Mvp1WyR18v3iwnCuX7eUAm1HmAbJHHLAbcu/EJcw==, + } + dev: false + + /@next/eslint-plugin-next/12.3.0: + resolution: + { + integrity: sha512-jVdq1qYTNDjUtulnE8/hkPv0pHILV4jMg5La99iaY/FFm20WxVnsAZtbNnMvlPbf8dc010oO304SX9yXbg5PAw==, + } + dependencies: + glob: 7.1.7 + dev: false + + /@next/swc-android-arm-eabi/12.2.5: + resolution: + { + integrity: sha512-cPWClKxGhgn2dLWnspW+7psl3MoLQUcNqJqOHk2BhNcou9ARDtC0IjQkKe5qcn9qg7I7U83Gp1yh2aesZfZJMA==, + } + engines: { node: ">= 10" } + cpu: [arm] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@next/swc-android-arm64/12.2.5: + resolution: + { + integrity: sha512-vMj0efliXmC5b7p+wfcQCX0AfU8IypjkzT64GiKJD9PgiA3IILNiGJr1fw2lyUDHkjeWx/5HMlMEpLnTsQslwg==, + } + engines: { node: ">= 10" } + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@next/swc-darwin-arm64/12.2.5: + resolution: + { + integrity: sha512-VOPWbO5EFr6snla/WcxUKtvzGVShfs302TEMOtzYyWni6f9zuOetijJvVh9CCTzInnXAZMtHyNhefijA4HMYLg==, + } + engines: { node: ">= 10" } + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@next/swc-darwin-x64/12.2.5: + resolution: + { + integrity: sha512-5o8bTCgAmtYOgauO/Xd27vW52G2/m3i5PX7MUYePquxXAnX73AAtqA3WgPXBRitEB60plSKZgOTkcpqrsh546A==, + } + engines: { node: ">= 10" } + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@next/swc-freebsd-x64/12.2.5: + resolution: + { + integrity: sha512-yYUbyup1JnznMtEBRkK4LT56N0lfK5qNTzr6/DEyDw5TbFVwnuy2hhLBzwCBkScFVjpFdfiC6SQAX3FrAZzuuw==, + } + engines: { node: ">= 10" } + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /@next/swc-linux-arm-gnueabihf/12.2.5: + resolution: + { + integrity: sha512-2ZE2/G921Acks7UopJZVMgKLdm4vN4U0yuzvAMJ6KBavPzqESA2yHJlm85TV/K9gIjKhSk5BVtauIUntFRP8cg==, + } + engines: { node: ">= 10" } + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@next/swc-linux-arm64-gnu/12.2.5: + resolution: + { + integrity: sha512-/I6+PWVlz2wkTdWqhlSYYJ1pWWgUVva6SgX353oqTh8njNQp1SdFQuWDqk8LnM6ulheVfSsgkDzxrDaAQZnzjQ==, + } + engines: { node: ">= 10" } + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@next/swc-linux-arm64-musl/12.2.5: + resolution: + { + integrity: sha512-LPQRelfX6asXyVr59p5sTpx5l+0yh2Vjp/R8Wi4X9pnqcayqT4CUJLiHqCvZuLin3IsFdisJL0rKHMoaZLRfmg==, + } + engines: { node: ">= 10" } + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@next/swc-linux-x64-gnu/12.2.5: + resolution: + { + integrity: sha512-0szyAo8jMCClkjNK0hknjhmAngUppoRekW6OAezbEYwHXN/VNtsXbfzgYOqjKWxEx3OoAzrT3jLwAF0HdX2MEw==, + } + engines: { node: ">= 10" } + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@next/swc-linux-x64-musl/12.2.5: + resolution: + { + integrity: sha512-zg/Y6oBar1yVnW6Il1I/08/2ukWtOG6s3acdJdEyIdsCzyQi4RLxbbhkD/EGQyhqBvd3QrC6ZXQEXighQUAZ0g==, + } + engines: { node: ">= 10" } + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@next/swc-win32-arm64-msvc/12.2.5: + resolution: + { + integrity: sha512-3/90DRNSqeeSRMMEhj4gHHQlLhhKg5SCCoYfE3kBjGpE63EfnblYUqsszGGZ9ekpKL/R4/SGB40iCQr8tR5Jiw==, + } + engines: { node: ">= 10" } + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@next/swc-win32-ia32-msvc/12.2.5: + resolution: + { + integrity: sha512-hGLc0ZRAwnaPL4ulwpp4D2RxmkHQLuI8CFOEEHdzZpS63/hMVzv81g8jzYA0UXbb9pus/iTc3VRbVbAM03SRrw==, + } + engines: { node: ">= 10" } + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@next/swc-win32-x64-msvc/12.2.5: + resolution: + { + integrity: sha512-7h5/ahY7NeaO2xygqVrSG/Y8Vs4cdjxIjowTZ5W6CKoTKn7tmnuxlUc2h74x06FKmbhAd9agOjr/AOKyxYYm9Q==, + } + engines: { node: ">= 10" } + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@nodelib/fs.scandir/2.1.5: + resolution: + { + integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==, + } + engines: { node: ">= 8" } + dependencies: + "@nodelib/fs.stat": 2.0.5 + run-parallel: 1.2.0 + dev: false + + /@nodelib/fs.stat/2.0.5: + resolution: + { + integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==, + } + engines: { node: ">= 8" } + dev: false + + /@nodelib/fs.walk/1.2.8: + resolution: + { + integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==, + } + engines: { node: ">= 8" } + dependencies: + "@nodelib/fs.scandir": 2.1.5 + fastq: 1.13.0 + dev: false + + /@rushstack/eslint-patch/1.1.4: + resolution: + { + integrity: sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==, + } + dev: false + + /@swc/helpers/0.4.3: + resolution: + { + integrity: sha512-6JrF+fdUK2zbGpJIlN7G3v966PQjyx/dPt1T9km2wj+EUBqgrxCk3uX4Kct16MIm9gGxfKRcfax2hVf5jvlTzA==, + } + dependencies: + tslib: 2.4.0 + dev: false + + /@types/json5/0.0.29: + resolution: + { + integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==, + } + dev: false + + /@types/node/17.0.45: + resolution: + { + integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==, + } + dev: true + + /@types/prop-types/15.7.5: + resolution: + { + integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==, + } + dev: true + + /@types/react-dom/18.0.6: + resolution: + { + integrity: sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==, + } + dependencies: + "@types/react": 18.0.20 + dev: true + + /@types/react/18.0.17: + resolution: + { + integrity: sha512-38ETy4tL+rn4uQQi7mB81G7V1g0u2ryquNmsVIOKUAEIDK+3CUjZ6rSRpdvS99dNBnkLFL83qfmtLacGOTIhwQ==, + } + dependencies: + "@types/prop-types": 15.7.5 + "@types/scheduler": 0.16.2 + csstype: 3.1.1 + dev: true + + /@types/react/18.0.20: + resolution: + { + integrity: sha512-MWul1teSPxujEHVwZl4a5HxQ9vVNsjTchVA+xRqv/VYGCuKGAU6UhfrTdF5aBefwD1BHUD8i/zq+O/vyCm/FrA==, + } + dependencies: + "@types/prop-types": 15.7.5 + "@types/scheduler": 0.16.2 + csstype: 3.1.1 + dev: true + + /@types/scheduler/0.16.2: + resolution: + { + integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==, + } + dev: true + + /@typescript-eslint/parser/5.37.0_dyxdave6dwjbccc5dgiifcmuza: + resolution: + { + integrity: sha512-01VzI/ipYKuaG5PkE5+qyJ6m02fVALmMPY3Qq5BHflDx3y4VobbLdHQkSMg9VPRS4KdNt4oYTMaomFoHonBGAw==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: "*" + peerDependenciesMeta: + typescript: + optional: true + dependencies: + "@typescript-eslint/scope-manager": 5.37.0 + "@typescript-eslint/types": 5.37.0 + "@typescript-eslint/typescript-estree": 5.37.0_typescript@4.8.3 + debug: 4.3.4 + eslint: 7.32.0 + typescript: 4.8.3 + transitivePeerDependencies: + - supports-color + dev: false + + /@typescript-eslint/scope-manager/5.37.0: + resolution: + { + integrity: sha512-F67MqrmSXGd/eZnujjtkPgBQzgespu/iCZ+54Ok9X5tALb9L2v3G+QBSoWkXG0p3lcTJsL+iXz5eLUEdSiJU9Q==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + dependencies: + "@typescript-eslint/types": 5.37.0 + "@typescript-eslint/visitor-keys": 5.37.0 + dev: false + + /@typescript-eslint/types/5.37.0: + resolution: + { + integrity: sha512-3frIJiTa5+tCb2iqR/bf7XwU20lnU05r/sgPJnRpwvfZaqCJBrl8Q/mw9vr3NrNdB/XtVyMA0eppRMMBqdJ1bA==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + dev: false + + /@typescript-eslint/typescript-estree/5.37.0_typescript@4.8.3: + resolution: + { + integrity: sha512-JkFoFIt/cx59iqEDSgIGnQpCTRv96MQnXCYvJi7QhBC24uyuzbD8wVbajMB1b9x4I0octYFJ3OwjAwNqk1AjDA==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + peerDependencies: + typescript: "*" + peerDependenciesMeta: + typescript: + optional: true + dependencies: + "@typescript-eslint/types": 5.37.0 + "@typescript-eslint/visitor-keys": 5.37.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.3.7 + tsutils: 3.21.0_typescript@4.8.3 + typescript: 4.8.3 + transitivePeerDependencies: + - supports-color + dev: false + + /@typescript-eslint/visitor-keys/5.37.0: + resolution: + { + integrity: sha512-Hp7rT4cENBPIzMwrlehLW/28EVCOcE9U1Z1BQTc8EA8v5qpr7GRGuG+U58V5tTY48zvUOA3KHvw3rA8tY9fbdA==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + dependencies: + "@typescript-eslint/types": 5.37.0 + eslint-visitor-keys: 3.3.0 + dev: false + + /acorn-jsx/5.3.2_acorn@7.4.1: + resolution: + { + integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==, + } + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 7.4.1 + + /acorn/7.4.1: + resolution: + { + integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==, + } + engines: { node: ">=0.4.0" } + hasBin: true + + /ajv/6.12.6: + resolution: + { + integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==, + } + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + /ajv/8.11.0: + resolution: + { + integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==, + } + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + + /ansi-colors/4.1.3: + resolution: + { + integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==, + } + engines: { node: ">=6" } + + /ansi-regex/5.0.1: + resolution: + { + integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==, + } + engines: { node: ">=8" } + + /ansi-styles/3.2.1: + resolution: + { + integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==, + } + engines: { node: ">=4" } + dependencies: + color-convert: 1.9.3 + + /ansi-styles/4.3.0: + resolution: + { + integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==, + } + engines: { node: ">=8" } + dependencies: + color-convert: 2.0.1 + + /argparse/1.0.10: + resolution: + { + integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==, + } + dependencies: + sprintf-js: 1.0.3 + + /aria-query/4.2.2: + resolution: + { + integrity: sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==, + } + engines: { node: ">=6.0" } + dependencies: + "@babel/runtime": 7.19.0 + "@babel/runtime-corejs3": 7.19.1 + dev: false + + /array-includes/3.1.5: + resolution: + { + integrity: sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==, + } + engines: { node: ">= 0.4" } + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.2 + get-intrinsic: 1.1.3 + is-string: 1.0.7 + dev: false + + /array-union/2.1.0: + resolution: + { + integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==, + } + engines: { node: ">=8" } + dev: false + + /array.prototype.flat/1.3.0: + resolution: + { + integrity: sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==, + } + engines: { node: ">= 0.4" } + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.2 + es-shim-unscopables: 1.0.0 + dev: false + + /array.prototype.flatmap/1.3.0: + resolution: + { + integrity: sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==, + } + engines: { node: ">= 0.4" } + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.2 + es-shim-unscopables: 1.0.0 + dev: false + + /ast-types-flow/0.0.7: + resolution: + { + integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==, + } + dev: false + + /astral-regex/2.0.0: + resolution: + { + integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==, + } + engines: { node: ">=8" } + + /axe-core/4.4.3: + resolution: + { + integrity: sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==, + } + engines: { node: ">=4" } + dev: false + + /axobject-query/2.2.0: + resolution: + { + integrity: sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==, + } + dev: false + + /balanced-match/1.0.2: + resolution: + { + integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==, + } + + /brace-expansion/1.1.11: + resolution: + { + integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==, + } + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + /braces/3.0.2: + resolution: + { + integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==, + } + engines: { node: ">=8" } + dependencies: + fill-range: 7.0.1 + dev: false + + /browserslist/4.21.3: + resolution: + { + integrity: sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==, + } + engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 } + hasBin: true + dependencies: + caniuse-lite: 1.0.30001399 + electron-to-chromium: 1.4.249 + node-releases: 2.0.6 + update-browserslist-db: 1.0.9_browserslist@4.21.3 + + /call-bind/1.0.2: + resolution: + { + integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==, + } + dependencies: + function-bind: 1.1.1 + get-intrinsic: 1.1.3 + dev: false + + /callsites/3.1.0: + resolution: + { + integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==, + } + engines: { node: ">=6" } + + /caniuse-lite/1.0.30001399: + resolution: + { + integrity: sha512-4vQ90tMKS+FkvuVWS5/QY1+d805ODxZiKFzsU8o/RsVJz49ZSRR8EjykLJbqhzdPgadbX6wB538wOzle3JniRA==, + } + + /chalk/2.4.2: + resolution: + { + integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==, + } + engines: { node: ">=4" } + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + /chalk/4.1.2: + resolution: + { + integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==, + } + engines: { node: ">=10" } + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + /color-convert/1.9.3: + resolution: + { + integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==, + } + dependencies: + color-name: 1.1.3 + + /color-convert/2.0.1: + resolution: + { + integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==, + } + engines: { node: ">=7.0.0" } + dependencies: + color-name: 1.1.4 + + /color-name/1.1.3: + resolution: + { + integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==, + } + + /color-name/1.1.4: + resolution: + { + integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, + } + + /concat-map/0.0.1: + resolution: + { + integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==, + } + + /convert-source-map/1.8.0: + resolution: + { + integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==, + } + dependencies: + safe-buffer: 5.1.2 + + /core-js-pure/3.25.1: + resolution: + { + integrity: sha512-7Fr74bliUDdeJCBMxkkIuQ4xfxn/SwrVg+HkJUAoNEXVqYLv55l6Af0dJ5Lq2YBUW9yKqSkLXaS5SYPK6MGa/A==, + } + requiresBuild: true + dev: false + + /cross-spawn/7.0.3: + resolution: + { + integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==, + } + engines: { node: ">= 8" } + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + /csstype/3.1.1: + resolution: + { + integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==, + } + dev: true + + /damerau-levenshtein/1.0.8: + resolution: + { + integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==, + } + dev: false + + /debug/2.6.9: + resolution: + { + integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==, + } + peerDependencies: + supports-color: "*" + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: false + + /debug/3.2.7: + resolution: + { + integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==, + } + peerDependencies: + supports-color: "*" + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: false + + /debug/4.3.4: + resolution: + { + integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==, + } + engines: { node: ">=6.0" } + peerDependencies: + supports-color: "*" + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + + /deep-is/0.1.4: + resolution: + { + integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==, + } + + /define-properties/1.1.4: + resolution: + { + integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==, + } + engines: { node: ">= 0.4" } + dependencies: + has-property-descriptors: 1.0.0 + object-keys: 1.1.1 + dev: false + + /dir-glob/3.0.1: + resolution: + { + integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==, + } + engines: { node: ">=8" } + dependencies: + path-type: 4.0.0 + dev: false + + /doctrine/2.1.0: + resolution: + { + integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==, + } + engines: { node: ">=0.10.0" } + dependencies: + esutils: 2.0.3 + dev: false + + /doctrine/3.0.0: + resolution: + { + integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==, + } + engines: { node: ">=6.0.0" } + dependencies: + esutils: 2.0.3 + + /electron-to-chromium/1.4.249: + resolution: + { + integrity: sha512-GMCxR3p2HQvIw47A599crTKYZprqihoBL4lDSAUmr7IYekXFK5t/WgEBrGJDCa2HWIZFQEkGuMqPCi05ceYqPQ==, + } + + /emoji-regex/8.0.0: + resolution: + { + integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==, + } + + /emoji-regex/9.2.2: + resolution: + { + integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==, + } + dev: false + + /enhanced-resolve/5.10.0: + resolution: + { + integrity: sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==, + } + engines: { node: ">=10.13.0" } + dependencies: + graceful-fs: 4.2.10 + tapable: 2.2.1 + dev: true + + /enquirer/2.3.6: + resolution: + { + integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==, + } + engines: { node: ">=8.6" } + dependencies: + ansi-colors: 4.1.3 + + /es-abstract/1.20.2: + resolution: + { + integrity: sha512-XxXQuVNrySBNlEkTYJoDNFe5+s2yIOpzq80sUHEdPdQr0S5nTLz4ZPPPswNIpKseDDUS5yghX1gfLIHQZ1iNuQ==, + } + engines: { node: ">= 0.4" } + dependencies: + call-bind: 1.0.2 + es-to-primitive: 1.2.1 + function-bind: 1.1.1 + function.prototype.name: 1.1.5 + get-intrinsic: 1.1.3 + get-symbol-description: 1.0.0 + has: 1.0.3 + has-property-descriptors: 1.0.0 + has-symbols: 1.0.3 + internal-slot: 1.0.3 + is-callable: 1.2.5 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-weakref: 1.0.2 + object-inspect: 1.12.2 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.4.3 + string.prototype.trimend: 1.0.5 + string.prototype.trimstart: 1.0.5 + unbox-primitive: 1.0.2 + dev: false + + /es-shim-unscopables/1.0.0: + resolution: + { + integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==, + } + dependencies: + has: 1.0.3 + dev: false + + /es-to-primitive/1.2.1: + resolution: + { + integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==, + } + engines: { node: ">= 0.4" } + dependencies: + is-callable: 1.2.5 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: false + + /escalade/3.1.1: + resolution: + { + integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==, + } + engines: { node: ">=6" } + + /escape-string-regexp/1.0.5: + resolution: + { + integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==, + } + engines: { node: ">=0.8.0" } + + /escape-string-regexp/4.0.0: + resolution: + { + integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==, + } + engines: { node: ">=10" } + + /eslint-config-next/12.3.0_dyxdave6dwjbccc5dgiifcmuza: + resolution: + { + integrity: sha512-guHSkNyKnTBB8HU35COgAMeMV0E026BiYRYvyEVVaTOeFcnU3i1EI8/Da0Rl7H3Sgua5FEvoA0vYd2s8kdIUXg==, + } + peerDependencies: + eslint: ^7.23.0 || ^8.0.0 + typescript: ">=3.3.1" + peerDependenciesMeta: + typescript: + optional: true + dependencies: + "@next/eslint-plugin-next": 12.3.0 + "@rushstack/eslint-patch": 1.1.4 + "@typescript-eslint/parser": 5.37.0_dyxdave6dwjbccc5dgiifcmuza + eslint: 7.32.0 + eslint-import-resolver-node: 0.3.6 + eslint-import-resolver-typescript: 2.7.1_hpmu7kn6tcn2vnxpfzvv33bxmy + eslint-plugin-import: 2.26.0_xag76ci373f5hzfwsxolrbhy4a + eslint-plugin-jsx-a11y: 6.6.1_eslint@7.32.0 + eslint-plugin-react: 7.31.7_eslint@7.32.0 + eslint-plugin-react-hooks: 4.6.0_eslint@7.32.0 + typescript: 4.8.3 + transitivePeerDependencies: + - eslint-import-resolver-webpack + - supports-color + dev: false + + /eslint-config-prettier/8.5.0_eslint@7.32.0: + resolution: + { + integrity: sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==, + } + hasBin: true + peerDependencies: + eslint: ">=7.0.0" + dependencies: + eslint: 7.32.0 + dev: false + + /eslint-config-turbo/0.0.3_eslint@7.32.0: + resolution: + { + integrity: sha512-hK5MlxDugUWZV9ZKcyfNwLXrlMuM2wPgAUk51cUFBC3nXRCVmCA9uSRFBZsyAIurN1wH7mS7G1NBo5F8VkF7lQ==, + } + peerDependencies: + eslint: ^7.23.0 || ^8.0.0 + dependencies: + eslint: 7.32.0 + eslint-plugin-turbo: 0.0.3_eslint@7.32.0 + dev: false + + /eslint-import-resolver-node/0.3.6: + resolution: + { + integrity: sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==, + } + dependencies: + debug: 3.2.7 + resolve: 1.22.1 + transitivePeerDependencies: + - supports-color + dev: false + + /eslint-import-resolver-typescript/2.7.1_hpmu7kn6tcn2vnxpfzvv33bxmy: + resolution: + { + integrity: sha512-00UbgGwV8bSgUv34igBDbTOtKhqoRMy9bFjNehT40bXg6585PNIct8HhXZ0SybqB9rWtXj9crcku8ndDn/gIqQ==, + } + engines: { node: ">=4" } + peerDependencies: + eslint: "*" + eslint-plugin-import: "*" + dependencies: + debug: 4.3.4 + eslint: 7.32.0 + eslint-plugin-import: 2.26.0_xag76ci373f5hzfwsxolrbhy4a + glob: 7.2.3 + is-glob: 4.0.3 + resolve: 1.22.1 + tsconfig-paths: 3.14.1 + transitivePeerDependencies: + - supports-color + dev: false + + /eslint-module-utils/2.7.4_qk4u2ghovatg5ueomqmuln4u2e: + resolution: + { + integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==, + } + engines: { node: ">=4" } + peerDependencies: + "@typescript-eslint/parser": "*" + eslint: "*" + eslint-import-resolver-node: "*" + eslint-import-resolver-typescript: "*" + eslint-import-resolver-webpack: "*" + peerDependenciesMeta: + "@typescript-eslint/parser": + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + "@typescript-eslint/parser": 5.37.0_dyxdave6dwjbccc5dgiifcmuza + debug: 3.2.7 + eslint: 7.32.0 + eslint-import-resolver-node: 0.3.6 + eslint-import-resolver-typescript: 2.7.1_hpmu7kn6tcn2vnxpfzvv33bxmy + transitivePeerDependencies: + - supports-color + dev: false + + /eslint-plugin-import/2.26.0_xag76ci373f5hzfwsxolrbhy4a: + resolution: + { + integrity: sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==, + } + engines: { node: ">=4" } + peerDependencies: + "@typescript-eslint/parser": "*" + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + "@typescript-eslint/parser": + optional: true + dependencies: + "@typescript-eslint/parser": 5.37.0_dyxdave6dwjbccc5dgiifcmuza + array-includes: 3.1.5 + array.prototype.flat: 1.3.0 + debug: 2.6.9 + doctrine: 2.1.0 + eslint: 7.32.0 + eslint-import-resolver-node: 0.3.6 + eslint-module-utils: 2.7.4_qk4u2ghovatg5ueomqmuln4u2e + has: 1.0.3 + is-core-module: 2.10.0 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.values: 1.1.5 + resolve: 1.22.1 + tsconfig-paths: 3.14.1 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: false + + /eslint-plugin-jsx-a11y/6.6.1_eslint@7.32.0: + resolution: + { + integrity: sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q==, + } + engines: { node: ">=4.0" } + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + dependencies: + "@babel/runtime": 7.19.0 + aria-query: 4.2.2 + array-includes: 3.1.5 + ast-types-flow: 0.0.7 + axe-core: 4.4.3 + axobject-query: 2.2.0 + damerau-levenshtein: 1.0.8 + emoji-regex: 9.2.2 + eslint: 7.32.0 + has: 1.0.3 + jsx-ast-utils: 3.3.3 + language-tags: 1.0.5 + minimatch: 3.1.2 + semver: 6.3.0 + dev: false + + /eslint-plugin-react-hooks/4.6.0_eslint@7.32.0: + resolution: + { + integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==, + } + engines: { node: ">=10" } + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + dependencies: + eslint: 7.32.0 + dev: false + + /eslint-plugin-react/7.31.7_eslint@7.32.0: + resolution: + { + integrity: sha512-8NldBTeYp/kQoTV1uT0XF6HcmDqbgZ0lNPkN0wlRw8DJKXEnaWu+oh/6gt3xIhzvQ35wB2Y545fJhIbJSZ2NNw==, + } + engines: { node: ">=4" } + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + dependencies: + array-includes: 3.1.5 + array.prototype.flatmap: 1.3.0 + doctrine: 2.1.0 + eslint: 7.32.0 + estraverse: 5.3.0 + jsx-ast-utils: 3.3.3 + minimatch: 3.1.2 + object.entries: 1.1.5 + object.fromentries: 2.0.5 + object.hasown: 1.1.1 + object.values: 1.1.5 + prop-types: 15.8.1 + resolve: 2.0.0-next.4 + semver: 6.3.0 + string.prototype.matchall: 4.0.7 + dev: false + + /eslint-plugin-turbo/0.0.3_eslint@7.32.0: + resolution: + { + integrity: sha512-QjidATGxWtaB9QUrD3NocUySmsgWKZlBMFlw4kX2IIjRLAxMPwukk90h3ZTaNXyRHuaQsrEgh7hhlCZoxP0TTw==, + } + peerDependencies: + eslint: ^7.23.0 || ^8.0.0 + dependencies: + eslint: 7.32.0 + dev: false + + /eslint-scope/5.1.1: + resolution: + { + integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==, + } + engines: { node: ">=8.0.0" } + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + + /eslint-utils/2.1.0: + resolution: + { + integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==, + } + engines: { node: ">=6" } + dependencies: + eslint-visitor-keys: 1.3.0 + + /eslint-visitor-keys/1.3.0: + resolution: + { + integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==, + } + engines: { node: ">=4" } + + /eslint-visitor-keys/2.1.0: + resolution: + { + integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==, + } + engines: { node: ">=10" } + + /eslint-visitor-keys/3.3.0: + resolution: + { + integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + dev: false + + /eslint/7.32.0: + resolution: + { + integrity: sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==, + } + engines: { node: ^10.12.0 || >=12.0.0 } + hasBin: true + dependencies: + "@babel/code-frame": 7.12.11 + "@eslint/eslintrc": 0.4.3 + "@humanwhocodes/config-array": 0.5.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + enquirer: 2.3.6 + escape-string-regexp: 4.0.0 + eslint-scope: 5.1.1 + eslint-utils: 2.1.0 + eslint-visitor-keys: 2.1.0 + espree: 7.3.1 + esquery: 1.4.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + functional-red-black-tree: 1.0.1 + glob-parent: 5.1.2 + globals: 13.17.0 + ignore: 4.0.6 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + js-yaml: 3.14.1 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.1 + progress: 2.0.3 + regexpp: 3.2.0 + semver: 7.3.7 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + table: 6.8.0 + text-table: 0.2.0 + v8-compile-cache: 2.3.0 + transitivePeerDependencies: + - supports-color + + /espree/7.3.1: + resolution: + { + integrity: sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==, + } + engines: { node: ^10.12.0 || >=12.0.0 } + dependencies: + acorn: 7.4.1 + acorn-jsx: 5.3.2_acorn@7.4.1 + eslint-visitor-keys: 1.3.0 + + /esprima/4.0.1: + resolution: + { + integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==, + } + engines: { node: ">=4" } + hasBin: true + + /esquery/1.4.0: + resolution: + { + integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==, + } + engines: { node: ">=0.10" } + dependencies: + estraverse: 5.3.0 + + /esrecurse/4.3.0: + resolution: + { + integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==, + } + engines: { node: ">=4.0" } + dependencies: + estraverse: 5.3.0 + + /estraverse/4.3.0: + resolution: + { + integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==, + } + engines: { node: ">=4.0" } + + /estraverse/5.3.0: + resolution: + { + integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==, + } + engines: { node: ">=4.0" } + + /esutils/2.0.3: + resolution: + { + integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==, + } + engines: { node: ">=0.10.0" } + + /fast-deep-equal/3.1.3: + resolution: + { + integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, + } + + /fast-glob/3.2.12: + resolution: + { + integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==, + } + engines: { node: ">=8.6.0" } + dependencies: + "@nodelib/fs.stat": 2.0.5 + "@nodelib/fs.walk": 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: false + + /fast-json-stable-stringify/2.1.0: + resolution: + { + integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==, + } + + /fast-levenshtein/2.0.6: + resolution: + { + integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==, + } + + /fastq/1.13.0: + resolution: + { + integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==, + } + dependencies: + reusify: 1.0.4 + dev: false + + /file-entry-cache/6.0.1: + resolution: + { + integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==, + } + engines: { node: ^10.12.0 || >=12.0.0 } + dependencies: + flat-cache: 3.0.4 + + /fill-range/7.0.1: + resolution: + { + integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==, + } + engines: { node: ">=8" } + dependencies: + to-regex-range: 5.0.1 + dev: false + + /flat-cache/3.0.4: + resolution: + { + integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==, + } + engines: { node: ^10.12.0 || >=12.0.0 } + dependencies: + flatted: 3.2.7 + rimraf: 3.0.2 + + /flatted/3.2.7: + resolution: + { + integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==, + } + + /fs.realpath/1.0.0: + resolution: + { + integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==, + } + + /function-bind/1.1.1: + resolution: + { + integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==, + } + dev: false + + /function.prototype.name/1.1.5: + resolution: + { + integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==, + } + engines: { node: ">= 0.4" } + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.2 + functions-have-names: 1.2.3 + dev: false + + /functional-red-black-tree/1.0.1: + resolution: + { + integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==, + } + + /functions-have-names/1.2.3: + resolution: + { + integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==, + } + dev: false + + /gensync/1.0.0-beta.2: + resolution: + { + integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==, + } + engines: { node: ">=6.9.0" } + + /get-intrinsic/1.1.3: + resolution: + { + integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==, + } + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-symbols: 1.0.3 + dev: false + + /get-symbol-description/1.0.0: + resolution: + { + integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==, + } + engines: { node: ">= 0.4" } + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.1.3 + dev: false + + /glob-parent/5.1.2: + resolution: + { + integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==, + } + engines: { node: ">= 6" } + dependencies: + is-glob: 4.0.3 + + /glob/7.1.7: + resolution: + { + integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==, + } + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: false + + /glob/7.2.3: + resolution: + { + integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==, + } + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + /globals/11.12.0: + resolution: + { + integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==, + } + engines: { node: ">=4" } + + /globals/13.17.0: + resolution: + { + integrity: sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==, + } + engines: { node: ">=8" } + dependencies: + type-fest: 0.20.2 + + /globby/11.1.0: + resolution: + { + integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==, + } + engines: { node: ">=10" } + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.2.12 + ignore: 5.2.0 + merge2: 1.4.1 + slash: 3.0.0 + dev: false + + /graceful-fs/4.2.10: + resolution: + { + integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==, + } + dev: true + + /has-bigints/1.0.2: + resolution: + { + integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==, + } + dev: false + + /has-flag/3.0.0: + resolution: + { + integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==, + } + engines: { node: ">=4" } + + /has-flag/4.0.0: + resolution: + { + integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==, + } + engines: { node: ">=8" } + + /has-property-descriptors/1.0.0: + resolution: + { + integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==, + } + dependencies: + get-intrinsic: 1.1.3 + dev: false + + /has-symbols/1.0.3: + resolution: + { + integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==, + } + engines: { node: ">= 0.4" } + dev: false + + /has-tostringtag/1.0.0: + resolution: + { + integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==, + } + engines: { node: ">= 0.4" } + dependencies: + has-symbols: 1.0.3 + dev: false + + /has/1.0.3: + resolution: + { + integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==, + } + engines: { node: ">= 0.4.0" } + dependencies: + function-bind: 1.1.1 + dev: false + + /ignore/4.0.6: + resolution: + { + integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==, + } + engines: { node: ">= 4" } + + /ignore/5.2.0: + resolution: + { + integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==, + } + engines: { node: ">= 4" } + dev: false + + /import-fresh/3.3.0: + resolution: + { + integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==, + } + engines: { node: ">=6" } + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + /imurmurhash/0.1.4: + resolution: + { + integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==, + } + engines: { node: ">=0.8.19" } + + /inflight/1.0.6: + resolution: + { + integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==, + } + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + /inherits/2.0.4: + resolution: + { + integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, + } + + /internal-slot/1.0.3: + resolution: + { + integrity: sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==, + } + engines: { node: ">= 0.4" } + dependencies: + get-intrinsic: 1.1.3 + has: 1.0.3 + side-channel: 1.0.4 + dev: false + + /is-bigint/1.0.4: + resolution: + { + integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==, + } + dependencies: + has-bigints: 1.0.2 + dev: false + + /is-boolean-object/1.1.2: + resolution: + { + integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==, + } + engines: { node: ">= 0.4" } + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: false + + /is-callable/1.2.5: + resolution: + { + integrity: sha512-ZIWRujF6MvYGkEuHMYtFRkL2wAtFw89EHfKlXrkPkjQZZRWeh9L1q3SV13NIfHnqxugjLvAOkEHx9mb1zcMnEw==, + } + engines: { node: ">= 0.4" } + dev: false + + /is-core-module/2.10.0: + resolution: + { + integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==, + } + dependencies: + has: 1.0.3 + dev: false + + /is-date-object/1.0.5: + resolution: + { + integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==, + } + engines: { node: ">= 0.4" } + dependencies: + has-tostringtag: 1.0.0 + dev: false + + /is-extglob/2.1.1: + resolution: + { + integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==, + } + engines: { node: ">=0.10.0" } + + /is-fullwidth-code-point/3.0.0: + resolution: + { + integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==, + } + engines: { node: ">=8" } + + /is-glob/4.0.3: + resolution: + { + integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==, + } + engines: { node: ">=0.10.0" } + dependencies: + is-extglob: 2.1.1 + + /is-negative-zero/2.0.2: + resolution: + { + integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==, + } + engines: { node: ">= 0.4" } + dev: false + + /is-number-object/1.0.7: + resolution: + { + integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==, + } + engines: { node: ">= 0.4" } + dependencies: + has-tostringtag: 1.0.0 + dev: false + + /is-number/7.0.0: + resolution: + { + integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==, + } + engines: { node: ">=0.12.0" } + dev: false + + /is-regex/1.1.4: + resolution: + { + integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==, + } + engines: { node: ">= 0.4" } + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: false + + /is-shared-array-buffer/1.0.2: + resolution: + { + integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==, + } + dependencies: + call-bind: 1.0.2 + dev: false + + /is-string/1.0.7: + resolution: + { + integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==, + } + engines: { node: ">= 0.4" } + dependencies: + has-tostringtag: 1.0.0 + dev: false + + /is-symbol/1.0.4: + resolution: + { + integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==, + } + engines: { node: ">= 0.4" } + dependencies: + has-symbols: 1.0.3 + dev: false + + /is-weakref/1.0.2: + resolution: + { + integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==, + } + dependencies: + call-bind: 1.0.2 + dev: false + + /isexe/2.0.0: + resolution: + { + integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, + } + + /js-tokens/4.0.0: + resolution: + { + integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==, + } + + /js-yaml/3.14.1: + resolution: + { + integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==, + } + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + /jsesc/2.5.2: + resolution: + { + integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==, + } + engines: { node: ">=4" } + hasBin: true + + /json-schema-traverse/0.4.1: + resolution: + { + integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==, + } + + /json-schema-traverse/1.0.0: + resolution: + { + integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==, + } + + /json-stable-stringify-without-jsonify/1.0.1: + resolution: + { + integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==, + } + + /json5/1.0.1: + resolution: + { + integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==, + } + hasBin: true + dependencies: + minimist: 1.2.6 + dev: false + + /json5/2.2.1: + resolution: + { + integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==, + } + engines: { node: ">=6" } + hasBin: true + + /jsx-ast-utils/3.3.3: + resolution: + { + integrity: sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==, + } + engines: { node: ">=4.0" } + dependencies: + array-includes: 3.1.5 + object.assign: 4.1.4 + dev: false + + /language-subtag-registry/0.3.22: + resolution: + { + integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==, + } + dev: false + + /language-tags/1.0.5: + resolution: + { + integrity: sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==, + } + dependencies: + language-subtag-registry: 0.3.22 + dev: false + + /levn/0.4.1: + resolution: + { + integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==, + } + engines: { node: ">= 0.8.0" } + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + /lodash.merge/4.6.2: + resolution: + { + integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==, + } + + /lodash.truncate/4.4.2: + resolution: + { + integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==, + } + + /lodash/4.17.21_ehchni3mpmovsvjxesffg2i5a4: + resolution: + { + integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==, + } + dev: false + patched: true + + /loose-envify/1.4.0: + resolution: + { + integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==, + } + hasBin: true + dependencies: + js-tokens: 4.0.0 + + /lru-cache/6.0.0: + resolution: + { + integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==, + } + engines: { node: ">=10" } + dependencies: + yallist: 4.0.0 + + /merge2/1.4.1: + resolution: + { + integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==, + } + engines: { node: ">= 8" } + dev: false + + /micromatch/4.0.5: + resolution: + { + integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==, + } + engines: { node: ">=8.6" } + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: false + + /minimatch/3.1.2: + resolution: + { + integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==, + } + dependencies: + brace-expansion: 1.1.11 + + /minimist/1.2.6: + resolution: + { + integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==, + } + dev: false + + /ms/2.0.0: + resolution: + { + integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==, + } + dev: false + + /ms/2.1.2: + resolution: + { + integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==, + } + + /ms/2.1.3: + resolution: + { + integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, + } + dev: false + + /nanoid/3.3.4: + resolution: + { + integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==, + } + engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } + hasBin: true + dev: false + + /natural-compare/1.4.0: + resolution: + { + integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==, + } + + /next-transpile-modules/9.0.0: + resolution: + { + integrity: sha512-VCNFOazIAnXn1hvgYYSTYMnoWgKgwlYh4lm1pKbSfiB3kj5ZYLcKVhfh3jkPOg1cnd9DP+pte9yCUocdPEUBTQ==, + } + dependencies: + enhanced-resolve: 5.10.0 + escalade: 3.1.1 + dev: true + + /next/12.2.5_ir3quccc6i62x6qn6jjhyjjiey: + resolution: + { + integrity: sha512-tBdjqX5XC/oFs/6gxrZhjmiq90YWizUYU6qOWAfat7zJwrwapJ+BYgX2PmiacunXMaRpeVT4vz5MSPSLgNkrpA==, + } + engines: { node: ">=12.22.0" } + hasBin: true + peerDependencies: + fibers: ">= 3.1.0" + node-sass: ^6.0.0 || ^7.0.0 + react: ^17.0.2 || ^18.0.0-0 + react-dom: ^17.0.2 || ^18.0.0-0 + sass: ^1.3.0 + peerDependenciesMeta: + fibers: + optional: true + node-sass: + optional: true + sass: + optional: true + dependencies: + "@next/env": 12.2.5 + "@swc/helpers": 0.4.3 + caniuse-lite: 1.0.30001399 + postcss: 8.4.14 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + styled-jsx: 5.0.4_3toe27fv7etiytxb5kxc7fxaw4 + use-sync-external-store: 1.2.0_react@18.2.0 + optionalDependencies: + "@next/swc-android-arm-eabi": 12.2.5 + "@next/swc-android-arm64": 12.2.5 + "@next/swc-darwin-arm64": 12.2.5 + "@next/swc-darwin-x64": 12.2.5 + "@next/swc-freebsd-x64": 12.2.5 + "@next/swc-linux-arm-gnueabihf": 12.2.5 + "@next/swc-linux-arm64-gnu": 12.2.5 + "@next/swc-linux-arm64-musl": 12.2.5 + "@next/swc-linux-x64-gnu": 12.2.5 + "@next/swc-linux-x64-musl": 12.2.5 + "@next/swc-win32-arm64-msvc": 12.2.5 + "@next/swc-win32-ia32-msvc": 12.2.5 + "@next/swc-win32-x64-msvc": 12.2.5 + transitivePeerDependencies: + - "@babel/core" + - babel-plugin-macros + dev: false + + /node-releases/2.0.6: + resolution: + { + integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==, + } + + /object-assign/4.1.1: + resolution: + { + integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==, + } + engines: { node: ">=0.10.0" } + dev: false + + /object-inspect/1.12.2: + resolution: + { + integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==, + } + dev: false + + /object-keys/1.1.1: + resolution: + { + integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==, + } + engines: { node: ">= 0.4" } + dev: false + + /object.assign/4.1.4: + resolution: + { + integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==, + } + engines: { node: ">= 0.4" } + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: false + + /object.entries/1.1.5: + resolution: + { + integrity: sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==, + } + engines: { node: ">= 0.4" } + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.2 + dev: false + + /object.fromentries/2.0.5: + resolution: + { + integrity: sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==, + } + engines: { node: ">= 0.4" } + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.2 + dev: false + + /object.hasown/1.1.1: + resolution: + { + integrity: sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==, + } + dependencies: + define-properties: 1.1.4 + es-abstract: 1.20.2 + dev: false + + /object.values/1.1.5: + resolution: + { + integrity: sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==, + } + engines: { node: ">= 0.4" } + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.2 + dev: false + + /once/1.4.0: + resolution: + { + integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==, + } + dependencies: + wrappy: 1.0.2 + + /optionator/0.9.1: + resolution: + { + integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==, + } + engines: { node: ">= 0.8.0" } + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.3 + + /parent-module/1.0.1: + resolution: + { + integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==, + } + engines: { node: ">=6" } + dependencies: + callsites: 3.1.0 + + /path-is-absolute/1.0.1: + resolution: + { + integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==, + } + engines: { node: ">=0.10.0" } + + /path-key/3.1.1: + resolution: + { + integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==, + } + engines: { node: ">=8" } + + /path-parse/1.0.7: + resolution: + { + integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==, + } + dev: false + + /path-type/4.0.0: + resolution: + { + integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==, + } + engines: { node: ">=8" } + dev: false + + /picocolors/1.0.0: + resolution: + { + integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==, + } + + /picomatch/2.3.1: + resolution: + { + integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==, + } + engines: { node: ">=8.6" } + dev: false + + /postcss/8.4.14: + resolution: + { + integrity: sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==, + } + engines: { node: ^10 || ^12 || >=14 } + dependencies: + nanoid: 3.3.4 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: false + + /prelude-ls/1.2.1: + resolution: + { + integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==, + } + engines: { node: ">= 0.8.0" } + + /prettier/2.7.1: + resolution: + { + integrity: sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==, + } + engines: { node: ">=10.13.0" } + hasBin: true + dev: true + + /progress/2.0.3: + resolution: + { + integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==, + } + engines: { node: ">=0.4.0" } + + /prop-types/15.8.1: + resolution: + { + integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==, + } + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + dev: false + + /punycode/2.1.1: + resolution: + { + integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==, + } + engines: { node: ">=6" } + + /queue-microtask/1.2.3: + resolution: + { + integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==, + } + dev: false + + /react-dom/18.2.0_react@18.2.0: + resolution: + { + integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==, + } + peerDependencies: + react: ^18.2.0 + dependencies: + loose-envify: 1.4.0 + react: 18.2.0 + scheduler: 0.23.0 + dev: false + + /react-is/16.13.1: + resolution: + { + integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==, + } + dev: false + + /react/18.2.0: + resolution: + { + integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==, + } + engines: { node: ">=0.10.0" } + dependencies: + loose-envify: 1.4.0 + + /regenerator-runtime/0.13.9: + resolution: + { + integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==, + } + dev: false + + /regexp.prototype.flags/1.4.3: + resolution: + { + integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==, + } + engines: { node: ">= 0.4" } + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + functions-have-names: 1.2.3 + dev: false + + /regexpp/3.2.0: + resolution: + { + integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==, + } + engines: { node: ">=8" } + + /require-from-string/2.0.2: + resolution: + { + integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==, + } + engines: { node: ">=0.10.0" } + + /resolve-from/4.0.0: + resolution: + { + integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==, + } + engines: { node: ">=4" } + + /resolve/1.22.1: + resolution: + { + integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==, + } + hasBin: true + dependencies: + is-core-module: 2.10.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: false + + /resolve/2.0.0-next.4: + resolution: + { + integrity: sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==, + } + hasBin: true + dependencies: + is-core-module: 2.10.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: false + + /reusify/1.0.4: + resolution: + { + integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==, + } + engines: { iojs: ">=1.0.0", node: ">=0.10.0" } + dev: false + + /rimraf/3.0.2: + resolution: + { + integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==, + } + hasBin: true + dependencies: + glob: 7.2.3 + + /run-parallel/1.2.0: + resolution: + { + integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==, + } + dependencies: + queue-microtask: 1.2.3 + dev: false + + /safe-buffer/5.1.2: + resolution: + { + integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==, + } + + /scheduler/0.23.0: + resolution: + { + integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==, + } + dependencies: + loose-envify: 1.4.0 + dev: false + + /semver/6.3.0: + resolution: + { + integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==, + } + hasBin: true + + /semver/7.3.7: + resolution: + { + integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==, + } + engines: { node: ">=10" } + hasBin: true + dependencies: + lru-cache: 6.0.0 + + /shebang-command/2.0.0: + resolution: + { + integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==, + } + engines: { node: ">=8" } + dependencies: + shebang-regex: 3.0.0 + + /shebang-regex/3.0.0: + resolution: + { + integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==, + } + engines: { node: ">=8" } + + /side-channel/1.0.4: + resolution: + { + integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==, + } + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.1.3 + object-inspect: 1.12.2 + dev: false + + /slash/3.0.0: + resolution: + { + integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==, + } + engines: { node: ">=8" } + dev: false + + /slice-ansi/4.0.0: + resolution: + { + integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==, + } + engines: { node: ">=10" } + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + + /source-map-js/1.0.2: + resolution: + { + integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==, + } + engines: { node: ">=0.10.0" } + dev: false + + /sprintf-js/1.0.3: + resolution: + { + integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==, + } + + /string-width/4.2.3: + resolution: + { + integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==, + } + engines: { node: ">=8" } + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + /string.prototype.matchall/4.0.7: + resolution: + { + integrity: sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==, + } + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.2 + get-intrinsic: 1.1.3 + has-symbols: 1.0.3 + internal-slot: 1.0.3 + regexp.prototype.flags: 1.4.3 + side-channel: 1.0.4 + dev: false + + /string.prototype.trimend/1.0.5: + resolution: + { + integrity: sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==, + } + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.2 + dev: false + + /string.prototype.trimstart/1.0.5: + resolution: + { + integrity: sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==, + } + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.2 + dev: false + + /strip-ansi/6.0.1: + resolution: + { + integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==, + } + engines: { node: ">=8" } + dependencies: + ansi-regex: 5.0.1 + + /strip-bom/3.0.0: + resolution: + { + integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==, + } + engines: { node: ">=4" } + dev: false + + /strip-json-comments/3.1.1: + resolution: + { + integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==, + } + engines: { node: ">=8" } + + /styled-jsx/5.0.4_3toe27fv7etiytxb5kxc7fxaw4: + resolution: + { + integrity: sha512-sDFWLbg4zR+UkNzfk5lPilyIgtpddfxXEULxhujorr5jtePTUqiPDc5BC0v1NRqTr/WaFBGQQUoYToGlF4B2KQ==, + } + engines: { node: ">= 12.0.0" } + peerDependencies: + "@babel/core": "*" + babel-plugin-macros: "*" + react: ">= 16.8.0 || 17.x.x || ^18.0.0-0" + peerDependenciesMeta: + "@babel/core": + optional: true + babel-plugin-macros: + optional: true + dependencies: + "@babel/core": 7.19.1 + react: 18.2.0 + dev: false + + /supports-color/5.5.0: + resolution: + { + integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==, + } + engines: { node: ">=4" } + dependencies: + has-flag: 3.0.0 + + /supports-color/7.2.0: + resolution: + { + integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==, + } + engines: { node: ">=8" } + dependencies: + has-flag: 4.0.0 + + /supports-preserve-symlinks-flag/1.0.0: + resolution: + { + integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==, + } + engines: { node: ">= 0.4" } + dev: false + + /table/6.8.0: + resolution: + { + integrity: sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==, + } + engines: { node: ">=10.0.0" } + dependencies: + ajv: 8.11.0 + lodash.truncate: 4.4.2 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + /tapable/2.2.1: + resolution: + { + integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==, + } + engines: { node: ">=6" } + dev: true + + /text-table/0.2.0: + resolution: + { + integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==, + } + + /to-fast-properties/2.0.0: + resolution: + { + integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==, + } + engines: { node: ">=4" } + + /to-regex-range/5.0.1: + resolution: + { + integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==, + } + engines: { node: ">=8.0" } + dependencies: + is-number: 7.0.0 + dev: false + + /tsconfig-paths/3.14.1: + resolution: + { + integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==, + } + dependencies: + "@types/json5": 0.0.29 + json5: 1.0.1 + minimist: 1.2.6 + strip-bom: 3.0.0 + dev: false + + /tslib/1.14.1: + resolution: + { + integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==, + } + dev: false + + /tslib/2.4.0: + resolution: + { + integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==, + } + dev: false + + /tsutils/3.21.0_typescript@4.8.3: + resolution: + { + integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==, + } + engines: { node: ">= 6" } + peerDependencies: + typescript: ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + dependencies: + tslib: 1.14.1 + typescript: 4.8.3 + dev: false + + /turbo-android-arm64/1.4.6: + resolution: + { + integrity: sha512-YxSlHc64CF5J7yNUMiLBHkeLyzrpe75Oy7tivWb3z7ySG44BXPikk4HDJZPh0T1ELvukDwuPKkvDukJ2oCLJpA==, + } + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /turbo-darwin-64/1.4.6: + resolution: + { + integrity: sha512-f6uto7LLpjwZ6iZSF+8uaDpuiTji6xmnWDxNuW23DBE8iv5mxehHd+6Ys851uKDRrPb3QdCu9ctyigKTAla5Vg==, + } + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /turbo-darwin-arm64/1.4.6: + resolution: + { + integrity: sha512-o9C6e5XyuMHQwE0fEhUxfpXxvNr2QXXWX8nxIjygxeF19AqKbk/s08vZBOEmXV6/gx/pRhZ1S2nf0PIUjKBD/Q==, + } + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /turbo-freebsd-64/1.4.6: + resolution: + { + integrity: sha512-Gg9VOUo6McXYKGevcYjGUSmMryZyZggvpdPh7Dw3QTcT8Tsy6OBtq6WnJ2O4kFDsMigyKtEOJPceD9vDMZt3yQ==, + } + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /turbo-freebsd-arm64/1.4.6: + resolution: + { + integrity: sha512-W7VrcneWFN1QENKt5cpAPSsf9ArYBBAm3VtPBZEO5tX8kuahGlah1SKdKJXrRxYOY82wyNxDagS/rHpBlrAAzw==, + } + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /turbo-linux-32/1.4.6: + resolution: + { + integrity: sha512-76j/zsui6mWPX8pZVMGgF8eiKHPmKuGa2lo0A/Ja0HUvdYCOGUfHsWJGVVIeYbuEp3jsKyVt7OnMDeH9CqO6bg==, + } + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /turbo-linux-64/1.4.6: + resolution: + { + integrity: sha512-z4A37Xm7lZyO9ddtGnvQHWMrsAKX6vFBxdbtb9MY76VRblo7lWSuk4LwCeM+T+ZDJ9LBFiF7aD/diRShlLx9jA==, + } + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /turbo-linux-arm/1.4.6: + resolution: + { + integrity: sha512-Uh/V3oaAdhyZW6FKPpKihAxQo3EbvLaVNnzzkBmBnvHRkqoDJHhpuG72V7nn8pzxVbJ1++NEVjvbc2kmKFvGjg==, + } + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /turbo-linux-arm64/1.4.6: + resolution: + { + integrity: sha512-FW1jmOpZfOoVVvml338N0MPnYjiMyYWTaMb4T+IosgGYymcUE3xJjfXJcqfU/9/uKTyY8zG0qr9/5rw2kpMS2Q==, + } + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /turbo-linux-mips64le/1.4.6: + resolution: + { + integrity: sha512-iWaL3Pwj52BH3T2M8nXScmbSnq4+x47MYK7lJMG7FsZGAIoT5ToO1Wt1iX3GRHTcnIZYm/kCfJ1ptK/NCossLA==, + } + cpu: [mipsel] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /turbo-linux-ppc64le/1.4.6: + resolution: + { + integrity: sha512-Af/KlUmpiORDyELxT7byXNWl3fefErGQMJfeqXEtAdhs8OCKQWuU+lchcZbiBZYNpL+lZoa3PAmP9Fpx7R4plA==, + } + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /turbo-windows-32/1.4.6: + resolution: + { + integrity: sha512-NBd+XPlRSaR//lVN13Q9DOqK3CbowSvafIyGsO4jfvMsGTdyNDL6AYtFsvTKW91/G7ZhATmSEkPn2pZRuhP/DA==, + } + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /turbo-windows-64/1.4.6: + resolution: + { + integrity: sha512-86AbmG+CjzVTpn4RGtwU2CYy4zSyAc9bIQ4pDGLIpCJg6JlD11duaiMJh0SCU/HCqWLJjWDI4qD+f9WNbgPsyQ==, + } + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /turbo-windows-arm64/1.4.6: + resolution: + { + integrity: sha512-V+pWcqhTtmQQ3ew8qEjYtUwzyW6tO1RgvP+6OKzItYzTnMTr1Fe42Q21V+tqRNxuNfFDKsgVJdk2p5wB87bvyQ==, + } + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /turbo/1.4.6: + resolution: + { + integrity: sha512-FKtBXlOJ7YjSK22yj4sJLCtDcHFElypt7xw9cZN7Wyv9x4XBrTmh5KP6RmcGnRR1/GJlTNwD2AY2T9QTPnHh+g==, + } + hasBin: true + requiresBuild: true + optionalDependencies: + turbo-android-arm64: 1.4.6 + turbo-darwin-64: 1.4.6 + turbo-darwin-arm64: 1.4.6 + turbo-freebsd-64: 1.4.6 + turbo-freebsd-arm64: 1.4.6 + turbo-linux-32: 1.4.6 + turbo-linux-64: 1.4.6 + turbo-linux-arm: 1.4.6 + turbo-linux-arm64: 1.4.6 + turbo-linux-mips64le: 1.4.6 + turbo-linux-ppc64le: 1.4.6 + turbo-windows-32: 1.4.6 + turbo-windows-64: 1.4.6 + turbo-windows-arm64: 1.4.6 + dev: true + + /type-check/0.4.0: + resolution: + { + integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==, + } + engines: { node: ">= 0.8.0" } + dependencies: + prelude-ls: 1.2.1 + + /type-fest/0.20.2: + resolution: + { + integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==, + } + engines: { node: ">=10" } + + /typescript/4.8.3: + resolution: + { + integrity: sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==, + } + engines: { node: ">=4.2.0" } + hasBin: true + + /unbox-primitive/1.0.2: + resolution: + { + integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==, + } + dependencies: + call-bind: 1.0.2 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: false + + /underscore/1.13.4_3pbfs36izefyn2uycmknwkvuuy: + resolution: + { + integrity: sha512-BQFnUDuAQ4Yf/cYY5LNrK9NCJFKriaRbD9uR1fTeXnBeoa97W0i41qkZfGO9pSo8I5KzjAcSY2XYtdf0oKd7KQ==, + } + dev: false + patched: true + + /update-browserslist-db/1.0.9_browserslist@4.21.3: + resolution: + { + integrity: sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==, + } + hasBin: true + peerDependencies: + browserslist: ">= 4.21.0" + dependencies: + browserslist: 4.21.3 + escalade: 3.1.1 + picocolors: 1.0.0 + + /uri-js/4.4.1: + resolution: + { + integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==, + } + dependencies: + punycode: 2.1.1 + + /use-sync-external-store/1.2.0_react@18.2.0: + resolution: + { + integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==, + } + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + dev: false + + /v8-compile-cache/2.3.0: + resolution: + { + integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==, + } + + /which-boxed-primitive/1.0.2: + resolution: + { + integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==, + } + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: false + + /which/2.0.2: + resolution: + { + integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==, + } + engines: { node: ">= 8" } + hasBin: true + dependencies: + isexe: 2.0.0 + + /word-wrap/1.2.3: + resolution: + { + integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==, + } + engines: { node: ">=0.10.0" } + + /wrappy/1.0.2: + resolution: + { + integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, + } + + /yallist/4.0.0: + resolution: + { + integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==, + } + + file:packages/ui: + resolution: { directory: packages/ui, type: directory } + name: ui + version: 0.0.0 + dev: false + + github.com/peerigon/dashboard-icons/ce27ef933144e09cef3911025f3649040a8571b6: + resolution: + { + tarball: https://codeload.github.com/peerigon/dashboard-icons/tar.gz/ce27ef933144e09cef3911025f3649040a8571b, + } + name: dashboard-icons + version: 1.0.0 + dev: false diff --git a/crates/turborepo-lockfiles/fixtures/pnpm8.yaml b/crates/turborepo-lockfiles/fixtures/pnpm8.yaml new file mode 100644 index 0000000000000..d7d9e274d60fd --- /dev/null +++ b/crates/turborepo-lockfiles/fixtures/pnpm8.yaml @@ -0,0 +1,107 @@ +lockfileVersion: "6.0" + +patchedDependencies: + is-even@1.0.0: + hash: trwuddosrpxsvtoqztvint6pca + path: patches/is-even@1.0.0.patch + +importers: + .: {} + + packages/a: + dependencies: + c: + specifier: workspace:* + version: link:../c + is-odd: + specifier: ^3.0.1 + version: 3.0.1 + + packages/b: + dependencies: + c: + specifier: workspace:* + version: link:../c + is-even: + specifier: ^1.0.0 + version: 1.0.0_trwuddosrpxsvtoqztvint6pca + + packages/c: + dependencies: + lodash: + specifier: ^4.17.21 + version: 4.17.21 + +packages: + /is-buffer@1.1.6: + resolution: + { + integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==, + } + dev: false + + /is-even@1.0.0_trwuddosrpxsvtoqztvint6pca: + resolution: + { + integrity: sha512-LEhnkAdJqic4Dbqn58A0y52IXoHWlsueqQkKfMfdEnIYG8A1sm/GHidKkS6yvXlMoRrkM34csHnXQtOqcb+Jzg==, + } + engines: { node: ">=0.10.0" } + dependencies: + is-odd: 0.1.2 + dev: false + patched: true + + /is-number@3.0.0: + resolution: + { + integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==, + } + engines: { node: ">=0.10.0" } + dependencies: + kind-of: 3.2.2 + dev: false + + /is-number@6.0.0: + resolution: + { + integrity: sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==, + } + engines: { node: ">=0.10.0" } + dev: false + + /is-odd@0.1.2: + resolution: + { + integrity: sha512-Ri7C2K7o5IrUU9UEI8losXJCCD/UtsaIrkR5sxIcFg4xQ9cRJXlWA5DQvTE0yDc0krvSNLsRGXN11UPS6KyfBw==, + } + engines: { node: ">=0.10.0" } + dependencies: + is-number: 3.0.0 + dev: false + + /is-odd@3.0.1: + resolution: + { + integrity: sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA==, + } + engines: { node: ">=4" } + dependencies: + is-number: 6.0.0 + dev: false + + /kind-of@3.2.2: + resolution: + { + integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==, + } + engines: { node: ">=0.10.0" } + dependencies: + is-buffer: 1.1.6 + dev: false + + /lodash@4.17.21: + resolution: + { + integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==, + } + dev: false diff --git a/crates/turborepo-lockfiles/src/lib.rs b/crates/turborepo-lockfiles/src/lib.rs index c18d272ec1252..e605e7bdc17ef 100644 --- a/crates/turborepo-lockfiles/src/lib.rs +++ b/crates/turborepo-lockfiles/src/lib.rs @@ -3,6 +3,7 @@ mod berry; mod error; mod npm; +mod pnpm; use std::collections::{HashMap, HashSet}; diff --git a/crates/turborepo-lockfiles/src/pnpm/mod.rs b/crates/turborepo-lockfiles/src/pnpm/mod.rs new file mode 100644 index 0000000000000..b6928fed1b660 --- /dev/null +++ b/crates/turborepo-lockfiles/src/pnpm/mod.rs @@ -0,0 +1,190 @@ +use serde::{Deserialize, Serialize}; + +type Map = std::collections::BTreeMap; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("yaml: {0}")] + Yaml(#[from] serde_yaml::Error), +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct PnpmLockfileData { + lockfile_version: LockfileVersion, + never_built_dependencies: Option>, + only_built_dependencies: Option>, + overrides: Option>, + package_extensions_checksum: Option, + patched_dependencies: Option>, + importers: Map, + packages: Option>, + time: Option>, +} + +#[derive(Debug, PartialEq, Eq)] +struct LockfileVersion { + version: String, + format: VersionFormat, +} + +#[derive(Debug, PartialEq, Eq)] +enum VersionFormat { + String, + Float, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct PatchFile { + path: String, + hash: String, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct ProjectSnapshot { + #[serde(flatten)] + dependencies: DependencyInfo, + dependencies_meta: Option>, + publish_directory: Option, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase", untagged)] +pub enum DependencyInfo { + PreV6 { + specifiers: Option>, + dependencies: Option>, + optional_dependencies: Option>, + dev_dependencies: Option>, + }, + V6 { + dependencies: Option>, + optional_dependencies: Option>, + dev_dependencies: Option>, + }, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct Dependency { + specifier: String, + version: String, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct PackageSnapshot { + // can we make this flow?/is it necessary? + resolution: PackageResolution, + id: Option, + + name: Option, + version: Option, + + dependencies: Option>, + optional_dependencies: Option>, + patched: Option, + + #[serde(flatten)] + other: Map, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct DependenciesMeta { + injected: Option, + node: Option, + patch: Option, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct PackageResolution { + #[serde(rename = "type")] + type_field: Option, + integrity: Option, + tarball: Option, + dir: Option, + repo: Option, + commit: Option, +} + +impl PnpmLockfileData { + pub fn from_bytes(bytes: &[u8]) -> Result { + let this = serde_yaml::from_slice(bytes)?; + Ok(this) + } +} + +impl From for LockfileVersion { + fn from(value: f32) -> Self { + Self { + version: value.to_string(), + format: VersionFormat::Float, + } + } +} + +impl From for LockfileVersion { + fn from(value: String) -> Self { + Self { + version: value, + format: VersionFormat::String, + } + } +} + +impl<'de> Deserialize<'de> for LockfileVersion { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + #[derive(Deserialize)] + #[serde(untagged)] + enum StringOrNum { + Str(String), + Num(f32), + } + + Ok(match StringOrNum::deserialize(deserializer)? { + StringOrNum::Num(x) => LockfileVersion::from(x), + StringOrNum::Str(s) => LockfileVersion::from(s), + }) + } +} + +impl Serialize for LockfileVersion { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + match self.format { + VersionFormat::String => serializer.serialize_str(&self.version), + VersionFormat::Float => serializer.serialize_f32( + self.version + .parse() + .expect("Expected lockfile version to be valid f32"), + ), + } + } +} + +#[cfg(test)] +mod tests { + use pretty_assertions::assert_eq; + + use super::*; + + #[test] + fn test_roundtrip() { + for fixture in &[ + &include_bytes!("../../fixtures/pnpm6-workspace.yaml")[..], + &include_bytes!("../../fixtures/pnpm7-workspace.yaml")[..], + &include_bytes!("../../fixtures/pnpm8.yaml")[..], + ] { + let lockfile = PnpmLockfileData::from_bytes(fixture).unwrap(); + let serialized_lockfile = serde_yaml::to_string(&lockfile).unwrap(); + let lockfile_from_serialized = + serde_yaml::from_slice(serialized_lockfile.as_bytes()).unwrap(); + assert_eq!(lockfile, lockfile_from_serialized); + } + } +} From b3870a48648fd9f2eecb2d82fb595254c70d7d71 Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Wed, 10 May 2023 16:20:57 -0700 Subject: [PATCH 02/11] add resolve dependency to rust impl --- Cargo.lock | 2 + crates/turborepo-lockfiles/Cargo.toml | 2 + .../fixtures/pnpm-absolute-v6.yaml | 18 + .../fixtures/pnpm-absolute.yaml | 38 ++ .../fixtures/pnpm-override.yaml | 24 + .../fixtures/pnpm-patch.yaml | 63 ++ .../fixtures/pnpm-peer-v6.yaml | 67 ++ .../fixtures/pnpm-top-level-dupe.yaml | 36 + crates/turborepo-lockfiles/src/pnpm/data.rs | 631 ++++++++++++++++++ .../turborepo-lockfiles/src/pnpm/dep_path.rs | 160 +++++ .../turborepo-lockfiles/src/pnpm/lockfile.rs | 5 + crates/turborepo-lockfiles/src/pnpm/mod.rs | 193 +----- 12 files changed, 1049 insertions(+), 190 deletions(-) create mode 100644 crates/turborepo-lockfiles/fixtures/pnpm-absolute-v6.yaml create mode 100644 crates/turborepo-lockfiles/fixtures/pnpm-absolute.yaml create mode 100644 crates/turborepo-lockfiles/fixtures/pnpm-override.yaml create mode 100644 crates/turborepo-lockfiles/fixtures/pnpm-patch.yaml create mode 100644 crates/turborepo-lockfiles/fixtures/pnpm-peer-v6.yaml create mode 100644 crates/turborepo-lockfiles/fixtures/pnpm-top-level-dupe.yaml create mode 100644 crates/turborepo-lockfiles/src/pnpm/data.rs create mode 100644 crates/turborepo-lockfiles/src/pnpm/dep_path.rs create mode 100644 crates/turborepo-lockfiles/src/pnpm/lockfile.rs diff --git a/Cargo.lock b/Cargo.lock index b29a4c148bc8d..c78db4f940e67 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9033,6 +9033,7 @@ dependencies = [ name = "turborepo-lockfiles" version = "0.1.0" dependencies = [ + "nom", "pest", "pest_derive", "pretty_assertions", @@ -9041,6 +9042,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml 0.9.19", + "test-case", "thiserror", ] diff --git a/crates/turborepo-lockfiles/Cargo.toml b/crates/turborepo-lockfiles/Cargo.toml index d89c8076d9c96..2d3b47b236de0 100644 --- a/crates/turborepo-lockfiles/Cargo.toml +++ b/crates/turborepo-lockfiles/Cargo.toml @@ -7,6 +7,7 @@ license = "MPL-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +nom = "7" pest = "2.5.6" pest_derive = "2.5.6" regex = "1" @@ -18,3 +19,4 @@ thiserror = "1.0.38" [dev-dependencies] pretty_assertions = "1.3" +test-case = "3.1.0" diff --git a/crates/turborepo-lockfiles/fixtures/pnpm-absolute-v6.yaml b/crates/turborepo-lockfiles/fixtures/pnpm-absolute-v6.yaml new file mode 100644 index 0000000000000..dc5d0e626014a --- /dev/null +++ b/crates/turborepo-lockfiles/fixtures/pnpm-absolute-v6.yaml @@ -0,0 +1,18 @@ +lockfileVersion: "6.0" +importers: + packages/a: + dependencies: + "@scope/parent": + specifier: ^1.0.0 + version: 1.0.0 + +packages: + /@scope/parent@1.0.0: + resolution: { integrity: junk } + dependencies: + child: /@scope/child@1.0.0 + dev: false + + /@scope/child@1.0.0: + resolution: { integrity: junk } + dev: false diff --git a/crates/turborepo-lockfiles/fixtures/pnpm-absolute.yaml b/crates/turborepo-lockfiles/fixtures/pnpm-absolute.yaml new file mode 100644 index 0000000000000..d39f802da9e7b --- /dev/null +++ b/crates/turborepo-lockfiles/fixtures/pnpm-absolute.yaml @@ -0,0 +1,38 @@ +lockfileVersion: 5.4 +importers: + packages/a: + specifiers: + another: ^1.0.0 + "@scope/parent": ^1.0.0 + special: npm:Special@1.2.3 + dependencies: + another: 1.0.0 + "@scope/parent": 1.0.0 + special: /Special/1.2.3 + +packages: + /@scope/parent/1.0.0: + resolution: { integrity: junk } + dependencies: + child: /@scope/child/1.0.0 + dev: false + + /@scope/child/1.0.0: + resolution: { integrity: junk } + dev: false + + /another/1.0.0: + resolution: { integrity: junk } + dev: false + dependencies: + foo: 1.0.0 + + /foo/1.0.0: + resolution: { integrity: junk } + dev: false + dependencies: + Special: 1.2.3 + + /Special/1.2.3: + resolution: { integrity: junk } + dev: false diff --git a/crates/turborepo-lockfiles/fixtures/pnpm-override.yaml b/crates/turborepo-lockfiles/fixtures/pnpm-override.yaml new file mode 100644 index 0000000000000..21021920f574e --- /dev/null +++ b/crates/turborepo-lockfiles/fixtures/pnpm-override.yaml @@ -0,0 +1,24 @@ +lockfileVersion: 5.4 + +overrides: + "@nomiclabs/hardhat-ethers": npm:hardhat-deploy-ethers@^0.3.0-beta.13 + +importers: + config/hardhat: + specifiers: + "@nomiclabs/hardhat-ethers": npm:hardhat-deploy-ethers@^0.3.0-beta.13 + dependencies: + "@nomiclabs/hardhat-ethers": /hardhat-deploy-ethers/0.3.0-beta.13_yab2ug5tvye2kp6e24l5x3z7uy + +packages: + /hardhat-deploy-ethers/0.3.0-beta.13_yab2ug5tvye2kp6e24l5x3z7uy: + resolution: + { + integrity: sha512-PdWVcKB9coqWV1L7JTpfXRCI91Cgwsm7KLmBcwZ8f0COSm1xtABHZTyz3fvF6p42cTnz1VM0QnfDvMFlIRkSNw==, + } + peerDependencies: + ethers: ^5.0.0 + hardhat: ^2.0.0 + dependencies: + ethers: 5.7.2 + hardhat: 2.12.4_typescript@4.9.4 diff --git a/crates/turborepo-lockfiles/fixtures/pnpm-patch.yaml b/crates/turborepo-lockfiles/fixtures/pnpm-patch.yaml new file mode 100644 index 0000000000000..ea84d72043b7b --- /dev/null +++ b/crates/turborepo-lockfiles/fixtures/pnpm-patch.yaml @@ -0,0 +1,63 @@ +lockfileVersion: 5.4 + +patchedDependencies: + is-odd@3.0.1: + hash: nrrwwz7lemethtlvvm75r5bmhq + path: patches/is-odd@3.0.1.patch + "@babel/core@7.20.12": + hash: 3hyn7hbvzkemudbydlwjmrb65y + path: patches/@babel__core@7.20.12.patch + moleculer@0.14.28: + hash: 5pk7ojv7qbqha75ozglk4y4f74 + path: patches/moleculer@0.14.28.patch + +importers: + .: + specifiers: {} + + packages/dependency: + specifiers: + is-odd: ^3.0.1 + "@babel/core": ^7.20.12 + dependencies: + is-odd: 3.0.1_nrrwwz7lemethtlvvm75r5bmhq + "@babel/core": 7.20.12_3hyn7hbvzkemudbydlwjmrb65y + +packages: + /@babel/core/7.20.12_3hyn7hbvzkemudbydlwjmrb65y: + resolution: + { + integrity: sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==, + } + engines: { node: ">=6.9.0" } + dev: false + + /is-number/6.0.0: + resolution: + { + integrity: sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==, + } + engines: { node: ">=0.10.0" } + dev: false + + /is-odd/3.0.1_nrrwwz7lemethtlvvm75r5bmhq: + resolution: + { + integrity: sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA==, + } + engines: { node: ">=4" } + dependencies: + is-number: 6.0.0 + dev: false + patched: true + + /moleculer/0.14.28_5pk7ojv7qbqha75ozglk4y4f74_kumip57h7zlinbhp4gz3jrbqry: + resolution: + { + integrity: sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA==, + } + engines: { node: ">=4" } + dependencies: + is-number: 6.0.0 + dev: false + patched: true diff --git a/crates/turborepo-lockfiles/fixtures/pnpm-peer-v6.yaml b/crates/turborepo-lockfiles/fixtures/pnpm-peer-v6.yaml new file mode 100644 index 0000000000000..feddd0769b09f --- /dev/null +++ b/crates/turborepo-lockfiles/fixtures/pnpm-peer-v6.yaml @@ -0,0 +1,67 @@ +lockfileVersion: "6.0" + +importers: + .: {} + + apps/web: + dependencies: + next: + specifier: 13.0.4 + version: 13.0.4(react-dom@18.2.0)(react@18.2.0) + react: + specifier: 18.2.0 + version: 18.2.0 + react-dom: + specifier: 18.2.0 + version: 18.2.0(react@18.2.0) + + packages/next-config: {} + + packages/package-for-ci: {} + + packages/tsconfig: {} + +packages: + /next@13.0.4: + resolution: + { + integrity: sha512-4P0MvbjPCI1E/UPL1GrTXtYlgFnbBbY3JQ+AMY8jYE2SwyvCWctEJySoRjveznAHjrl6TIjuAJeB8u1c2StYUQ==, + } + engines: { node: ">=14.6.0" } + hasBin: true + peerDependencies: + fibers: ">= 3.1.0" + node-sass: ^6.0.0 || ^7.0.0 + react: ^18.2.0 + react-dom: ^18.2.0 + sass: ^1.3.0 + peerDependenciesMeta: + fibers: + optional: true + node-sass: + optional: true + sass: + optional: true + dev: true + + /next@13.0.4(react-dom@18.2.0)(react@18.2.0): + resolution: + { + integrity: sha512-4P0MvbjPCI1E/UPL1GrTXtYlgFnbBbY3JQ+AMY8jYE2SwyvCWctEJySoRjveznAHjrl6TIjuAJeB8u1c2StYUQ==, + } + engines: { node: ">=14.6.0" } + hasBin: true + peerDependencies: + fibers: ">= 3.1.0" + node-sass: ^6.0.0 || ^7.0.0 + react: ^18.2.0 + react-dom: ^18.2.0 + sass: ^1.3.0 + peerDependenciesMeta: + fibers: + optional: true + node-sass: + optional: true + sass: + optional: true + dev: false diff --git a/crates/turborepo-lockfiles/fixtures/pnpm-top-level-dupe.yaml b/crates/turborepo-lockfiles/fixtures/pnpm-top-level-dupe.yaml new file mode 100644 index 0000000000000..6837f223da853 --- /dev/null +++ b/crates/turborepo-lockfiles/fixtures/pnpm-top-level-dupe.yaml @@ -0,0 +1,36 @@ +lockfileVersion: 5.4 + +importers: + packages/a: + specifiers: + ci-info: ^2.0.0 + is-ci: ^3.0.1 + dependencies: + ci-info: 2.0.0 + is-ci: 3.0.1 + +packages: + /ci-info/2.0.0: + resolution: + { + integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==, + } + dev: false + + /ci-info/3.7.1: + resolution: + { + integrity: sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==, + } + engines: { node: ">=8" } + dev: false + + /is-ci/3.0.1: + resolution: + { + integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==, + } + hasBin: true + dependencies: + ci-info: 3.7.1 + dev: false diff --git a/crates/turborepo-lockfiles/src/pnpm/data.rs b/crates/turborepo-lockfiles/src/pnpm/data.rs new file mode 100644 index 0000000000000..0bc1851b55125 --- /dev/null +++ b/crates/turborepo-lockfiles/src/pnpm/data.rs @@ -0,0 +1,631 @@ +use std::borrow::Cow; + +use serde::{Deserialize, Serialize}; + +use super::dep_path::DepPath; + +type Map = std::collections::BTreeMap; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("yaml: {0}")] + Yaml(#[from] serde_yaml::Error), +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct PnpmLockfileData { + lockfile_version: LockfileVersion, + never_built_dependencies: Option>, + only_built_dependencies: Option>, + overrides: Option>, + package_extensions_checksum: Option, + patched_dependencies: Option>, + importers: Map, + packages: Option>, + time: Option>, +} + +#[derive(Debug, PartialEq, Eq)] +struct LockfileVersion { + version: String, + format: VersionFormat, +} + +#[derive(Debug, PartialEq, Eq)] +enum VersionFormat { + String, + Float, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct PatchFile { + path: String, + hash: String, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct ProjectSnapshot { + #[serde(flatten)] + dependencies: DependencyInfo, + dependencies_meta: Option>, + publish_directory: Option, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase", untagged)] +pub enum DependencyInfo { + #[serde(rename_all = "camelCase")] + PreV6 { + specifiers: Option>, + dependencies: Option>, + optional_dependencies: Option>, + dev_dependencies: Option>, + }, + #[serde(rename_all = "camelCase")] + V6 { + dependencies: Option>, + optional_dependencies: Option>, + dev_dependencies: Option>, + }, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct Dependency { + specifier: String, + version: String, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] +#[serde(rename_all = "camelCase")] +pub struct PackageSnapshot { + // can we make this flow?/is it necessary? + resolution: PackageResolution, + id: Option, + + name: Option, + version: Option, + + dependencies: Option>, + optional_dependencies: Option>, + patched: Option, + + #[serde(flatten)] + other: Map, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] +pub struct DependenciesMeta { + injected: Option, + node: Option, + patch: Option, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] +pub struct PackageResolution { + #[serde(rename = "type")] + type_field: Option, + integrity: Option, + tarball: Option, + dir: Option, + repo: Option, + commit: Option, +} + +impl PnpmLockfileData { + pub fn from_bytes(bytes: &[u8]) -> Result { + let this = serde_yaml::from_slice(bytes)?; + Ok(this) + } + + pub fn patches(&self) -> Vec { + let mut patches = self + .patched_dependencies + .iter() + .flatten() + .map(|(_, patch)| patch.path.clone()) + .collect::>(); + patches.sort(); + patches + } + + fn get_packages(&self, key: &str) -> Option<&PackageSnapshot> { + self.packages + .as_ref() + .and_then(|packages| packages.get(key)) + } + + fn get_workspace(&self, workspace_path: &str) -> Result<&ProjectSnapshot, crate::Error> { + let key = match workspace_path { + // For pnpm, the root is named "." + "" => ".", + k => k, + }; + self.importers + .get(key) + .ok_or_else(|| crate::Error::MissingWorkspace(workspace_path.into())) + } + + fn is_v6(&self) -> bool { + matches!(self.lockfile_version.format, VersionFormat::String) + } + + fn format_key(&self, name: &str, version: &str) -> String { + match self.is_v6() { + true => format!("/{name}@{version}"), + false => format!("/{name}/{version}"), + } + } + + fn extract_version<'a>(&self, key: &'a str) -> Option> { + let dp = DepPath::try_from(key).ok()?; + if let Some(suffix) = dp.peer_suffix { + let sep = match self.is_v6() { + true => "", + false => "_", + }; + Some(format!("{}{}{}", dp.version, sep, suffix).into()) + } else { + Some(dp.version.into()) + } + } + + fn apply_overrides<'a>(&'a self, name: &str, specifier: &'a str) -> &'a str { + self.overrides + .as_ref() + .and_then(|o| o.get(name)) + .map(|s| s.as_str()) + .unwrap_or(specifier) + } + + fn resolve_specifier<'a>( + &'a self, + workspace_path: &str, + name: &str, + specifier: &'a str, + ) -> Result, crate::Error> { + let importer = self.get_workspace(workspace_path)?; + + let Some((resolved_specifier, resolved_version)) = importer.dependencies.find_resolution(name) else { + self.get_packages(&self.format_key(name, specifier)); + return Ok(None) + }; + + let override_specifier = self.apply_overrides(name, specifier); + if resolved_specifier == override_specifier { + Ok(Some(resolved_version)) + } else if self + .get_packages(&self.format_key(name, override_specifier)) + .is_some() + { + Ok(Some(override_specifier)) + } else { + Ok(None) + } + } + + pub fn subgraph( + &self, + workspace_paths: &[String], + packages: &[String], + ) -> Result { + let mut pruned_packages = Map::new(); + for package in packages { + let entry = self + .get_packages(package.as_str()) + .ok_or_else(|| crate::Error::MissingPackage(package.clone()))?; + pruned_packages.insert(package.clone(), entry.clone()); + } + todo!() + } +} + +impl crate::Lockfile for PnpmLockfileData { + fn resolve_package( + &self, + workspace_path: &str, + name: &str, + version: &str, + ) -> Result, crate::Error> { + // Check if version is a key + if self.get_packages(version).is_some() { + // TODO no unwrap + let extracted_version = self.extract_version(version).unwrap(); + return Ok(Some(crate::Package { + key: version.into(), + version: extracted_version.into(), + })); + } + + let Some(resolved_version) = self.resolve_specifier(workspace_path, name, version)? else { + return Ok(None) + }; + + let key = self.format_key(name, resolved_version); + + if let Some(pkg) = self.get_packages(&key) { + Ok(Some(crate::Package { + key, + version: pkg + .version + .clone() + .unwrap_or_else(|| resolved_version.to_string()), + })) + } else if let Some(pkg) = self.get_packages(resolved_version) { + Ok(Some(crate::Package { + key: resolved_version.to_string(), + version: pkg + .version + .clone() + // TODO avoid unwrap here? + .unwrap_or_else(|| self.extract_version(resolved_version).unwrap().to_string()), + })) + } else { + Ok(None) + } + } + + fn all_dependencies( + &self, + key: &str, + ) -> Result>, crate::Error> { + let Some(entry) = self.packages.as_ref().and_then(|pkgs| pkgs.get(key)) else { + return Ok(None) + }; + Ok(Some( + entry + .dependencies + .iter() + .flatten() + .chain(entry.optional_dependencies.iter().flatten()) + .map(|(k, v)| (k.clone(), v.clone())) + .collect(), + )) + } +} + +impl From for LockfileVersion { + fn from(value: f32) -> Self { + Self { + version: value.to_string(), + format: VersionFormat::Float, + } + } +} + +impl From for LockfileVersion { + fn from(value: String) -> Self { + Self { + version: value, + format: VersionFormat::String, + } + } +} + +impl<'de> Deserialize<'de> for LockfileVersion { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + #[derive(Deserialize)] + #[serde(untagged)] + enum StringOrNum { + Str(String), + Num(f32), + } + + Ok(match StringOrNum::deserialize(deserializer)? { + StringOrNum::Num(x) => LockfileVersion::from(x), + StringOrNum::Str(s) => LockfileVersion::from(s), + }) + } +} + +impl Serialize for LockfileVersion { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + match self.format { + VersionFormat::String => serializer.serialize_str(&self.version), + VersionFormat::Float => serializer.serialize_f32( + self.version + .parse() + .expect("Expected lockfile version to be valid f32"), + ), + } + } +} + +impl DependencyInfo { + pub fn find_resolution(&self, dependency: &str) -> Option<(&str, &str)> { + match self { + DependencyInfo::PreV6 { + specifiers, + dependencies, + optional_dependencies, + dev_dependencies, + } => { + let specifier = specifiers.as_ref().and_then(|s| s.get(dependency))?; + let version = Self::get_resolution(dependencies, dependency) + .or_else(|| Self::get_resolution(dev_dependencies, dependency)) + .or_else(|| Self::get_resolution(optional_dependencies, dependency))?; + Some((specifier, version)) + } + DependencyInfo::V6 { + dependencies, + optional_dependencies, + dev_dependencies, + } => Self::get_resolution(dependencies, dependency) + .or_else(|| Self::get_resolution(dev_dependencies, dependency)) + .or_else(|| Self::get_resolution(optional_dependencies, dependency)) + .map(Dependency::as_tuple), + } + } + + fn get_resolution<'a, V>(maybe_map: &'a Option>, key: &str) -> Option<&'a V> { + maybe_map.as_ref().and_then(|maybe_map| maybe_map.get(key)) + } +} + +impl Dependency { + fn as_tuple(&self) -> (&str, &str) { + let Dependency { specifier, version } = self; + (specifier, version) + } +} + +#[cfg(test)] +mod tests { + use pretty_assertions::assert_eq; + use test_case::test_case; + + const PNPM6: &[u8] = include_bytes!("../../fixtures/pnpm6-workspace.yaml").as_slice(); + const PNPM7: &[u8] = include_bytes!("../../fixtures/pnpm7-workspace.yaml").as_slice(); + const PNPM8: &[u8] = include_bytes!("../../fixtures/pnpm8.yaml").as_slice(); + const PNPM_ABSOLUTE: &[u8] = include_bytes!("../../fixtures/pnpm-absolute.yaml").as_slice(); + const PNPM_ABSOLUTE_V6: &[u8] = + include_bytes!("../../fixtures/pnpm-absolute-v6.yaml").as_slice(); + const PNPM_PEER: &[u8] = include_bytes!("../../fixtures/pnpm-peer-v6.yaml").as_slice(); + const PNPM_TOP_LEVEL_OVERRIDE: &[u8] = + include_bytes!("../../fixtures/pnpm-top-level-dupe.yaml").as_slice(); + const PNPM_OVERRIDE: &[u8] = include_bytes!("../../fixtures/pnpm-override.yaml").as_slice(); + + use super::*; + use crate::Lockfile; + + #[test] + fn test_roundtrip() { + for fixture in &[PNPM6, PNPM7, PNPM8] { + let lockfile = PnpmLockfileData::from_bytes(fixture).unwrap(); + let serialized_lockfile = serde_yaml::to_string(&lockfile).unwrap(); + let lockfile_from_serialized = + serde_yaml::from_slice(serialized_lockfile.as_bytes()).unwrap(); + assert_eq!(lockfile, lockfile_from_serialized); + } + } + + #[test] + fn test_patches() { + let lockfile = + PnpmLockfileData::from_bytes(include_bytes!("../../fixtures/pnpm-patch.yaml")).unwrap(); + assert_eq!( + lockfile.patches(), + vec![ + "patches/@babel__core@7.20.12.patch".to_string(), + "patches/is-odd@3.0.1.patch".to_string(), + "patches/moleculer@0.14.28.patch".to_string(), + ] + ); + } + + #[test_case( + PNPM7, + "apps/docs", + "next", + "12.2.5", + Ok(Some("12.2.5_ir3quccc6i62x6qn6jjhyjjiey")) + ; "resolution from docs" + )] + #[test_case( + PNPM7, + "apps/web", + "next", + "12.2.5", + Ok(Some("12.2.5_ir3quccc6i62x6qn6jjhyjjiey")) + ; "resolution from web" + )] + #[test_case( + PNPM7, + "apps/web", + "typescript", + "^4.5.3", + Ok(Some("4.8.3")) + ; "no peer deps" + )] + #[test_case( + PNPM7, + "apps/web", + "lodash", + "bad-tag", + Ok(None) + ; "bad tag" + )] + #[test_case( + PNPM7, + "apps/web", + "lodash", + "^4.17.21", + Ok(Some("4.17.21_ehchni3mpmovsvjxesffg2i5a4")) + ; "patched lodash" + )] + #[test_case( + PNPM7, + "apps/docs", + "dashboard-icons", + "github:peerigon/dashboard-icons", + Ok(Some("github.com/peerigon/dashboard-icons/ce27ef933144e09cef3911025f3649040a8571b6")) + ; "github dependency" + )] + #[test_case( + PNPM7, + "", + "turbo", + "latest", + Ok(Some("1.4.6")) + ; "root dependency" + )] + #[test_case( + PNPM7, + "apps/bad_workspace", + "turbo", + "latest", + Err("Workspace 'apps/bad_workspace' not found in lockfile") + ; "invalid workspace" + )] + #[test_case( + PNPM8, + "packages/a", + "c", + "workspace:*", + Ok(Some("link:../c")) + ; "v6 workspace" + )] + #[test_case( + PNPM8, + "packages/a", + "is-odd", + "^3.0.1", + Ok(Some("3.0.1")) + ; "v6 external package" + )] + #[test_case( + PNPM8, + "packages/b", + "is-odd", + "^3.0.1", + Ok(None) + ; "v6 missing" + )] + #[test_case( + PNPM8, + "apps/bad_workspace", + "is-odd", + "^3.0.1", + Err("Workspace 'apps/bad_workspace' not found in lockfile") + ; "v6 missing workspace" + )] + fn test_specifier_resolution( + lockfile: &[u8], + workspace_path: &str, + package: &str, + specifier: &str, + expected: Result, &str>, + ) { + let lockfile = PnpmLockfileData::from_bytes(lockfile).unwrap(); + + let actual = lockfile.resolve_specifier(workspace_path, package, specifier); + match (actual, expected) { + (Ok(actual), Ok(expected)) => assert_eq!(actual, expected), + (Err(actual), Err(expected_msg)) => assert!( + actual.to_string().contains(expected_msg), + "Expected '{}' to appear in error message: '{}'", + expected_msg, + actual, + ), + (actual, expected) => { + panic!("Mismatched result variants: {:?} {:?}", actual, expected) + } + } + } + + #[test_case( + PNPM7, + "apps/docs", + "dashboard-icons", + "github:peerigon/dashboard-icons", + Ok(Some(crate::Package { + key: "github.com/peerigon/dashboard-icons/ce27ef933144e09cef3911025f3649040a8571b6".into(), + version: "1.0.0".into(), + })) + ; "git package" + )] + #[test_case( + PNPM_ABSOLUTE, + "packages/a", + "child", + "/@scope/child/1.0.0", + Ok(Some(crate::Package { + key: "/@scope/child/1.0.0".into(), + version: "1.0.0".into(), + })) + ; "absolute package" + )] + #[test_case( + PNPM_ABSOLUTE_V6, + "packages/a", + "child", + "/@scope/child@1.0.0", + Ok(Some(crate::Package { + key: "/@scope/child@1.0.0".into(), + version: "1.0.0".into(), + })) + ; "v6 absolute package" + )] + #[test_case( + PNPM_PEER, + "apps/web", + "next", + "13.0.4", + Ok(Some(crate::Package { + key: "/next@13.0.4(react-dom@18.2.0)(react@18.2.0)".into(), + version: "13.0.4(react-dom@18.2.0)(react@18.2.0)".into(), + })) + ; "v6 peer package" + )] + #[test_case( + PNPM_TOP_LEVEL_OVERRIDE, + "packages/a", + "ci-info", + "3.7.1", + Ok(Some(crate::Package { + key: "/ci-info/3.7.1".into(), + version: "3.7.1".into(), + })) + ; "top level override" + )] + #[test_case( + PNPM_OVERRIDE, + "config/hardhat", + "@nomiclabs/hardhat-ethers", + "npm:hardhat-deploy-ethers@0.3.0-beta.13", + Ok(Some(crate::Package { + key: "/hardhat-deploy-ethers/0.3.0-beta.13_yab2ug5tvye2kp6e24l5x3z7uy".into(), + version: "0.3.0-beta.13_yab2ug5tvye2kp6e24l5x3z7uy".into(), + })) + ; "pnpm override" + )] + fn test_resolve_package( + lockfile: &[u8], + workspace_path: &str, + package: &str, + specifier: &str, + expected: Result, &str>, + ) { + let lockfile = PnpmLockfileData::from_bytes(lockfile).unwrap(); + let actual = lockfile.resolve_package(workspace_path, package, specifier); + match (actual, expected) { + (Ok(actual), Ok(expected)) => assert_eq!(actual, expected), + (Err(actual), Err(expected_msg)) => assert!( + actual.to_string().contains(expected_msg), + "Expected '{}' to appear in error message: '{}'", + expected_msg, + actual, + ), + (actual, expected) => { + panic!("Mismatched result variants: {:?} {:?}", actual, expected) + } + } + } +} diff --git a/crates/turborepo-lockfiles/src/pnpm/dep_path.rs b/crates/turborepo-lockfiles/src/pnpm/dep_path.rs new file mode 100644 index 0000000000000..79a7a8c2fd71b --- /dev/null +++ b/crates/turborepo-lockfiles/src/pnpm/dep_path.rs @@ -0,0 +1,160 @@ +use std::borrow::Cow; + +use nom::{ + branch::alt, + bytes::complete::{is_not, tag}, + combinator::{opt, recognize}, + sequence::tuple, + Finish, IResult, +}; + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct DepPath<'a> { + // todo we possibly keep the full string here for 0-cost serialization + pub name: &'a str, + pub version: &'a str, + pub host: Option<&'a str>, + pub peer_suffix: Option<&'a str>, +} + +impl<'a> DepPath<'a> { + pub fn new(name: &'a str, version: &'a str) -> Self { + Self { + name, + version, + host: None, + peer_suffix: None, + } + } + + pub fn with_host(mut self, host: Option<&'a str>) -> Self { + self.host = host; + self + } + + pub fn with_peer_suffix(mut self, peer_suffix: Option<&'a str>) -> Self { + self.peer_suffix = peer_suffix; + self + } + + pub fn patch_hash(&self) -> Option<&str> { + self.peer_suffix.and_then(|s| { + if s.starts_with('(') { + let (_, suffixes) = parse_v6_suffixes(s).ok()?; + suffixes.iter().find_map(|s| s.strip_prefix("patch_hash=")) + // Check if suffix is pre v6 + } else if let Some(idx) = s.find('_') { + Some(&s[..idx]) + } else { + // if a dependency just has a single suffix we can't tell if it's + // a patch or peer hash return it in case it's a patch hash + Some(s) + } + }) + } +} + +impl<'a> TryFrom<&'a str> for DepPath<'a> { + type Error = nom::error::Error; + + fn try_from(value: &'a str) -> Result { + let (_, dep_path) = parse_dep_path(value).map_err(|e| e.to_owned()).finish()?; + Ok(dep_path) + } +} + +// See https://github.com/pnpm/pnpm/blob/185ab01adfc927ea23d2db08a14723bf51d0025f/packages/dependency-path/src/index.ts#L96 +fn parse_dep_path(i: &str) -> IResult<&str, DepPath> { + let (i, host) = parse_host(i)?; + let (i, _) = nom::character::complete::char('/')(i)?; + let (i, name) = parse_name(i)?; + let (i, _) = nom::character::complete::one_of("/@")(i)?; + let (i, version) = parse_version(i)?; + let (i, peer_suffix) = opt(alt((parse_new_peer_suffix, parse_old_peer_suffix)))(i)?; + Ok(( + i, + DepPath { + name, + version, + host, + peer_suffix, + }, + )) +} + +fn parse_host(i: &str) -> IResult<&str, Option<&str>> { + let (i, host) = opt(is_not("/"))(i)?; + Ok((i, host)) +} + +fn parse_name(i: &str) -> IResult<&str, &str> { + let (i, name) = alt((parse_name_with_scope, is_not("/@")))(i)?; + Ok((i, name)) +} + +fn parse_name_with_scope(i: &str) -> IResult<&str, &str> { + let (i, name) = recognize(tuple((tag("@"), is_not("/"), tag("/"), is_not("/@"))))(i)?; + Ok((i, name)) +} + +fn parse_version(i: &str) -> IResult<&str, &str> { + // pre v6 lockfiles use _ to delimit version from metadata + // v6+ wraps metadata in ( + let (i, version) = is_not("_(")(i)?; + Ok((i, version)) +} + +fn parse_old_peer_suffix(i: &str) -> IResult<&str, &str> { + let (rest, _) = tag("_")(i)?; + Ok(("", rest)) +} + +fn parse_new_peer_suffix(i: &str) -> IResult<&str, &str> { + let (i, suffix) = recognize(parse_v6_suffixes)(i)?; + Ok((i, suffix)) +} + +fn parse_v6_suffix(i: &str) -> IResult<&str, &str> { + let (i, _) = tag("(")(i)?; + let (i, entry) = is_not(")")(i)?; + let (i, _) = tag(")")(i)?; + Ok((i, entry)) +} + +fn parse_v6_suffixes(i: &str) -> IResult<&str, Vec<&str>> { + let (i, suffixes) = nom::multi::many1(parse_v6_suffix)(i)?; + Ok((i, suffixes)) +} + +#[cfg(test)] +mod tests { + use test_case::test_case; + + use super::*; + + #[test_case("/foo/1.0.0", DepPath::new("foo", "1.0.0"); "basic dep path")] + #[test_case("/@foo/bar/1.0.0", DepPath::new("@foo/bar", "1.0.0"); "scoped dep path")] + #[test_case("example.org/foo/1.0.0", DepPath::new("foo", "1.0.0").with_host(Some("example.org")); "dep path with custom host")] + #[test_case("/foo/1.0.0_bar@1.0.0", DepPath::new("foo", "1.0.0").with_peer_suffix(Some("bar@1.0.0")); "dep path with peer dependency")] + #[test_case("/foo/1.0.0(bar@1.0.0)", DepPath::new("foo", "1.0.0").with_peer_suffix(Some("(bar@1.0.0)")); "dep path with new peer dependency")] + #[test_case("/foo/1.0.0_patchHash_peerHash", DepPath::new("foo", "1.0.0").with_peer_suffix(Some("patchHash_peerHash")); "dep path with path and peer hash")] + #[test_case("/@babel/helper-string-parser/7.19.4(patch_hash=wjhgmpzh47qmycrzgpeyoyh3ce)(@babel/core@7.21.0)", DepPath::new("@babel/helper-string-parser", "7.19.4").with_peer_suffix(Some("(patch_hash=wjhgmpzh47qmycrzgpeyoyh3ce)(@babel/core@7.21.0)")); "dep path with new path and peer hash")] + #[test_case("/foo@1.0.0", DepPath::new("foo", "1.0.0"); "basic v6 dep path")] + #[test_case("/is-even@1.0.0_foobar", DepPath::new("is-even", "1.0.0").with_peer_suffix(Some("foobar")); "v6 dep path with suffix")] + #[test_case("/foo@1.0.0(bar@1.0.0)(baz@1.0.0)", DepPath::new("foo", "1.0.0").with_peer_suffix(Some("(bar@1.0.0)(baz@1.0.0)")); "v6 with multiple peers")] + #[test_case("/@babel/helper-string-parser@7.19.4(patch_hash=wjhgmpzh47qmycrzgpeyoyh3ce)(@babel/core@7.21.0)", DepPath::new("@babel/helper-string-parser", "7.19.4").with_peer_suffix(Some("(patch_hash=wjhgmpzh47qmycrzgpeyoyh3ce)(@babel/core@7.21.0)")); "v6 with scope")] + fn dep_path_parse_tests(s: &str, expected: DepPath) { + let (rest, actual) = parse_dep_path(s).unwrap(); + assert_eq!(rest, ""); + assert_eq!(actual, expected); + } + + #[test_case("/@babel/helper-string-parser/7.19.4(patch_hash=wjhgmpzh47qmycrzgpeyoyh3ce)(@babel/core@7.21.0)", Some("wjhgmpzh47qmycrzgpeyoyh3ce"); "v6 patch")] + #[test_case("/foo/1.0.0_patchHash_peerHash", Some("patchHash"); "pre v6 patch")] + #[test_case("/foo/1.0.0", None; "no suffix")] + #[test_case("/foo/1.0.0(bar@1.0.0)", None; "no patch")] + fn dep_path_patch_hash(input: &str, expected: Option<&str>) { + let dep_path = DepPath::try_from(input).unwrap(); + assert_eq!(dep_path.patch_hash(), expected); + } +} diff --git a/crates/turborepo-lockfiles/src/pnpm/lockfile.rs b/crates/turborepo-lockfiles/src/pnpm/lockfile.rs new file mode 100644 index 0000000000000..7d5cc96d4cb3a --- /dev/null +++ b/crates/turborepo-lockfiles/src/pnpm/lockfile.rs @@ -0,0 +1,5 @@ +use super::data::{PnpmLockfileData, ProjectSnapshot}; + +pub struct PnpmLockfile<'a> { + data: &'a PnpmLockfileData, +} diff --git a/crates/turborepo-lockfiles/src/pnpm/mod.rs b/crates/turborepo-lockfiles/src/pnpm/mod.rs index b6928fed1b660..4f2e3654fc88e 100644 --- a/crates/turborepo-lockfiles/src/pnpm/mod.rs +++ b/crates/turborepo-lockfiles/src/pnpm/mod.rs @@ -1,190 +1,3 @@ -use serde::{Deserialize, Serialize}; - -type Map = std::collections::BTreeMap; - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("yaml: {0}")] - Yaml(#[from] serde_yaml::Error), -} - -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] -#[serde(rename_all = "camelCase")] -pub struct PnpmLockfileData { - lockfile_version: LockfileVersion, - never_built_dependencies: Option>, - only_built_dependencies: Option>, - overrides: Option>, - package_extensions_checksum: Option, - patched_dependencies: Option>, - importers: Map, - packages: Option>, - time: Option>, -} - -#[derive(Debug, PartialEq, Eq)] -struct LockfileVersion { - version: String, - format: VersionFormat, -} - -#[derive(Debug, PartialEq, Eq)] -enum VersionFormat { - String, - Float, -} - -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] -pub struct PatchFile { - path: String, - hash: String, -} - -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] -#[serde(rename_all = "camelCase")] -pub struct ProjectSnapshot { - #[serde(flatten)] - dependencies: DependencyInfo, - dependencies_meta: Option>, - publish_directory: Option, -} - -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] -#[serde(rename_all = "camelCase", untagged)] -pub enum DependencyInfo { - PreV6 { - specifiers: Option>, - dependencies: Option>, - optional_dependencies: Option>, - dev_dependencies: Option>, - }, - V6 { - dependencies: Option>, - optional_dependencies: Option>, - dev_dependencies: Option>, - }, -} - -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] -pub struct Dependency { - specifier: String, - version: String, -} - -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] -#[serde(rename_all = "camelCase")] -pub struct PackageSnapshot { - // can we make this flow?/is it necessary? - resolution: PackageResolution, - id: Option, - - name: Option, - version: Option, - - dependencies: Option>, - optional_dependencies: Option>, - patched: Option, - - #[serde(flatten)] - other: Map, -} - -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] -pub struct DependenciesMeta { - injected: Option, - node: Option, - patch: Option, -} - -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] -pub struct PackageResolution { - #[serde(rename = "type")] - type_field: Option, - integrity: Option, - tarball: Option, - dir: Option, - repo: Option, - commit: Option, -} - -impl PnpmLockfileData { - pub fn from_bytes(bytes: &[u8]) -> Result { - let this = serde_yaml::from_slice(bytes)?; - Ok(this) - } -} - -impl From for LockfileVersion { - fn from(value: f32) -> Self { - Self { - version: value.to_string(), - format: VersionFormat::Float, - } - } -} - -impl From for LockfileVersion { - fn from(value: String) -> Self { - Self { - version: value, - format: VersionFormat::String, - } - } -} - -impl<'de> Deserialize<'de> for LockfileVersion { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - #[derive(Deserialize)] - #[serde(untagged)] - enum StringOrNum { - Str(String), - Num(f32), - } - - Ok(match StringOrNum::deserialize(deserializer)? { - StringOrNum::Num(x) => LockfileVersion::from(x), - StringOrNum::Str(s) => LockfileVersion::from(s), - }) - } -} - -impl Serialize for LockfileVersion { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - match self.format { - VersionFormat::String => serializer.serialize_str(&self.version), - VersionFormat::Float => serializer.serialize_f32( - self.version - .parse() - .expect("Expected lockfile version to be valid f32"), - ), - } - } -} - -#[cfg(test)] -mod tests { - use pretty_assertions::assert_eq; - - use super::*; - - #[test] - fn test_roundtrip() { - for fixture in &[ - &include_bytes!("../../fixtures/pnpm6-workspace.yaml")[..], - &include_bytes!("../../fixtures/pnpm7-workspace.yaml")[..], - &include_bytes!("../../fixtures/pnpm8.yaml")[..], - ] { - let lockfile = PnpmLockfileData::from_bytes(fixture).unwrap(); - let serialized_lockfile = serde_yaml::to_string(&lockfile).unwrap(); - let lockfile_from_serialized = - serde_yaml::from_slice(serialized_lockfile.as_bytes()).unwrap(); - assert_eq!(lockfile, lockfile_from_serialized); - } - } -} +mod data; +mod dep_path; +mod lockfile; From 74ad956011527708d57356ea4be8ab4534433a26 Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Wed, 10 May 2023 18:48:02 -0700 Subject: [PATCH 03/11] finish porting all tests --- .../fixtures/pnpm-patch-v6.yaml | 40 ++++++ crates/turborepo-lockfiles/src/pnpm/data.rs | 126 ++++++++++++++++-- 2 files changed, 158 insertions(+), 8 deletions(-) create mode 100644 crates/turborepo-lockfiles/fixtures/pnpm-patch-v6.yaml diff --git a/crates/turborepo-lockfiles/fixtures/pnpm-patch-v6.yaml b/crates/turborepo-lockfiles/fixtures/pnpm-patch-v6.yaml new file mode 100644 index 0000000000000..b620472460d97 --- /dev/null +++ b/crates/turborepo-lockfiles/fixtures/pnpm-patch-v6.yaml @@ -0,0 +1,40 @@ +lockfileVersion: "6.0" + +patchedDependencies: + lodash@4.17.21: + hash: lgum37zgng4nfkynzh3cs7wdeq + path: patches/lodash@4.17.21.patch + "@babel/helper-string-parser@7.19.4": + hash: wjhgmpzh47qmycrzgpeyoyh3ce + path: patches/@babel__helper-string-parser@7.19.4.patch + +importers: + .: {} + + packages/a: + dependencies: + lodash: + specifier: ^4.17.21 + version: 4.17.21(patch_hash=lgum37zgng4nfkynzh3cs7wdeq) + + packages/b: + dependencies: + "@babel/helper-string-parser": + specifier: ^7.19.4 + version: 7.19.4(patch_hash=wjhgmpzh47qmycrzgpeyoyh3ce)(@babel/core@7.21.0) + +packages: + /@babel/helper-string-parser@7.19.4(patch_hash=wjhgmpzh47qmycrzgpeyoyh3ce)(@babel/core@7.21.0): + resolution: + { + integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==, + } + engines: { node: ">=6.9.0" } + dev: false + + /lodash@4.17.21(patch_hash=lgum37zgng4nfkynzh3cs7wdeq): + resolution: + { + integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==, + } + dev: false diff --git a/crates/turborepo-lockfiles/src/pnpm/data.rs b/crates/turborepo-lockfiles/src/pnpm/data.rs index 0bc1851b55125..0e34ff60440fa 100644 --- a/crates/turborepo-lockfiles/src/pnpm/data.rs +++ b/crates/turborepo-lockfiles/src/pnpm/data.rs @@ -12,7 +12,7 @@ pub enum Error { Yaml(#[from] serde_yaml::Error), } -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] #[serde(rename_all = "camelCase")] pub struct PnpmLockfileData { lockfile_version: LockfileVersion, @@ -26,25 +26,25 @@ pub struct PnpmLockfileData { time: Option>, } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Clone)] struct LockfileVersion { version: String, format: VersionFormat, } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Clone)] enum VersionFormat { String, Float, } -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct PatchFile { path: String, hash: String, } -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] #[serde(rename_all = "camelCase")] pub struct ProjectSnapshot { #[serde(flatten)] @@ -53,7 +53,7 @@ pub struct ProjectSnapshot { publish_directory: Option, } -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] #[serde(rename_all = "camelCase", untagged)] pub enum DependencyInfo { #[serde(rename_all = "camelCase")] @@ -71,7 +71,7 @@ pub enum DependencyInfo { }, } -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct Dependency { specifier: String, version: String, @@ -210,6 +210,13 @@ impl PnpmLockfileData { workspace_paths: &[String], packages: &[String], ) -> Result { + let importers = self + .importers + .iter() + .filter(|(key, _)| key.as_str() == "." || workspace_paths.contains(key)) + .map(|(k, v)| (k.clone(), v.clone())) + .collect::>(); + let mut pruned_packages = Map::new(); for package in packages { let entry = self @@ -217,7 +224,57 @@ impl PnpmLockfileData { .ok_or_else(|| crate::Error::MissingPackage(package.clone()))?; pruned_packages.insert(package.clone(), entry.clone()); } - todo!() + for importer in importers.values() { + for dependency in + importer + .dependencies_meta + .iter() + .flatten() + .filter_map(|(dep, meta)| match meta.injected { + Some(true) => Some(dep), + _ => None, + }) + { + let Some((_, version)) = importer.dependencies.find_resolution(dependency) else { + panic!("TODO error handling") + }; + + let entry = self + .get_packages(version) + .ok_or_else(|| crate::Error::MissingPackage(version.into()))?; + pruned_packages.insert(version.to_string(), entry.clone()); + } + } + + let patches = self.patched_dependencies.as_ref().map(|patches| { + let mut pruned_patches = Map::new(); + for dependency in pruned_packages.keys() { + let dp = DepPath::try_from(dependency.as_str()).unwrap(); + let patch_key = format!("{}@{}", dp.name, dp.version); + if let Some(patch) = patches + .get(&patch_key) + .filter(|patch| dp.patch_hash() == Some(&patch.hash)) + { + pruned_patches.insert(patch_key, patch.clone()); + } + } + pruned_patches + }); + + Ok(Self { + importers, + packages: match pruned_packages.is_empty() { + false => Some(pruned_packages), + true => None, + }, + lockfile_version: self.lockfile_version.clone(), + never_built_dependencies: self.never_built_dependencies.clone(), + only_built_dependencies: self.only_built_dependencies.clone(), + overrides: self.overrides.clone(), + package_extensions_checksum: self.package_extensions_checksum.clone(), + patched_dependencies: patches, + time: None, + }) } } @@ -391,6 +448,8 @@ mod tests { const PNPM_TOP_LEVEL_OVERRIDE: &[u8] = include_bytes!("../../fixtures/pnpm-top-level-dupe.yaml").as_slice(); const PNPM_OVERRIDE: &[u8] = include_bytes!("../../fixtures/pnpm-override.yaml").as_slice(); + const PNPM_PATCH: &[u8] = include_bytes!("../../fixtures/pnpm-patch.yaml").as_slice(); + const PNPM_PATCH_V6: &[u8] = include_bytes!("../../fixtures/pnpm-patch-v6.yaml").as_slice(); use super::*; use crate::Lockfile; @@ -628,4 +687,55 @@ mod tests { } } } + + #[test] + fn test_prune_patches() { + let lockfile = PnpmLockfileData::from_bytes(PNPM_PATCH).unwrap(); + let pruned = lockfile + .subgraph( + &["packages/dependency".into()], + &[ + "/is-odd/3.0.1_nrrwwz7lemethtlvvm75r5bmhq".into(), + "/is-number/6.0.0".into(), + "/@babel/core/7.20.12_3hyn7hbvzkemudbydlwjmrb65y".into(), + "/moleculer/0.14.28_5pk7ojv7qbqha75ozglk4y4f74_kumip57h7zlinbhp4gz3jrbqry" + .into(), + ], + ) + .unwrap(); + assert_eq!( + pruned.patches(), + vec![ + "patches/@babel__core@7.20.12.patch", + "patches/is-odd@3.0.1.patch", + "patches/moleculer@0.14.28.patch", + ] + ) + } + + #[test] + fn test_prune_patches_v6() { + let lockfile = PnpmLockfileData::from_bytes(PNPM_PATCH_V6).unwrap(); + let pruned = lockfile + .subgraph( + &["packages/a".into()], + &["/lodash@4.17.21(patch_hash=lgum37zgng4nfkynzh3cs7wdeq)".into()], + ) + .unwrap(); + assert_eq!(pruned.patches(), vec!["patches/lodash@4.17.21.patch"]); + + let pruned = + lockfile + .subgraph( + &["packages/b".into()], + &["/@babel/helper-string-parser@7.19.\ + 4(patch_hash=wjhgmpzh47qmycrzgpeyoyh3ce)(@babel/core@7.21.0)" + .into()], + ) + .unwrap(); + assert_eq!( + pruned.patches(), + vec!["patches/@babel__helper-string-parser@7.19.4.patch"] + ) + } } From 70ee7068dbba920ad9e70baea101cc7aa7355da6 Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Wed, 10 May 2023 18:58:04 -0700 Subject: [PATCH 04/11] slight code shuffling --- crates/turborepo-lockfiles/src/pnpm/data.rs | 69 +------------------ crates/turborepo-lockfiles/src/pnpm/de.rs | 40 +++++++++++ .../turborepo-lockfiles/src/pnpm/lockfile.rs | 5 -- crates/turborepo-lockfiles/src/pnpm/mod.rs | 15 +++- crates/turborepo-lockfiles/src/pnpm/ser.rs | 19 +++++ 5 files changed, 75 insertions(+), 73 deletions(-) create mode 100644 crates/turborepo-lockfiles/src/pnpm/de.rs delete mode 100644 crates/turborepo-lockfiles/src/pnpm/lockfile.rs create mode 100644 crates/turborepo-lockfiles/src/pnpm/ser.rs diff --git a/crates/turborepo-lockfiles/src/pnpm/data.rs b/crates/turborepo-lockfiles/src/pnpm/data.rs index 0e34ff60440fa..8908af5dbbd8b 100644 --- a/crates/turborepo-lockfiles/src/pnpm/data.rs +++ b/crates/turborepo-lockfiles/src/pnpm/data.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use serde::{Deserialize, Serialize}; -use super::dep_path::DepPath; +use super::{dep_path::DepPath, LockfileVersion}; type Map = std::collections::BTreeMap; @@ -26,18 +26,6 @@ pub struct PnpmLockfileData { time: Option>, } -#[derive(Debug, PartialEq, Eq, Clone)] -struct LockfileVersion { - version: String, - format: VersionFormat, -} - -#[derive(Debug, PartialEq, Eq, Clone)] -enum VersionFormat { - String, - Float, -} - #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct PatchFile { path: String, @@ -148,7 +136,7 @@ impl PnpmLockfileData { } fn is_v6(&self) -> bool { - matches!(self.lockfile_version.format, VersionFormat::String) + matches!(self.lockfile_version.format, super::VersionFormat::String) } fn format_key(&self, name: &str, version: &str) -> String { @@ -342,59 +330,6 @@ impl crate::Lockfile for PnpmLockfileData { } } -impl From for LockfileVersion { - fn from(value: f32) -> Self { - Self { - version: value.to_string(), - format: VersionFormat::Float, - } - } -} - -impl From for LockfileVersion { - fn from(value: String) -> Self { - Self { - version: value, - format: VersionFormat::String, - } - } -} - -impl<'de> Deserialize<'de> for LockfileVersion { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - #[derive(Deserialize)] - #[serde(untagged)] - enum StringOrNum { - Str(String), - Num(f32), - } - - Ok(match StringOrNum::deserialize(deserializer)? { - StringOrNum::Num(x) => LockfileVersion::from(x), - StringOrNum::Str(s) => LockfileVersion::from(s), - }) - } -} - -impl Serialize for LockfileVersion { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - match self.format { - VersionFormat::String => serializer.serialize_str(&self.version), - VersionFormat::Float => serializer.serialize_f32( - self.version - .parse() - .expect("Expected lockfile version to be valid f32"), - ), - } - } -} - impl DependencyInfo { pub fn find_resolution(&self, dependency: &str) -> Option<(&str, &str)> { match self { diff --git a/crates/turborepo-lockfiles/src/pnpm/de.rs b/crates/turborepo-lockfiles/src/pnpm/de.rs new file mode 100644 index 0000000000000..106ac6e7f42dc --- /dev/null +++ b/crates/turborepo-lockfiles/src/pnpm/de.rs @@ -0,0 +1,40 @@ +use serde::Deserialize; + +use super::{LockfileVersion, VersionFormat}; + +impl From for LockfileVersion { + fn from(value: f32) -> Self { + Self { + version: value.to_string(), + format: VersionFormat::Float, + } + } +} + +impl From for LockfileVersion { + fn from(value: String) -> Self { + Self { + version: value, + format: VersionFormat::String, + } + } +} + +impl<'de> Deserialize<'de> for LockfileVersion { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + #[derive(Deserialize)] + #[serde(untagged)] + enum StringOrNum { + Str(String), + Num(f32), + } + + Ok(match StringOrNum::deserialize(deserializer)? { + StringOrNum::Num(x) => LockfileVersion::from(x), + StringOrNum::Str(s) => LockfileVersion::from(s), + }) + } +} diff --git a/crates/turborepo-lockfiles/src/pnpm/lockfile.rs b/crates/turborepo-lockfiles/src/pnpm/lockfile.rs deleted file mode 100644 index 7d5cc96d4cb3a..0000000000000 --- a/crates/turborepo-lockfiles/src/pnpm/lockfile.rs +++ /dev/null @@ -1,5 +0,0 @@ -use super::data::{PnpmLockfileData, ProjectSnapshot}; - -pub struct PnpmLockfile<'a> { - data: &'a PnpmLockfileData, -} diff --git a/crates/turborepo-lockfiles/src/pnpm/mod.rs b/crates/turborepo-lockfiles/src/pnpm/mod.rs index 4f2e3654fc88e..b55f6d9eb35c5 100644 --- a/crates/turborepo-lockfiles/src/pnpm/mod.rs +++ b/crates/turborepo-lockfiles/src/pnpm/mod.rs @@ -1,3 +1,16 @@ mod data; +mod de; mod dep_path; -mod lockfile; +mod ser; + +#[derive(Debug, PartialEq, Eq, Clone)] +struct LockfileVersion { + version: String, + format: VersionFormat, +} + +#[derive(Debug, PartialEq, Eq, Clone)] +enum VersionFormat { + String, + Float, +} diff --git a/crates/turborepo-lockfiles/src/pnpm/ser.rs b/crates/turborepo-lockfiles/src/pnpm/ser.rs new file mode 100644 index 0000000000000..632c91a7a3ccd --- /dev/null +++ b/crates/turborepo-lockfiles/src/pnpm/ser.rs @@ -0,0 +1,19 @@ +use serde::Serialize; + +use super::{LockfileVersion, VersionFormat}; + +impl Serialize for LockfileVersion { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + match self.format { + VersionFormat::String => serializer.serialize_str(&self.version), + VersionFormat::Float => serializer.serialize_f32( + self.version + .parse() + .expect("Expected lockfile version to be valid f32"), + ), + } + } +} From 58b18972f2e568d3b56d6b52e029265976f4461f Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Thu, 11 May 2023 04:58:55 -0700 Subject: [PATCH 05/11] remove all unwrap and panics --- crates/turborepo-lockfiles/src/error.rs | 4 + crates/turborepo-lockfiles/src/lib.rs | 1 + crates/turborepo-lockfiles/src/pnpm/data.rs | 108 ++++++++++-------- .../turborepo-lockfiles/src/pnpm/dep_path.rs | 2 - crates/turborepo-lockfiles/src/pnpm/mod.rs | 21 ++++ 5 files changed, 89 insertions(+), 47 deletions(-) diff --git a/crates/turborepo-lockfiles/src/error.rs b/crates/turborepo-lockfiles/src/error.rs index 1668371e17b75..791765741a7a8 100644 --- a/crates/turborepo-lockfiles/src/error.rs +++ b/crates/turborepo-lockfiles/src/error.rs @@ -10,6 +10,10 @@ pub enum Error { MissingVersion(String), #[error("Unable to convert from json")] JsonError(#[from] serde_json::Error), + #[error("Unable to convert to yaml: {0}")] + Yaml(#[from] serde_yaml::Error), #[error("Turbo doesn't support npm lockfiles without a 'packages' field")] UnsupportedNpmVersion, + #[error(transparent)] + Pnpm(#[from] crate::pnpm::Error), } diff --git a/crates/turborepo-lockfiles/src/lib.rs b/crates/turborepo-lockfiles/src/lib.rs index e605e7bdc17ef..7fbdb2a24199f 100644 --- a/crates/turborepo-lockfiles/src/lib.rs +++ b/crates/turborepo-lockfiles/src/lib.rs @@ -10,6 +10,7 @@ use std::collections::{HashMap, HashSet}; pub use berry::{Error as BerryError, *}; pub use error::Error; pub use npm::*; +pub use pnpm::{pnpm_global_change, pnpm_subgraph, PnpmLockfile}; use serde::Serialize; #[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord, Hash, Serialize)] diff --git a/crates/turborepo-lockfiles/src/pnpm/data.rs b/crates/turborepo-lockfiles/src/pnpm/data.rs index 8908af5dbbd8b..6724c1301cb00 100644 --- a/crates/turborepo-lockfiles/src/pnpm/data.rs +++ b/crates/turborepo-lockfiles/src/pnpm/data.rs @@ -2,19 +2,13 @@ use std::borrow::Cow; use serde::{Deserialize, Serialize}; -use super::{dep_path::DepPath, LockfileVersion}; +use super::{dep_path::DepPath, Error, LockfileVersion}; type Map = std::collections::BTreeMap; -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("yaml: {0}")] - Yaml(#[from] serde_yaml::Error), -} - #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] #[serde(rename_all = "camelCase")] -pub struct PnpmLockfileData { +pub struct PnpmLockfile { lockfile_version: LockfileVersion, never_built_dependencies: Option>, only_built_dependencies: Option>, @@ -101,8 +95,8 @@ pub struct PackageResolution { commit: Option, } -impl PnpmLockfileData { - pub fn from_bytes(bytes: &[u8]) -> Result { +impl PnpmLockfile { + pub fn from_bytes(bytes: &[u8]) -> Result { let this = serde_yaml::from_slice(bytes)?; Ok(this) } @@ -146,16 +140,16 @@ impl PnpmLockfileData { } } - fn extract_version<'a>(&self, key: &'a str) -> Option> { - let dp = DepPath::try_from(key).ok()?; + fn extract_version<'a>(&self, key: &'a str) -> Result, Error> { + let dp = DepPath::try_from(key)?; if let Some(suffix) = dp.peer_suffix { let sep = match self.is_v6() { true => "", false => "_", }; - Some(format!("{}{}{}", dp.version, sep, suffix).into()) + Ok(format!("{}{}{}", dp.version, sep, suffix).into()) } else { - Some(dp.version.into()) + Ok(dp.version.into()) } } @@ -223,9 +217,10 @@ impl PnpmLockfileData { _ => None, }) { - let Some((_, version)) = importer.dependencies.find_resolution(dependency) else { - panic!("TODO error handling") - }; + let (_, version) = importer + .dependencies + .find_resolution(dependency) + .ok_or_else(|| Error::MissingInjectedPackage(dependency.clone()))?; let entry = self .get_packages(version) @@ -234,20 +229,11 @@ impl PnpmLockfileData { } } - let patches = self.patched_dependencies.as_ref().map(|patches| { - let mut pruned_patches = Map::new(); - for dependency in pruned_packages.keys() { - let dp = DepPath::try_from(dependency.as_str()).unwrap(); - let patch_key = format!("{}@{}", dp.name, dp.version); - if let Some(patch) = patches - .get(&patch_key) - .filter(|patch| dp.patch_hash() == Some(&patch.hash)) - { - pruned_patches.insert(patch_key, patch.clone()); - } - } - pruned_patches - }); + let patches = self + .patched_dependencies + .as_ref() + .map(|patches| Self::prune_patches(patches, &pruned_packages)) + .transpose()?; Ok(Self { importers, @@ -264,9 +250,27 @@ impl PnpmLockfileData { time: None, }) } + + fn prune_patches( + patches: &Map, + pruned_packages: &Map, + ) -> Result, Error> { + let mut pruned_patches = Map::new(); + for dependency in pruned_packages.keys() { + let dp = DepPath::try_from(dependency.as_str())?; + let patch_key = format!("{}@{}", dp.name, dp.version); + if let Some(patch) = patches + .get(&patch_key) + .filter(|patch| dp.patch_hash() == Some(&patch.hash)) + { + pruned_patches.insert(patch_key, patch.clone()); + } + } + Ok(pruned_patches) + } } -impl crate::Lockfile for PnpmLockfileData { +impl crate::Lockfile for PnpmLockfile { fn resolve_package( &self, workspace_path: &str, @@ -275,8 +279,7 @@ impl crate::Lockfile for PnpmLockfileData { ) -> Result, crate::Error> { // Check if version is a key if self.get_packages(version).is_some() { - // TODO no unwrap - let extracted_version = self.extract_version(version).unwrap(); + let extracted_version = self.extract_version(version)?; return Ok(Some(crate::Package { key: version.into(), version: extracted_version.into(), @@ -298,13 +301,16 @@ impl crate::Lockfile for PnpmLockfileData { .unwrap_or_else(|| resolved_version.to_string()), })) } else if let Some(pkg) = self.get_packages(resolved_version) { + let version = pkg.version.clone().map_or_else( + || { + self.extract_version(resolved_version) + .map(|s| s.to_string()) + }, + Ok, + )?; Ok(Some(crate::Package { key: resolved_version.to_string(), - version: pkg - .version - .clone() - // TODO avoid unwrap here? - .unwrap_or_else(|| self.extract_version(resolved_version).unwrap().to_string()), + version, })) } else { Ok(None) @@ -368,6 +374,18 @@ impl Dependency { } } +pub fn pnpm_global_change( + prev_contents: &[u8], + curr_contents: &[u8], +) -> Result { + let prev_data = PnpmLockfile::from_bytes(prev_contents)?; + let curr_data = PnpmLockfile::from_bytes(curr_contents)?; + Ok(prev_data.lockfile_version != curr_data.lockfile_version + || prev_data.package_extensions_checksum != curr_data.package_extensions_checksum + || prev_data.overrides != curr_data.overrides + || prev_data.patched_dependencies != curr_data.patched_dependencies) +} + #[cfg(test)] mod tests { use pretty_assertions::assert_eq; @@ -392,7 +410,7 @@ mod tests { #[test] fn test_roundtrip() { for fixture in &[PNPM6, PNPM7, PNPM8] { - let lockfile = PnpmLockfileData::from_bytes(fixture).unwrap(); + let lockfile = PnpmLockfile::from_bytes(fixture).unwrap(); let serialized_lockfile = serde_yaml::to_string(&lockfile).unwrap(); let lockfile_from_serialized = serde_yaml::from_slice(serialized_lockfile.as_bytes()).unwrap(); @@ -403,7 +421,7 @@ mod tests { #[test] fn test_patches() { let lockfile = - PnpmLockfileData::from_bytes(include_bytes!("../../fixtures/pnpm-patch.yaml")).unwrap(); + PnpmLockfile::from_bytes(include_bytes!("../../fixtures/pnpm-patch.yaml")).unwrap(); assert_eq!( lockfile.patches(), vec![ @@ -517,7 +535,7 @@ mod tests { specifier: &str, expected: Result, &str>, ) { - let lockfile = PnpmLockfileData::from_bytes(lockfile).unwrap(); + let lockfile = PnpmLockfile::from_bytes(lockfile).unwrap(); let actual = lockfile.resolve_specifier(workspace_path, package, specifier); match (actual, expected) { @@ -607,7 +625,7 @@ mod tests { specifier: &str, expected: Result, &str>, ) { - let lockfile = PnpmLockfileData::from_bytes(lockfile).unwrap(); + let lockfile = PnpmLockfile::from_bytes(lockfile).unwrap(); let actual = lockfile.resolve_package(workspace_path, package, specifier); match (actual, expected) { (Ok(actual), Ok(expected)) => assert_eq!(actual, expected), @@ -625,7 +643,7 @@ mod tests { #[test] fn test_prune_patches() { - let lockfile = PnpmLockfileData::from_bytes(PNPM_PATCH).unwrap(); + let lockfile = PnpmLockfile::from_bytes(PNPM_PATCH).unwrap(); let pruned = lockfile .subgraph( &["packages/dependency".into()], @@ -650,7 +668,7 @@ mod tests { #[test] fn test_prune_patches_v6() { - let lockfile = PnpmLockfileData::from_bytes(PNPM_PATCH_V6).unwrap(); + let lockfile = PnpmLockfile::from_bytes(PNPM_PATCH_V6).unwrap(); let pruned = lockfile .subgraph( &["packages/a".into()], diff --git a/crates/turborepo-lockfiles/src/pnpm/dep_path.rs b/crates/turborepo-lockfiles/src/pnpm/dep_path.rs index 79a7a8c2fd71b..6b4f0eb8e1a8c 100644 --- a/crates/turborepo-lockfiles/src/pnpm/dep_path.rs +++ b/crates/turborepo-lockfiles/src/pnpm/dep_path.rs @@ -1,5 +1,3 @@ -use std::borrow::Cow; - use nom::{ branch::alt, bytes::complete::{is_not, tag}, diff --git a/crates/turborepo-lockfiles/src/pnpm/mod.rs b/crates/turborepo-lockfiles/src/pnpm/mod.rs index b55f6d9eb35c5..5cd15b1287230 100644 --- a/crates/turborepo-lockfiles/src/pnpm/mod.rs +++ b/crates/turborepo-lockfiles/src/pnpm/mod.rs @@ -3,6 +3,16 @@ mod de; mod dep_path; mod ser; +pub use data::{pnpm_global_change, PnpmLockfile}; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("error parsing dependency path: {0}")] + DependencyPath(#[from] nom::error::Error), + #[error("Unable to find '{0}' other than reference in dependenciesMeta")] + MissingInjectedPackage(String), +} + #[derive(Debug, PartialEq, Eq, Clone)] struct LockfileVersion { version: String, @@ -14,3 +24,14 @@ enum VersionFormat { String, Float, } + +pub fn pnpm_subgraph( + contents: &[u8], + workspace_packages: &[String], + packages: &[String], +) -> Result, crate::Error> { + let lockfile = PnpmLockfile::from_bytes(contents)?; + let pruned_lockfile = lockfile.subgraph(workspace_packages, packages)?; + let new_contents = serde_yaml::to_string(&pruned_lockfile)?.into_bytes(); + Ok(new_contents) +} From 67e4e65a47893585e67d3bfb8459bc3b05b938d7 Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Thu, 11 May 2023 05:40:05 -0700 Subject: [PATCH 06/11] switch over to rust impl --- cli/internal/ffi/ffi.go | 2 + cli/internal/ffi/proto/messages.pb.go | 10 +- cli/internal/lockfile/lockfile.go | 3 + cli/internal/lockfile/pnpm_lockfile.go | 551 +------------------- cli/internal/lockfile/pnpm_lockfile_test.go | 360 +------------ crates/turborepo-ffi/messages.proto | 1 + crates/turborepo-ffi/src/lockfile.rs | 27 +- 7 files changed, 68 insertions(+), 886 deletions(-) diff --git a/cli/internal/ffi/ffi.go b/cli/internal/ffi/ffi.go index b59846fa73bb0..a18a8032ab33c 100644 --- a/cli/internal/ffi/ffi.go +++ b/cli/internal/ffi/ffi.go @@ -216,6 +216,8 @@ func toPackageManager(packageManager string) ffi_proto.PackageManager { return ffi_proto.PackageManager_NPM case "berry": return ffi_proto.PackageManager_BERRY + case "pnpm": + return ffi_proto.PackageManager_PNPM default: panic(fmt.Sprintf("Invalid package manager string: %s", packageManager)) } diff --git a/cli/internal/ffi/proto/messages.pb.go b/cli/internal/ffi/proto/messages.pb.go index 553b205c07904..efe5d226c0b7c 100644 --- a/cli/internal/ffi/proto/messages.pb.go +++ b/cli/internal/ffi/proto/messages.pb.go @@ -25,6 +25,7 @@ type PackageManager int32 const ( PackageManager_NPM PackageManager = 0 PackageManager_BERRY PackageManager = 1 + PackageManager_PNPM PackageManager = 2 ) // Enum value maps for PackageManager. @@ -32,10 +33,12 @@ var ( PackageManager_name = map[int32]string{ 0: "NPM", 1: "BERRY", + 2: "PNPM", } PackageManager_value = map[string]int32{ "NPM": 0, "BERRY": 1, + "PNPM": 2, } ) @@ -1843,10 +1846,11 @@ var file_turborepo_ffi_messages_proto_rawDesc = []byte{ 0x76, 0x65, 0x43, 0x6f, 0x70, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x2a, 0x24, 0x0a, 0x0e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x61, + 0x72, 0x6f, 0x72, 0x2a, 0x2e, 0x0a, 0x0e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x07, 0x0a, 0x03, 0x4e, 0x50, 0x4d, 0x10, 0x00, 0x12, 0x09, - 0x0a, 0x05, 0x42, 0x45, 0x52, 0x52, 0x59, 0x10, 0x01, 0x42, 0x0b, 0x5a, 0x09, 0x66, 0x66, 0x69, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x0a, 0x05, 0x42, 0x45, 0x52, 0x52, 0x59, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x4e, 0x50, + 0x4d, 0x10, 0x02, 0x42, 0x0b, 0x5a, 0x09, 0x66, 0x66, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/cli/internal/lockfile/lockfile.go b/cli/internal/lockfile/lockfile.go index 81667fde7abdc..7aaa75b746dd1 100644 --- a/cli/internal/lockfile/lockfile.go +++ b/cli/internal/lockfile/lockfile.go @@ -79,6 +79,9 @@ func AllTransitiveClosures( if lf, ok := lockFile.(*BerryLockfile); ok { return rustTransitiveDeps(lf.contents, "berry", workspaces, lf.resolutions) } + if lf, ok := lockFile.(*PnpmLockfile); ok { + return rustTransitiveDeps(lf.contents, "pnpm", workspaces, nil) + } g := new(errgroup.Group) c := make(chan closureMsg, len(workspaces)) diff --git a/cli/internal/lockfile/pnpm_lockfile.go b/cli/internal/lockfile/pnpm_lockfile.go index a51b36e768a9a..474e888187cc4 100644 --- a/cli/internal/lockfile/pnpm_lockfile.go +++ b/cli/internal/lockfile/pnpm_lockfile.go @@ -1,579 +1,78 @@ package lockfile import ( - "fmt" "io" - "reflect" - "sort" - "strings" - "github.com/pkg/errors" + "github.com/vercel/turbo/cli/internal/ffi" "github.com/vercel/turbo/cli/internal/turbopath" - "github.com/vercel/turbo/cli/internal/yaml" ) // PnpmLockfile Go representation of the contents of 'pnpm-lock.yaml' // Reference https://github.com/pnpm/pnpm/blob/main/packages/lockfile-types/src/index.ts type PnpmLockfile struct { - isV6 bool - // Before 6.0 version was stored as a float, but as of 6.0+ it's a string - Version interface{} `yaml:"lockfileVersion"` - NeverBuiltDependencies []string `yaml:"neverBuiltDependencies,omitempty"` - OnlyBuiltDependencies []string `yaml:"onlyBuiltDependencies,omitempty"` - Overrides map[string]string `yaml:"overrides,omitempty"` - PackageExtensionsChecksum string `yaml:"packageExtensionsChecksum,omitempty"` - PatchedDependencies map[string]PatchFile `yaml:"patchedDependencies,omitempty"` - Importers map[string]ProjectSnapshot `yaml:"importers"` - Packages map[string]PackageSnapshot `yaml:"packages,omitempty"` - Time map[string]string `yaml:"time,omitempty"` + contents []byte } var _ Lockfile = (*PnpmLockfile)(nil) -// ProjectSnapshot Snapshot used to represent projects in the importers section -type ProjectSnapshot struct { - // for v6 we omitempty - // for pre v6 we *need* to omit the empty map - Specifiers SpecifierMap `yaml:"specifiers,omitempty"` - - // The values of these maps will be string if lockfileVersion <6 or DependencyV6 if 6+ - Dependencies map[string]yaml.Node `yaml:"dependencies,omitempty"` - OptionalDependencies map[string]yaml.Node `yaml:"optionalDependencies,omitempty"` - DevDependencies map[string]yaml.Node `yaml:"devDependencies,omitempty"` - - DependenciesMeta map[string]DependenciesMeta `yaml:"dependenciesMeta,omitempty"` - PublishDirectory string `yaml:"publishDirectory,omitempty"` -} - -// SpecifierMap is a type wrapper that overrides IsZero for Golang's map -// to match the behavior that pnpm expects -type SpecifierMap map[string]string - -// IsZero is used to check whether an object is zero to -// determine whether it should be omitted when marshaling -// with the omitempty flag. -func (m SpecifierMap) IsZero() bool { - return m == nil -} - -var _ (yaml.IsZeroer) = (*SpecifierMap)(nil) - -// DependencyV6 are dependency entries for lockfileVersion 6.0+ -type DependencyV6 struct { - Specifier string `yaml:"specifier"` - Version string `yaml:"version"` -} - -// Will try to find a resolution in any of the dependency fields -func (p *ProjectSnapshot) findResolution(dependency string) (DependencyV6, bool, error) { - var getResolution func(yaml.Node) (DependencyV6, bool, error) - if len(p.Specifiers) > 0 { - getResolution = func(node yaml.Node) (DependencyV6, bool, error) { - specifier, ok := p.Specifiers[dependency] - if !ok { - return DependencyV6{}, false, nil - } - var version string - if err := node.Decode(&version); err != nil { - return DependencyV6{}, false, err - } - return DependencyV6{Version: version, Specifier: specifier}, true, nil - } - } else { - getResolution = func(node yaml.Node) (DependencyV6, bool, error) { - var resolution DependencyV6 - if err := node.Decode(&resolution); err != nil { - return DependencyV6{}, false, err - } - return resolution, true, nil - } - } - if resolution, ok := p.Dependencies[dependency]; ok { - return getResolution(resolution) - } - if resolution, ok := p.DevDependencies[dependency]; ok { - return getResolution(resolution) - } - if resolution, ok := p.OptionalDependencies[dependency]; ok { - return getResolution(resolution) - } - return DependencyV6{}, false, nil -} - -// PackageSnapshot Snapshot used to represent a package in the packages setion -type PackageSnapshot struct { - Resolution PackageResolution `yaml:"resolution,flow"` - ID string `yaml:"id,omitempty"` - - // only needed for packages that aren't in npm - Name string `yaml:"name,omitempty"` - Version string `yaml:"version,omitempty"` - - Engines struct { - Node string `yaml:"node"` - NPM string `yaml:"npm,omitempty"` - } `yaml:"engines,omitempty,flow"` - CPU []string `yaml:"cpu,omitempty,flow"` - Os []string `yaml:"os,omitempty,flow"` - LibC []string `yaml:"libc,omitempty"` - - Deprecated string `yaml:"deprecated,omitempty"` - HasBin bool `yaml:"hasBin,omitempty"` - Prepare bool `yaml:"prepare,omitempty"` - RequiresBuild bool `yaml:"requiresBuild,omitempty"` - - BundledDependencies []string `yaml:"bundledDependencies,omitempty"` - PeerDependencies map[string]string `yaml:"peerDependencies,omitempty"` - PeerDependenciesMeta map[string]struct { - Optional bool `yaml:"optional"` - } `yaml:"peerDependenciesMeta,omitempty"` - - Dependencies map[string]string `yaml:"dependencies,omitempty"` - OptionalDependencies map[string]string `yaml:"optionalDependencies,omitempty"` - - TransitivePeerDependencies []string `yaml:"transitivePeerDependencies,omitempty"` - Dev bool `yaml:"dev"` - Optional bool `yaml:"optional,omitempty"` - Patched bool `yaml:"patched,omitempty"` -} - -// PackageResolution Various resolution strategies for packages -type PackageResolution struct { - Type string `yaml:"type,omitempty"` - // For npm or tarball - Integrity string `yaml:"integrity,omitempty"` - - // For tarball - Tarball string `yaml:"tarball,omitempty"` - - // For local directory - Dir string `yaml:"directory,omitempty"` - - // For git repo - Repo string `yaml:"repo,omitempty"` - Commit string `yaml:"commit,omitempty"` -} - -// PatchFile represent a patch applied to a package -type PatchFile struct { - Path string `yaml:"path"` - Hash string `yaml:"hash"` -} - -func isSupportedVersion(version interface{}) error { - switch version.(type) { - case string: - if version == "6.0" { - return nil - } - case float64: - if version == 5.3 || version == 5.4 { - return nil - } - default: - return fmt.Errorf("lockfileVersion of type %T is invalid", version) - } - supportedVersions := []string{"5.3", "5.4", "6.0"} - return errors.Errorf("Unable to generate pnpm-lock.yaml with lockfileVersion: %s. Supported lockfile versions are %v", version, supportedVersions) -} - -// DependenciesMeta metadata for dependencies -type DependenciesMeta struct { - Injected bool `yaml:"injected,omitempty"` - Node string `yaml:"node,omitempty"` - Patch string `yaml:"patch,omitempty"` -} - // DecodePnpmLockfile parse a pnpm lockfile func DecodePnpmLockfile(contents []byte) (*PnpmLockfile, error) { - var lockfile PnpmLockfile - err := yaml.Unmarshal(contents, &lockfile) - if err != nil { - return nil, errors.Wrap(err, "could not unmarshal lockfile: ") - } - - switch lockfile.Version.(type) { - case float64: - lockfile.isV6 = false - case string: - lockfile.isV6 = true - default: - return nil, fmt.Errorf("Unexpected type of lockfileVersion: '%T', expected float64 or string", lockfile.Version) - } - return &lockfile, nil + return &PnpmLockfile{contents: contents}, nil } // ResolvePackage Given a package and version returns the key, resolved version, and if it was found func (p *PnpmLockfile) ResolvePackage(workspacePath turbopath.AnchoredUnixPath, name string, version string) (Package, error) { - // Check if version is a key - if _, ok := p.Packages[version]; ok { - return Package{Key: version, Version: p.extractVersion(version), Found: true}, nil - } - - resolvedVersion, ok, err := p.resolveSpecifier(workspacePath, name, version) - if !ok || err != nil { - return Package{}, err - } - key := p.formatKey(name, resolvedVersion) - if entry, ok := (p.Packages)[key]; ok { - var version string - if entry.Version != "" { - version = entry.Version - } else { - version = resolvedVersion - } - return Package{Key: key, Version: version, Found: true}, nil - } - - if entry, ok := p.Packages[resolvedVersion]; ok { - var version string - if entry.Version != "" { - version = entry.Version - } else { - // If there isn't a version field in the entry then the version is - // encoded in the key and we can omit the name from the version. - version = p.extractVersion(resolvedVersion) - } - return Package{Key: resolvedVersion, Version: version, Found: true}, nil - } - - return Package{}, nil + // This is only used when doing calculating the transitive deps, but Rust + // implementations do this calculation on the Rust side. + panic("Unreachable") } // AllDependencies Given a lockfile key return all (dev/optional/peer) dependencies of that package func (p *PnpmLockfile) AllDependencies(key string) (map[string]string, bool) { - deps := map[string]string{} - entry, ok := p.Packages[key] - if !ok { - return deps, false - } - - for name, version := range entry.Dependencies { - deps[name] = version - } - - for name, version := range entry.OptionalDependencies { - deps[name] = version - } - - // Peer dependencies appear in the Dependencies map resolved - - return deps, true + // This is only used when doing calculating the transitive deps, but Rust + // implementations do this calculation on the Rust side. + panic("Unreachable") } // Subgraph Given a list of lockfile keys returns a Lockfile based off the original one that only contains the packages given func (p *PnpmLockfile) Subgraph(workspacePackages []turbopath.AnchoredSystemPath, packages []string) (Lockfile, error) { - lockfilePackages := make(map[string]PackageSnapshot, len(packages)) - for _, key := range packages { - entry, ok := p.Packages[key] - if ok { - lockfilePackages[key] = entry - } else { - return nil, fmt.Errorf("Unable to find lockfile entry for %s", key) - } + workspaces := make([]string, len(workspacePackages)) + for i, workspace := range workspacePackages { + workspaces[i] = workspace.ToUnixPath().ToString() } - - importers, err := pruneImporters(p.Importers, workspacePackages) + contents, err := ffi.Subgraph("pnpm", p.contents, workspaces, packages, nil) if err != nil { return nil, err } - - for _, importer := range importers { - for dependency, meta := range importer.DependenciesMeta { - if meta.Injected { - resolution, ok, err := importer.findResolution(dependency) - if err != nil { - return nil, errors.Wrapf(err, "Unable to decode reference to %s", dependency) - } - if !ok { - return nil, fmt.Errorf("Unable to find %s other than reference in dependenciesMeta", dependency) - } - entry, ok := p.Packages[resolution.Version] - if !ok { - return nil, fmt.Errorf("Unable to find package entry for %s", resolution) - } - - lockfilePackages[resolution.Version] = entry - } - } - } - - lockfile := PnpmLockfile{ - Version: p.Version, - Packages: lockfilePackages, - NeverBuiltDependencies: p.NeverBuiltDependencies, - OnlyBuiltDependencies: p.OnlyBuiltDependencies, - Overrides: p.Overrides, - PackageExtensionsChecksum: p.PackageExtensionsChecksum, - PatchedDependencies: p.prunePatches(p.PatchedDependencies, lockfilePackages), - Importers: importers, - } - - return &lockfile, nil -} - -// Prune imports to only those have all of their dependencies in the packages list -func pruneImporters(importers map[string]ProjectSnapshot, workspacePackages []turbopath.AnchoredSystemPath) (map[string]ProjectSnapshot, error) { - prunedImporters := map[string]ProjectSnapshot{} - - // Copy over root level importer - if root, ok := importers["."]; ok { - prunedImporters["."] = root - } - - for _, workspacePath := range workspacePackages { - workspace := workspacePath.ToUnixPath().ToString() - importer, ok := importers[workspace] - - // If a workspace has no dependencies *and* it is only depended on by the - // workspace root it will not show up as an importer. - if ok { - prunedImporters[workspace] = importer - } - - } - - return prunedImporters, nil -} - -func (p *PnpmLockfile) prunePatches(patches map[string]PatchFile, packages map[string]PackageSnapshot) map[string]PatchFile { - if len(patches) == 0 { - return nil - } - - patchPackages := make(map[string]PatchFile, len(patches)) - for dependency := range packages { - if p.isV6 { - // Internally pnpm partially converts the new path format to the old - // format in order for existing parsing logic to work. - dependency = convertNewToOldDepPath(dependency) - } - dp := parseDepPath(dependency) - patchKey := fmt.Sprintf("%s@%s", dp.name, dp.version) - - if patch, ok := patches[patchKey]; ok && patch.Hash == dp.patchHash() { - patchPackages[patchKey] = patch - } - } - - return patchPackages + return &PnpmLockfile{contents: contents}, nil } // Encode encode the lockfile representation and write it to the given writer func (p *PnpmLockfile) Encode(w io.Writer) error { - if err := isSupportedVersion(p.Version); err != nil { - return err - } - - encoder := yaml.NewEncoder(w) - encoder.SetIndent(2) - - if err := encoder.Encode(p); err != nil { - return errors.Wrap(err, "unable to encode pnpm lockfile") - } - return nil + _, err := w.Write(p.contents) + return err } // Patches return a list of patches used in the lockfile func (p *PnpmLockfile) Patches() []turbopath.AnchoredUnixPath { - if len(p.PatchedDependencies) == 0 { + rawPatches := ffi.Patches(p.contents, "berry") + if len(rawPatches) == 0 { return nil } - patches := make([]string, len(p.PatchedDependencies)) - i := 0 - for _, patch := range p.PatchedDependencies { - patches[i] = patch.Path - i++ - } - sort.Strings(patches) - - patchPaths := make([]turbopath.AnchoredUnixPath, len(p.PatchedDependencies)) - for i, patch := range patches { - patchPaths[i] = turbopath.AnchoredUnixPath(patch) + patches := make([]turbopath.AnchoredUnixPath, len(rawPatches)) + for i, patch := range rawPatches { + patches[i] = turbopath.AnchoredUnixPath(patch) } - return patchPaths + return patches } // GlobalChange checks if there are any differences between lockfiles that would completely invalidate // the cache. func (p *PnpmLockfile) GlobalChange(other Lockfile) bool { - o, ok := other.(*PnpmLockfile) - return !ok || - p.Version != o.Version || - p.PackageExtensionsChecksum != o.PackageExtensionsChecksum || - !reflect.DeepEqual(p.Overrides, o.Overrides) || - !reflect.DeepEqual(p.PatchedDependencies, o.PatchedDependencies) -} - -func (p *PnpmLockfile) resolveSpecifier(workspacePath turbopath.AnchoredUnixPath, name string, specifier string) (string, bool, error) { - pnpmWorkspacePath := workspacePath.ToString() - if pnpmWorkspacePath == "" { - // For pnpm, the root is named "." - pnpmWorkspacePath = "." - } - importer, ok := p.Importers[pnpmWorkspacePath] + o, ok := other.(*BerryLockfile) if !ok { - return "", false, fmt.Errorf("no workspace '%v' found in lockfile", workspacePath) - } - resolution, ok, err := importer.findResolution(name) - if err != nil { - return "", false, err - } - // Verify that the specifier in the importer matches the one given - if !ok { - // Check if the specifier is already a resolved version - if _, ok := p.Packages[p.formatKey(name, specifier)]; ok { - return specifier, true, nil - } - return "", false, fmt.Errorf("Unable to find resolved version for %s@%s in %s", name, specifier, workspacePath) - } - overrideSpecifier := p.applyOverrides(name, specifier) - if resolution.Specifier != overrideSpecifier { - if _, ok := p.Packages[p.formatKey(name, overrideSpecifier)]; ok { - return overrideSpecifier, true, nil - } - return "", false, nil - } - return resolution.Version, true, nil -} - -// Apply pnpm overrides to specifier, see https://pnpm.io/package_json#pnpmoverrides -// Note this is barebones support and will only supports global overrides -// future work will support semver ranges and selector filtering. -func (p *PnpmLockfile) applyOverrides(name string, specifier string) string { - if len(p.Overrides) > 0 { - if new, ok := p.Overrides[name]; ok { - return new - } - } - return specifier -} - -// Formatter of the lockfile key given a package name and version -func (p *PnpmLockfile) formatKey(name string, version string) string { - if p.isV6 { - return fmt.Sprintf("/%s@%s", name, version) - } - return fmt.Sprintf("/%s/%s", name, version) -} - -// Extracts version from lockfile key -func (p *PnpmLockfile) extractVersion(key string) string { - if p.isV6 { - key = convertNewToOldDepPath(key) - } - dp := parseDepPath(key) - if dp.peerSuffix != "" { - sep := "" - if !p.isV6 { - sep = "_" - } - return fmt.Sprintf("%s%s%s", dp.version, sep, dp.peerSuffix) - } - return dp.version -} - -// Parsed representation of a pnpm lockfile key -type depPath struct { - host string - name string - version string - peerSuffix string -} - -func parseDepPath(dependency string) depPath { - // See https://github.com/pnpm/pnpm/blob/185ab01adfc927ea23d2db08a14723bf51d0025f/packages/dependency-path/src/index.ts#L96 - var dp depPath - parts := strings.Split(dependency, "/") - shift := func() string { - if len(parts) == 0 { - return "" - } - val := parts[0] - parts = parts[1:] - return val - } - - isAbsolute := dependency[0] != '/' - // Skip leading '/' - if !isAbsolute { - shift() - } - - if isAbsolute { - dp.host = shift() + return true } - if len(parts) == 0 { - return dp - } - - if strings.HasPrefix(parts[0], "@") { - dp.name = fmt.Sprintf("%s/%s", shift(), shift()) - } else { - dp.name = shift() - } - - version := strings.Join(parts, "/") - if len(version) > 0 { - var peerSuffixIndex int - if strings.Contains(version, "(") && strings.HasSuffix(version, ")") { - // v6 encodes peers deps using (peer=version) - // also used to encode patches using (path_hash=hash) - peerSuffixIndex = strings.Index(version, "(") - dp.peerSuffix = version[peerSuffixIndex:] - dp.version = version[0:peerSuffixIndex] - } else { - // pre v6 uses _ to separate version from peer dependencies - // if a dependency is patched and has peer dependencies its version will - // be encoded as version_patchHash_peerDepsHash - peerSuffixIndex = strings.Index(version, "_") - if peerSuffixIndex != -1 { - dp.peerSuffix = version[peerSuffixIndex+1:] - dp.version = version[0:peerSuffixIndex] - } - } - if peerSuffixIndex == -1 { - dp.version = version - } - } - - return dp -} - -var _patchHashKey = "patch_hash=" - -func (d depPath) patchHash() string { - if strings.HasPrefix(d.peerSuffix, "(") && strings.HasSuffix(d.peerSuffix, ")") { - for _, part := range strings.Split(d.peerSuffix, "(") { - if strings.HasPrefix(part, _patchHashKey) { - // drop the enclosing ')' - return part[len(_patchHashKey) : len(part)-1] - } - } - // no patch entry found - return "" - } - - sepIndex := strings.Index(d.peerSuffix, "_") - if sepIndex != -1 { - return d.peerSuffix[:sepIndex] - } - // if a dependency just has a single suffix we can't tell if it's a patch or peer hash - // return it in case it's a patch hash - return d.peerSuffix -} - -// Used to convert v6's dep path of /name@version to v5's /name/version -// See https://github.com/pnpm/pnpm/blob/185ab01adfc927ea23d2db08a14723bf51d0025f/lockfile/lockfile-file/src/experiments/inlineSpecifiersLockfileConverters.ts#L162 -func convertNewToOldDepPath(newPath string) string { - if len(newPath) > 2 && !strings.Contains(newPath[2:], "@") { - return newPath - } - searchStartIndex := strings.Index(newPath, "/@") + 2 - index := strings.Index(newPath[searchStartIndex:], "@") + searchStartIndex - if strings.Contains(newPath, "(") && index > strings.Index(newPath, "(") { - return newPath - } - return fmt.Sprintf("%s/%s", newPath[0:index], newPath[index+1:]) + return ffi.GlobalChange("berry", o.contents, p.contents) } diff --git a/cli/internal/lockfile/pnpm_lockfile_test.go b/cli/internal/lockfile/pnpm_lockfile_test.go index b4c8475711b3a..e39720508f8a2 100644 --- a/cli/internal/lockfile/pnpm_lockfile_test.go +++ b/cli/internal/lockfile/pnpm_lockfile_test.go @@ -1,15 +1,12 @@ package lockfile import ( - "bytes" "os" "sort" "testing" - "github.com/google/go-cmp/cmp/cmpopts" "github.com/pkg/errors" "github.com/vercel/turbo/cli/internal/turbopath" - "github.com/vercel/turbo/cli/internal/yaml" "gotest.tools/v3/assert" ) @@ -26,357 +23,6 @@ func getFixture(t *testing.T, name string) ([]byte, error) { return os.ReadFile(lockfilePath.ToString()) } -func Test_Roundtrip(t *testing.T) { - lockfiles := []string{"pnpm6-workspace.yaml", "pnpm7-workspace.yaml", "pnpm8.yaml"} - - for _, lockfilePath := range lockfiles { - lockfileContent, err := getFixture(t, lockfilePath) - if err != nil { - t.Errorf("failure getting fixture: %s", err) - } - lockfile, err := DecodePnpmLockfile(lockfileContent) - if err != nil { - t.Errorf("decoding failed %s", err) - } - var b bytes.Buffer - if err := lockfile.Encode(&b); err != nil { - t.Errorf("encoding failed %s", err) - } - newLockfile, err := DecodePnpmLockfile(b.Bytes()) - if err != nil { - t.Errorf("decoding failed %s", err) - } - - assert.DeepEqual( - t, - lockfile, - newLockfile, - // Skip over fields that don't get serialized - cmpopts.IgnoreUnexported(PnpmLockfile{}), - cmpopts.IgnoreTypes(yaml.Node{}), - ) - } -} - -func Test_SpecifierResolution(t *testing.T) { - contents, err := getFixture(t, "pnpm7-workspace.yaml") - if err != nil { - t.Error(err) - } - lockfile, err := DecodePnpmLockfile(contents) - if err != nil { - t.Errorf("failure decoding lockfile: %v", err) - } - - type Case struct { - workspacePath turbopath.AnchoredUnixPath - pkg string - specifier string - version string - found bool - err string - } - - cases := []Case{ - {workspacePath: "apps/docs", pkg: "next", specifier: "12.2.5", version: "12.2.5_ir3quccc6i62x6qn6jjhyjjiey", found: true}, - {workspacePath: "apps/web", pkg: "next", specifier: "12.2.5", version: "12.2.5_ir3quccc6i62x6qn6jjhyjjiey", found: true}, - {workspacePath: "apps/web", pkg: "typescript", specifier: "^4.5.3", version: "4.8.3", found: true}, - {workspacePath: "apps/web", pkg: "lodash", specifier: "bad-tag", version: "", found: false}, - {workspacePath: "apps/web", pkg: "lodash", specifier: "^4.17.21", version: "4.17.21_ehchni3mpmovsvjxesffg2i5a4", found: true}, - {workspacePath: "apps/docs", pkg: "dashboard-icons", specifier: "github:peerigon/dashboard-icons", version: "github.com/peerigon/dashboard-icons/ce27ef933144e09cef3911025f3649040a8571b6", found: true}, - {workspacePath: "", pkg: "turbo", specifier: "latest", version: "1.4.6", found: true}, - {workspacePath: "apps/bad_workspace", pkg: "turbo", specifier: "latest", version: "1.4.6", err: "no workspace 'apps/bad_workspace' found in lockfile"}, - } - - for _, testCase := range cases { - actualVersion, actualFound, err := lockfile.resolveSpecifier(testCase.workspacePath, testCase.pkg, testCase.specifier) - if testCase.err != "" { - assert.Error(t, err, testCase.err) - } else { - assert.Equal(t, actualFound, testCase.found, "%s@%s", testCase.pkg, testCase.version) - assert.Equal(t, actualVersion, testCase.version, "%s@%s", testCase.pkg, testCase.version) - } - } -} - -func Test_SpecifierResolutionV6(t *testing.T) { - contents, err := getFixture(t, "pnpm8.yaml") - if err != nil { - t.Error(err) - } - lockfile, err := DecodePnpmLockfile(contents) - if err != nil { - t.Errorf("failure decoding lockfile: %v", err) - } - - type Case struct { - workspacePath turbopath.AnchoredUnixPath - pkg string - specifier string - version string - found bool - err string - } - - cases := []Case{ - {workspacePath: "packages/a", pkg: "c", specifier: "workspace:*", version: "link:../c", found: true}, - {workspacePath: "packages/a", pkg: "is-odd", specifier: "^3.0.1", version: "3.0.1", found: true}, - {workspacePath: "packages/b", pkg: "is-odd", specifier: "^3.0.1", version: "3.0.1", err: "Unable to find resolved version for is-odd@^3.0.1 in packages/b"}, - {workspacePath: "apps/bad_workspace", pkg: "turbo", specifier: "latest", version: "1.4.6", err: "no workspace 'apps/bad_workspace' found in lockfile"}, - } - - for _, testCase := range cases { - actualVersion, actualFound, err := lockfile.resolveSpecifier(testCase.workspacePath, testCase.pkg, testCase.specifier) - if testCase.err != "" { - assert.Error(t, err, testCase.err) - } else { - assert.Equal(t, actualFound, testCase.found, "%s@%s", testCase.pkg, testCase.version) - assert.Equal(t, actualVersion, testCase.version, "%s@%s", testCase.pkg, testCase.version) - } - } -} - -func Test_SubgraphInjectedPackages(t *testing.T) { - contents, err := getFixture(t, "pnpm7-workspace.yaml") - if err != nil { - t.Error(err) - } - lockfile, err := DecodePnpmLockfile(contents) - assert.NilError(t, err, "decode lockfile") - - packageWithInjectedPackage := turbopath.AnchoredUnixPath("apps/docs").ToSystemPath() - - prunedLockfile, err := lockfile.Subgraph([]turbopath.AnchoredSystemPath{packageWithInjectedPackage}, []string{}) - assert.NilError(t, err, "prune lockfile") - - pnpmLockfile, ok := prunedLockfile.(*PnpmLockfile) - assert.Assert(t, ok, "got different lockfile impl") - - _, hasInjectedPackage := pnpmLockfile.Packages["file:packages/ui"] - - assert.Assert(t, hasInjectedPackage, "pruned lockfile is missing injected package") - -} - -func Test_GitPackages(t *testing.T) { - contents, err := getFixture(t, "pnpm7-workspace.yaml") - if err != nil { - t.Error(err) - } - lockfile, err := DecodePnpmLockfile(contents) - assert.NilError(t, err, "decode lockfile") - - pkg, err := lockfile.ResolvePackage(turbopath.AnchoredUnixPath("apps/docs"), "dashboard-icons", "github:peerigon/dashboard-icons") - assert.NilError(t, err, "failure to find package") - assert.Assert(t, pkg.Found) - assert.DeepEqual(t, pkg.Key, "github.com/peerigon/dashboard-icons/ce27ef933144e09cef3911025f3649040a8571b6") - assert.DeepEqual(t, pkg.Version, "1.0.0") - // make sure subgraph produces git dep -} - -func Test_DecodePnpmUnquotedURL(t *testing.T) { - resolutionWithQuestionMark := `{integrity: sha512-deadbeef, tarball: path/to/tarball?foo=bar}` - var resolution map[string]interface{} - err := yaml.Unmarshal([]byte(resolutionWithQuestionMark), &resolution) - assert.NilError(t, err, "valid package entry should be able to be decoded") - assert.Equal(t, resolution["tarball"], "path/to/tarball?foo=bar") -} - -func Test_PnpmLockfilePatches(t *testing.T) { - contents, err := getFixture(t, "pnpm-patch.yaml") - assert.NilError(t, err) - - lockfile, err := DecodePnpmLockfile(contents) - assert.NilError(t, err) - - patches := lockfile.Patches() - assert.Equal(t, len(patches), 3) - assert.Equal(t, patches[0], turbopath.AnchoredUnixPath("patches/@babel__core@7.20.12.patch")) - assert.Equal(t, patches[1], turbopath.AnchoredUnixPath("patches/is-odd@3.0.1.patch")) -} - -func Test_PnpmPrunePatches(t *testing.T) { - contents, err := getFixture(t, "pnpm-patch.yaml") - assert.NilError(t, err) - - lockfile, err := DecodePnpmLockfile(contents) - assert.NilError(t, err) - - prunedLockfile, err := lockfile.Subgraph( - []turbopath.AnchoredSystemPath{turbopath.AnchoredSystemPath("packages/dependency")}, - []string{"/is-odd/3.0.1_nrrwwz7lemethtlvvm75r5bmhq", "/is-number/6.0.0", "/@babel/core/7.20.12_3hyn7hbvzkemudbydlwjmrb65y", "/moleculer/0.14.28_5pk7ojv7qbqha75ozglk4y4f74_kumip57h7zlinbhp4gz3jrbqry"}, - ) - assert.NilError(t, err) - - assert.Equal(t, len(prunedLockfile.Patches()), 3) -} - -func Test_PnpmPrunePatchesV6(t *testing.T) { - contents, err := getFixture(t, "pnpm-patch-v6.yaml") - assert.NilError(t, err) - - lockfile, err := DecodePnpmLockfile(contents) - assert.NilError(t, err) - - prunedLockfile, err := lockfile.Subgraph( - []turbopath.AnchoredSystemPath{turbopath.AnchoredSystemPath("packages/a")}, - []string{"/lodash@4.17.21(patch_hash=lgum37zgng4nfkynzh3cs7wdeq)"}, - ) - assert.NilError(t, err) - - assert.Equal(t, len(prunedLockfile.Patches()), 1) - - prunedLockfile, err = lockfile.Subgraph( - []turbopath.AnchoredSystemPath{turbopath.AnchoredSystemPath("packages/b")}, - []string{"/@babel/helper-string-parser@7.19.4(patch_hash=wjhgmpzh47qmycrzgpeyoyh3ce)(@babel/core@7.21.0)"}, - ) - assert.NilError(t, err) - - assert.Equal(t, len(prunedLockfile.Patches()), 1) -} - -func Test_PnpmAbsoluteDependency(t *testing.T) { - type testCase struct { - fixture string - key string - } - testcases := []testCase{ - {"pnpm-absolute.yaml", "/@scope/child/1.0.0"}, - {"pnpm-absolute-v6.yaml", "/@scope/child@1.0.0"}, - } - for _, tc := range testcases { - contents, err := getFixture(t, tc.fixture) - assert.NilError(t, err, tc.fixture) - - lockfile, err := DecodePnpmLockfile(contents) - assert.NilError(t, err, tc.fixture) - - pkg, err := lockfile.ResolvePackage(turbopath.AnchoredUnixPath("packages/a"), "child", tc.key) - assert.NilError(t, err, "resolve") - assert.Assert(t, pkg.Found, tc.fixture) - assert.DeepEqual(t, pkg.Key, tc.key) - assert.DeepEqual(t, pkg.Version, "1.0.0") - } -} - -func Test_LockfilePeer(t *testing.T) { - contents, err := getFixture(t, "pnpm-peer-v6.yaml") - if err != nil { - t.Error(err) - } - assert.NilError(t, err, "read fixture") - lockfile, err := DecodePnpmLockfile(contents) - assert.NilError(t, err, "parse lockfile") - - pkg, err := lockfile.ResolvePackage(turbopath.AnchoredUnixPath("apps/web"), "next", "13.0.4") - assert.NilError(t, err, "read lockfile") - assert.Assert(t, pkg.Found) - assert.DeepEqual(t, pkg.Version, "13.0.4(react-dom@18.2.0)(react@18.2.0)") - assert.DeepEqual(t, pkg.Key, "/next@13.0.4(react-dom@18.2.0)(react@18.2.0)") -} - -func Test_LockfileTopLevelOverride(t *testing.T) { - contents, err := getFixture(t, "pnpm-top-level-dupe.yaml") - if err != nil { - t.Error(err) - } - lockfile, err := DecodePnpmLockfile(contents) - assert.NilError(t, err, "decode lockfile") - - pkg, err := lockfile.ResolvePackage(turbopath.AnchoredUnixPath("packages/a"), "ci-info", "3.7.1") - assert.NilError(t, err, "resolve package") - - assert.Assert(t, pkg.Found) - assert.DeepEqual(t, pkg.Key, "/ci-info/3.7.1") - assert.DeepEqual(t, pkg.Version, "3.7.1") -} - -func Test_PnpmOverride(t *testing.T) { - contents, err := getFixture(t, "pnpm_override.yaml") - if err != nil { - t.Error(err) - } - lockfile, err := DecodePnpmLockfile(contents) - assert.NilError(t, err, "decode lockfile") - - pkg, err := lockfile.ResolvePackage( - turbopath.AnchoredUnixPath("config/hardhat"), - "@nomiclabs/hardhat-ethers", - "npm:hardhat-deploy-ethers@0.3.0-beta.13", - ) - assert.NilError(t, err, "failure to find package") - assert.Assert(t, pkg.Found) - assert.DeepEqual(t, pkg.Key, "/hardhat-deploy-ethers/0.3.0-beta.13_yab2ug5tvye2kp6e24l5x3z7uy") - assert.DeepEqual(t, pkg.Version, "0.3.0-beta.13_yab2ug5tvye2kp6e24l5x3z7uy") -} - -func Test_DepPathParsing(t *testing.T) { - type testCase struct { - input string - dp depPath - } - testCases := []testCase{ - { - "/foo/1.0.0", - depPath{ - name: "foo", - version: "1.0.0", - }, - }, - { - "/@foo/bar/1.0.0", - depPath{ - name: "@foo/bar", - version: "1.0.0", - }, - }, - { - "example.org/foo/1.0.0", - depPath{ - host: "example.org", - name: "foo", - version: "1.0.0", - }, - }, - { - "/foo/1.0.0_bar@1.0.0", - depPath{ - name: "foo", - version: "1.0.0", - peerSuffix: "bar@1.0.0", - }, - }, - { - "/foo/1.0.0(bar@1.0.0)", - depPath{ - name: "foo", - version: "1.0.0", - peerSuffix: "(bar@1.0.0)", - }, - }, - { - "/foo/1.0.0_patchHash_peerHash", - depPath{ - name: "foo", - version: "1.0.0", - peerSuffix: "patchHash_peerHash", - }, - }, - { - "/@babel/helper-string-parser/7.19.4(patch_hash=wjhgmpzh47qmycrzgpeyoyh3ce)(@babel/core@7.21.0)", - depPath{ - name: "@babel/helper-string-parser", - version: "7.19.4", - peerSuffix: "(patch_hash=wjhgmpzh47qmycrzgpeyoyh3ce)(@babel/core@7.21.0)", - }, - }, - } - - for _, tc := range testCases { - assert.Equal(t, parseDepPath(tc.input), tc.dp, tc.input) - } -} - func Test_PnpmAliasesOverlap(t *testing.T) { contents, err := getFixture(t, "pnpm-absolute.yaml") assert.NilError(t, err) @@ -384,11 +30,13 @@ func Test_PnpmAliasesOverlap(t *testing.T) { lockfile, err := DecodePnpmLockfile(contents) assert.NilError(t, err) - closure, err := transitiveClosure("packages/a", map[string]string{"@scope/parent": "^1.0.0", "another": "^1.0.0", "special": "npm:Special@1.2.3"}, lockfile) + closures, err := AllTransitiveClosures(map[turbopath.AnchoredUnixPath]map[string]string{"packages/a": {"@scope/parent": "^1.0.0", "another": "^1.0.0", "special": "npm:Special@1.2.3"}}, lockfile) assert.NilError(t, err) - deps := []Package{} + closure, ok := closures[turbopath.AnchoredUnixPath("packages/a")] + assert.Assert(t, ok) + deps := []Package{} for _, v := range closure.ToSlice() { dep := v.(Package) deps = append(deps, dep) diff --git a/crates/turborepo-ffi/messages.proto b/crates/turborepo-ffi/messages.proto index ce7b189a1f3a2..fb53d2d2faaef 100644 --- a/crates/turborepo-ffi/messages.proto +++ b/crates/turborepo-ffi/messages.proto @@ -57,6 +57,7 @@ message PreviousContentResp { enum PackageManager { NPM = 0; BERRY = 1; + PNPM = 2; } message PackageDependency { diff --git a/crates/turborepo-ffi/src/lockfile.rs b/crates/turborepo-ffi/src/lockfile.rs index 7864610749e08..5181fa0504e52 100644 --- a/crates/turborepo-ffi/src/lockfile.rs +++ b/crates/turborepo-ffi/src/lockfile.rs @@ -4,7 +4,7 @@ use std::{ }; use thiserror::Error; -use turborepo_lockfiles::{self, BerryLockfile, LockfileData, NpmLockfile, Package}; +use turborepo_lockfiles::{self, BerryLockfile, LockfileData, NpmLockfile, Package, PnpmLockfile}; use super::{proto, Buffer}; @@ -50,6 +50,7 @@ fn transitive_closure_inner(buf: Buffer) -> Result npm_transitive_closure_inner(request), proto::PackageManager::Berry => berry_transitive_closure_inner(request), + proto::PackageManager::Pnpm => pnpm_transitive_closure_inner(request), } } @@ -89,6 +90,22 @@ fn berry_transitive_closure_inner( Ok(dependencies.into()) } +fn pnpm_transitive_closure_inner( + request: proto::TransitiveDepsRequest, +) -> Result { + let proto::TransitiveDepsRequest { + contents, + workspaces, + .. + } = request; + let lockfile = PnpmLockfile::from_bytes(contents.as_slice())?; + let dependencies = turborepo_lockfiles::all_transitive_closures( + &lockfile, + workspaces.into_iter().map(|(k, v)| (k, v.into())).collect(), + )?; + Ok(dependencies.into()) +} + #[no_mangle] pub extern "C" fn subgraph(buf: Buffer) -> Buffer { use proto::subgraph_response::Response; @@ -121,6 +138,9 @@ fn subgraph_inner(buf: Buffer) -> Result, Error> { &packages, resolutions.map(|res| res.resolutions), )?, + proto::PackageManager::Pnpm => { + turborepo_lockfiles::pnpm_subgraph(&contents, &workspaces, &packages)? + } }; Ok(contents) } @@ -177,6 +197,10 @@ fn global_change_inner(buf: Buffer) -> Result { &request.prev_contents, &request.curr_contents, )?), + proto::PackageManager::Pnpm => Ok(turborepo_lockfiles::pnpm_global_change( + &request.prev_contents, + &request.curr_contents, + )?), } } @@ -219,6 +243,7 @@ impl fmt::Display for proto::PackageManager { f.write_str(match self { proto::PackageManager::Npm => "npm", proto::PackageManager::Berry => "berry", + proto::PackageManager::Pnpm => "pnpm", }) } } From 619c3f19ba82d23efc86ade1497cb5550a166f97 Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Thu, 11 May 2023 10:47:34 -0700 Subject: [PATCH 07/11] fix up exact specifier resolution --- crates/turborepo-lockfiles/src/lib.rs | 8 +++ crates/turborepo-lockfiles/src/pnpm/data.rs | 55 +++++++++++++++++++-- crates/turborepo-lockfiles/src/pnpm/mod.rs | 6 +++ 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/crates/turborepo-lockfiles/src/lib.rs b/crates/turborepo-lockfiles/src/lib.rs index 7fbdb2a24199f..c83d9c9565547 100644 --- a/crates/turborepo-lockfiles/src/lib.rs +++ b/crates/turborepo-lockfiles/src/lib.rs @@ -94,3 +94,11 @@ fn transitive_closure_helper( Ok(()) } + +impl Package { + pub fn new(key: impl Into, version: impl Into) -> Self { + let key = key.into(); + let version = version.into(); + Self { key, version } + } +} diff --git a/crates/turborepo-lockfiles/src/pnpm/data.rs b/crates/turborepo-lockfiles/src/pnpm/data.rs index 6724c1301cb00..0ebab5633550f 100644 --- a/crates/turborepo-lockfiles/src/pnpm/data.rs +++ b/crates/turborepo-lockfiles/src/pnpm/data.rs @@ -170,8 +170,14 @@ impl PnpmLockfile { let importer = self.get_workspace(workspace_path)?; let Some((resolved_specifier, resolved_version)) = importer.dependencies.find_resolution(name) else { - self.get_packages(&self.format_key(name, specifier)); - return Ok(None) + return match self.get_packages(&self.format_key(name, specifier)) { + Some(_) => Ok(Some(specifier)), + None => Err(Error::MissingResolvedVersion{ + name: name.into(), + specifier: specifier.into(), + workspace: workspace_path.into(), + }.into()), + } }; let override_specifier = self.apply_overrides(name, specifier); @@ -388,6 +394,8 @@ pub fn pnpm_global_change( #[cfg(test)] mod tests { + use std::collections::HashSet; + use pretty_assertions::assert_eq; use test_case::test_case; @@ -405,7 +413,7 @@ mod tests { const PNPM_PATCH_V6: &[u8] = include_bytes!("../../fixtures/pnpm-patch-v6.yaml").as_slice(); use super::*; - use crate::Lockfile; + use crate::{Lockfile, Package}; #[test] fn test_roundtrip() { @@ -517,7 +525,7 @@ mod tests { "packages/b", "is-odd", "^3.0.1", - Ok(None) + Err("Unable to find resolved version for is-odd@^3.0.1 in packages/b") ; "v6 missing" )] #[test_case( @@ -691,4 +699,43 @@ mod tests { vec!["patches/@babel__helper-string-parser@7.19.4.patch"] ) } + + #[test] + fn test_pnpm_alias_overlap() { + let lockfile = PnpmLockfile::from_bytes(PNPM_ABSOLUTE).unwrap(); + let closures = crate::all_transitive_closures( + &lockfile, + vec![( + "packages/a".to_string(), + vec![ + ("@scope/parent".to_string(), "^1.0.0".to_string()), + ("another".to_string(), "^1.0.0".to_string()), + ("special".to_string(), "npm:Special@1.2.3".to_string()), + ] + .into_iter() + .collect(), + )] + .into_iter() + .collect(), + ) + .unwrap(); + + let mut closure = closures + .get("packages/a") + .unwrap() + .iter() + .cloned() + .collect::>(); + closure.sort(); + assert_eq!( + closure, + vec![ + Package::new("/@scope/child/1.0.0", "1.0.0"), + Package::new("/@scope/parent/1.0.0", "1.0.0"), + Package::new("/Special/1.2.3", "1.2.3"), + Package::new("/another/1.0.0", "1.0.0"), + Package::new("/foo/1.0.0", "1.0.0"), + ], + ); + } } diff --git a/crates/turborepo-lockfiles/src/pnpm/mod.rs b/crates/turborepo-lockfiles/src/pnpm/mod.rs index 5cd15b1287230..27b85e4caa63e 100644 --- a/crates/turborepo-lockfiles/src/pnpm/mod.rs +++ b/crates/turborepo-lockfiles/src/pnpm/mod.rs @@ -11,6 +11,12 @@ pub enum Error { DependencyPath(#[from] nom::error::Error), #[error("Unable to find '{0}' other than reference in dependenciesMeta")] MissingInjectedPackage(String), + #[error("Unable to find resolved version for {name}@{specifier} in {workspace}")] + MissingResolvedVersion { + name: String, + specifier: String, + workspace: String, + }, } #[derive(Debug, PartialEq, Eq, Clone)] From 7f3b454198db4fff4fbd7235ad5b1eb9f30243a6 Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Thu, 11 May 2023 10:51:51 -0700 Subject: [PATCH 08/11] clean up lints --- crates/turborepo-lockfiles/src/pnpm/data.rs | 2 -- crates/turborepo-lockfiles/src/pnpm/dep_path.rs | 9 +++------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/crates/turborepo-lockfiles/src/pnpm/data.rs b/crates/turborepo-lockfiles/src/pnpm/data.rs index 0ebab5633550f..ebe68d846a73b 100644 --- a/crates/turborepo-lockfiles/src/pnpm/data.rs +++ b/crates/turborepo-lockfiles/src/pnpm/data.rs @@ -394,8 +394,6 @@ pub fn pnpm_global_change( #[cfg(test)] mod tests { - use std::collections::HashSet; - use pretty_assertions::assert_eq; use test_case::test_case; diff --git a/crates/turborepo-lockfiles/src/pnpm/dep_path.rs b/crates/turborepo-lockfiles/src/pnpm/dep_path.rs index 6b4f0eb8e1a8c..625dbb36b2d33 100644 --- a/crates/turborepo-lockfiles/src/pnpm/dep_path.rs +++ b/crates/turborepo-lockfiles/src/pnpm/dep_path.rs @@ -71,12 +71,9 @@ fn parse_dep_path(i: &str) -> IResult<&str, DepPath> { let (i, peer_suffix) = opt(alt((parse_new_peer_suffix, parse_old_peer_suffix)))(i)?; Ok(( i, - DepPath { - name, - version, - host, - peer_suffix, - }, + DepPath::new(name, version) + .with_host(host) + .with_peer_suffix(peer_suffix), )) } From 5f317794bbf5add9d18cfa5d800036f4f40f1d5c Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Thu, 11 May 2023 11:14:57 -0700 Subject: [PATCH 09/11] add comments --- crates/turborepo-lockfiles/src/pnpm/data.rs | 11 +++++++++++ crates/turborepo-lockfiles/src/pnpm/dep_path.rs | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/crates/turborepo-lockfiles/src/pnpm/data.rs b/crates/turborepo-lockfiles/src/pnpm/data.rs index ebe68d846a73b..781e6a7930f8c 100644 --- a/crates/turborepo-lockfiles/src/pnpm/data.rs +++ b/crates/turborepo-lockfiles/src/pnpm/data.rs @@ -130,6 +130,7 @@ impl PnpmLockfile { } fn is_v6(&self) -> bool { + // With lockfile v6+ the lockfile version is stored as a string matches!(self.lockfile_version.format, super::VersionFormat::String) } @@ -140,8 +141,11 @@ impl PnpmLockfile { } } + // Extracts the version from a dependency path fn extract_version<'a>(&self, key: &'a str) -> Result, Error> { let dp = DepPath::try_from(key)?; + // If there's a suffix, the suffix gets included as part of the version + // so we can track patch file changes if let Some(suffix) = dp.peer_suffix { let sep = match self.is_v6() { true => "", @@ -153,6 +157,7 @@ impl PnpmLockfile { } } + // Returns the version override if there's an override for a package fn apply_overrides<'a>(&'a self, name: &str, specifier: &'a str) -> &'a str { self.overrides .as_ref() @@ -161,6 +166,7 @@ impl PnpmLockfile { .unwrap_or(specifier) } + // Given a package and version specifier resolves it to an exact version fn resolve_specifier<'a>( &'a self, workspace_path: &str, @@ -170,6 +176,7 @@ impl PnpmLockfile { let importer = self.get_workspace(workspace_path)?; let Some((resolved_specifier, resolved_version)) = importer.dependencies.find_resolution(name) else { + // Check if the specifier is already an exact version return match self.get_packages(&self.format_key(name, specifier)) { Some(_) => Ok(Some(specifier)), None => Err(Error::MissingResolvedVersion{ @@ -213,6 +220,8 @@ impl PnpmLockfile { pruned_packages.insert(package.clone(), entry.clone()); } for importer in importers.values() { + // Find all injected packages in each workspace and include it in + // the pruned lockfile for dependency in importer .dependencies_meta @@ -343,6 +352,8 @@ impl crate::Lockfile for PnpmLockfile { } impl DependencyInfo { + // Given a dependency will find the specifier and resolved version that + // appear in the importer object pub fn find_resolution(&self, dependency: &str) -> Option<(&str, &str)> { match self { DependencyInfo::PreV6 { diff --git a/crates/turborepo-lockfiles/src/pnpm/dep_path.rs b/crates/turborepo-lockfiles/src/pnpm/dep_path.rs index 625dbb36b2d33..8e96d78ed422b 100644 --- a/crates/turborepo-lockfiles/src/pnpm/dep_path.rs +++ b/crates/turborepo-lockfiles/src/pnpm/dep_path.rs @@ -62,6 +62,10 @@ impl<'a> TryFrom<&'a str> for DepPath<'a> { } // See https://github.com/pnpm/pnpm/blob/185ab01adfc927ea23d2db08a14723bf51d0025f/packages/dependency-path/src/index.ts#L96 +// This diverges from the pnpm implementation that only parses <6 and in +// order to parse 6+ it partially converts to the old format. +// The conversion only replaces the '@' separator with '/', we avoid this +// conversion by allowing for a '@' or a '/' to be used as a separator. fn parse_dep_path(i: &str) -> IResult<&str, DepPath> { let (i, host) = parse_host(i)?; let (i, _) = nom::character::complete::char('/')(i)?; From e50bedbef584682938162b1d05edc4e710211bdb Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Thu, 11 May 2023 13:49:55 -0700 Subject: [PATCH 10/11] various fixes --- cli/internal/lockfile/pnpm_lockfile.go | 6 ++-- crates/turborepo-ffi/src/lockfile.rs | 4 +++ crates/turborepo-lockfiles/src/pnpm/data.rs | 32 ++++++++++++++++++++- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/cli/internal/lockfile/pnpm_lockfile.go b/cli/internal/lockfile/pnpm_lockfile.go index 474e888187cc4..a430e872cb06e 100644 --- a/cli/internal/lockfile/pnpm_lockfile.go +++ b/cli/internal/lockfile/pnpm_lockfile.go @@ -55,7 +55,7 @@ func (p *PnpmLockfile) Encode(w io.Writer) error { // Patches return a list of patches used in the lockfile func (p *PnpmLockfile) Patches() []turbopath.AnchoredUnixPath { - rawPatches := ffi.Patches(p.contents, "berry") + rawPatches := ffi.Patches(p.contents, "pnpm") if len(rawPatches) == 0 { return nil } @@ -69,10 +69,10 @@ func (p *PnpmLockfile) Patches() []turbopath.AnchoredUnixPath { // GlobalChange checks if there are any differences between lockfiles that would completely invalidate // the cache. func (p *PnpmLockfile) GlobalChange(other Lockfile) bool { - o, ok := other.(*BerryLockfile) + o, ok := other.(*PnpmLockfile) if !ok { return true } - return ffi.GlobalChange("berry", o.contents, p.contents) + return ffi.GlobalChange("pnpm", o.contents, p.contents) } diff --git a/crates/turborepo-ffi/src/lockfile.rs b/crates/turborepo-ffi/src/lockfile.rs index 5181fa0504e52..342d7dfdd052d 100644 --- a/crates/turborepo-ffi/src/lockfile.rs +++ b/crates/turborepo-ffi/src/lockfile.rs @@ -173,6 +173,10 @@ fn patches_internal(buf: Buffer) -> Result { }) .collect::>()) } + proto::PackageManager::Pnpm => { + let lockfile = PnpmLockfile::from_bytes(&request.contents)?; + Ok(lockfile.patches()) + } pm => Err(Error::UnsupportedPackageManager(pm)), }?; Ok(proto::Patches { patches }) diff --git a/crates/turborepo-lockfiles/src/pnpm/data.rs b/crates/turborepo-lockfiles/src/pnpm/data.rs index 781e6a7930f8c..28fcdb3972aed 100644 --- a/crates/turborepo-lockfiles/src/pnpm/data.rs +++ b/crates/turborepo-lockfiles/src/pnpm/data.rs @@ -10,13 +10,20 @@ type Map = std::collections::BTreeMap; #[serde(rename_all = "camelCase")] pub struct PnpmLockfile { lockfile_version: LockfileVersion, + #[serde(skip_serializing_if = "Option::is_none")] never_built_dependencies: Option>, + #[serde(skip_serializing_if = "Option::is_none")] only_built_dependencies: Option>, + #[serde(skip_serializing_if = "Option::is_none")] overrides: Option>, + #[serde(skip_serializing_if = "Option::is_none")] package_extensions_checksum: Option, + #[serde(skip_serializing_if = "Option::is_none")] patched_dependencies: Option>, importers: Map, + #[serde(skip_serializing_if = "Option::is_none")] packages: Option>, + #[serde(skip_serializing_if = "Option::is_none")] time: Option>, } @@ -31,7 +38,9 @@ pub struct PatchFile { pub struct ProjectSnapshot { #[serde(flatten)] dependencies: DependencyInfo, + #[serde(skip_serializing_if = "Option::is_none")] dependencies_meta: Option>, + #[serde(skip_serializing_if = "Option::is_none")] publish_directory: Option, } @@ -40,15 +49,22 @@ pub struct ProjectSnapshot { pub enum DependencyInfo { #[serde(rename_all = "camelCase")] PreV6 { + #[serde(skip_serializing_if = "Option::is_none")] specifiers: Option>, + #[serde(skip_serializing_if = "Option::is_none")] dependencies: Option>, + #[serde(skip_serializing_if = "Option::is_none")] optional_dependencies: Option>, + #[serde(skip_serializing_if = "Option::is_none")] dev_dependencies: Option>, }, #[serde(rename_all = "camelCase")] V6 { + #[serde(skip_serializing_if = "Option::is_none")] dependencies: Option>, + #[serde(skip_serializing_if = "Option::is_none")] optional_dependencies: Option>, + #[serde(skip_serializing_if = "Option::is_none")] dev_dependencies: Option>, }, } @@ -64,13 +80,19 @@ pub struct Dependency { pub struct PackageSnapshot { // can we make this flow?/is it necessary? resolution: PackageResolution, + #[serde(skip_serializing_if = "Option::is_none")] id: Option, + #[serde(skip_serializing_if = "Option::is_none")] name: Option, + #[serde(skip_serializing_if = "Option::is_none")] version: Option, + #[serde(skip_serializing_if = "Option::is_none")] dependencies: Option>, + #[serde(skip_serializing_if = "Option::is_none")] optional_dependencies: Option>, + #[serde(skip_serializing_if = "Option::is_none")] patched: Option, #[serde(flatten)] @@ -79,19 +101,27 @@ pub struct PackageSnapshot { #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct DependenciesMeta { + #[serde(skip_serializing_if = "Option::is_none")] injected: Option, + #[serde(skip_serializing_if = "Option::is_none")] node: Option, + #[serde(skip_serializing_if = "Option::is_none")] patch: Option, } #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct PackageResolution { - #[serde(rename = "type")] + #[serde(rename = "type", skip_serializing_if = "Option::is_none")] type_field: Option, + #[serde(skip_serializing_if = "Option::is_none")] integrity: Option, + #[serde(skip_serializing_if = "Option::is_none")] tarball: Option, + #[serde(skip_serializing_if = "Option::is_none")] dir: Option, + #[serde(skip_serializing_if = "Option::is_none")] repo: Option, + #[serde(skip_serializing_if = "Option::is_none")] commit: Option, } From e5e4a88d30bb995521cf5fc2a137c2cff9e0da4d Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Fri, 26 May 2023 15:08:29 -0700 Subject: [PATCH 11/11] PR feedback --- crates/turborepo-lockfiles/src/pnpm/dep_path.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/turborepo-lockfiles/src/pnpm/dep_path.rs b/crates/turborepo-lockfiles/src/pnpm/dep_path.rs index 8e96d78ed422b..558991baa717f 100644 --- a/crates/turborepo-lockfiles/src/pnpm/dep_path.rs +++ b/crates/turborepo-lockfiles/src/pnpm/dep_path.rs @@ -73,8 +73,9 @@ fn parse_dep_path(i: &str) -> IResult<&str, DepPath> { let (i, _) = nom::character::complete::one_of("/@")(i)?; let (i, version) = parse_version(i)?; let (i, peer_suffix) = opt(alt((parse_new_peer_suffix, parse_old_peer_suffix)))(i)?; + let (_, _) = nom::combinator::eof(i)?; Ok(( - i, + "", DepPath::new(name, version) .with_host(host) .with_peer_suffix(peer_suffix),