From 601aca16733fe6180a31bf1923041e09be55b1a1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 2 May 2021 23:24:26 +0000 Subject: [PATCH 1/2] Lock file maintenance (#5585) * Lock file maintenance * Fix types * Fix types Co-authored-by: Renovate Bot Co-authored-by: Tim Leslie --- .../keystone/src/scripts/tests/build.test.ts | 4 +- tests/api-tests/package.json | 2 +- yarn.lock | 748 +++++++++--------- 3 files changed, 383 insertions(+), 371 deletions(-) diff --git a/packages-next/keystone/src/scripts/tests/build.test.ts b/packages-next/keystone/src/scripts/tests/build.test.ts index 551025dec06..502241dad19 100644 --- a/packages-next/keystone/src/scripts/tests/build.test.ts +++ b/packages-next/keystone/src/scripts/tests/build.test.ts @@ -77,7 +77,7 @@ test('build works with typescript without the user defining a babel config', asy ✨ Generating Admin UI code ✨ Generating Keystone config code ✨ Building Admin UI - info - Using webpack 4. Reason: future.webpack5 option not enabled https://nextjs.org/docs/messages/webpack5 + info - Using webpack 4. Reason: custom webpack configuration in next.config.js https://nextjs.org/docs/messages/webpack5 info - Checking validity of types... info - Creating an optimized production build... info - Compiled successfully @@ -92,7 +92,7 @@ test('build works with typescript without the user defining a babel config', asy Page Size First Load JS ┌ ○ / size size ├ /_app size size - ├ ○ /404 size size + ├ ○ /404 size size ├ λ /api/__keystone_api_build size size ├ ○ /no-access size size ├ ○ /todos size size diff --git a/tests/api-tests/package.json b/tests/api-tests/package.json index 90f4ddac9ed..93233601918 100644 --- a/tests/api-tests/package.json +++ b/tests/api-tests/package.json @@ -28,7 +28,7 @@ "@keystone-next/test-utils-legacy": "^17.0.0", "@keystone-next/types": "^17.0.0", "@keystone-next/utils-legacy": "^9.0.0", - "apollo-cache-control": "^0.12.0", + "apollo-cache-control": "^0.13.0", "express": "^4.17.1" } } diff --git a/yarn.lock b/yarn.lock index 2a5dbdf0983..913e2e57e3d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3,9 +3,9 @@ "@apollo/client@^3.1.3", "@apollo/client@^3.2.5", "@apollo/client@^3.3.15": - version "3.3.15" - resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.3.15.tgz#bdd230894aac4beb8ade2b472a1d3c9ea6152812" - integrity sha512-/WQmNvLEZMA0mA3u+FkEPTXKzxZD/KhyO7WlbKcy3zKGrXKza83tAbNMzsitQE7DTcSc3DLEcIu1Z5Rc7PFq0Q== + version "3.3.16" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.3.16.tgz#e4a51b0f86583b18ab81723660e381ef616536c1" + integrity sha512-EPTiNpmiU6/vvxpl4lXWQDqS3YddweC1sh/ewCuVP9IK0+xlVGb5vR1yhM/7T3PIJqwz52dGpZyJskmbTfENfQ== dependencies: "@graphql-typed-document-node/core" "^3.0.0" "@types/zen-observable" "^0.8.0" @@ -21,10 +21,10 @@ tslib "^1.10.0" zen-observable "^0.8.14" -"@apollo/protobufjs@^1.0.3": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@apollo/protobufjs/-/protobufjs-1.2.0.tgz#9720f9ee435ad57b0a9a9d213766a4cf77264ed4" - integrity sha512-TBgsADig/K4Hx71uQO6KPLxgoE/ORhPGh/HgouHru+cum8RLDfAfEY5Dde+cNala+luGI2X4Rs42pLWRud7/WA== +"@apollo/protobufjs@1.2.2", "@apollo/protobufjs@^1.0.3": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@apollo/protobufjs/-/protobufjs-1.2.2.tgz#4bd92cd7701ccaef6d517cdb75af2755f049f87c" + integrity sha512-vF+zxhPiLtkwxONs6YanSt1EpwpGilThpneExUN5K3tCymuxNnVq2yojTvnpRjv2QfsEIt/n7ozPIIzBLwGIDQ== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" @@ -40,12 +40,12 @@ "@types/node" "^10.1.0" long "^4.0.0" -"@apollographql/apollo-tools@^0.4.3": - version "0.4.12" - resolved "https://registry.yarnpkg.com/@apollographql/apollo-tools/-/apollo-tools-0.4.12.tgz#30668fd34f9ecf1106ab510105bcb2a88001fc29" - integrity sha512-JdC7aBzMUO6SaGH5g6MvIG8TWd+7cU/G9cyjKS/woYVtqyICLamyG21R8SmjiBnd5c1UgPWOxjSIxYBL2ln8Mg== +"@apollographql/apollo-tools@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@apollographql/apollo-tools/-/apollo-tools-0.5.0.tgz#81aadcabb35eeab6ef7e0d3d6c592a6fe15e66d9" + integrity sha512-7IOZHVaKjBq44StXFJEITl4rxgZCsZFSWogAvIErKR9DYV20rt9bJ2mY5lCn+zghfGrweykjLb9g4TDxLg750w== dependencies: - apollo-env "^0.9.0" + apollo-env "^0.10.0" "@apollographql/graphql-playground-html@1.6.27": version "1.6.27" @@ -88,10 +88,10 @@ dependencies: "@babel/highlight" "^7.12.13" -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.13.15", "@babel/compat-data@^7.13.8": - version "7.13.15" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.13.15.tgz#7e8eea42d0b64fda2b375b22d06c605222e848f4" - integrity sha512-ltnibHKR1VnrU4ymHyQ/CXtNXI6yZC0oJThyW78Hft8XndANwi+9H+UIklBDraIjFEJzw8wmcM427oDd9KS5wA== +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.13.15", "@babel/compat-data@^7.13.8", "@babel/compat-data@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.14.0.tgz#a901128bce2ad02565df95e6ecbf195cf9465919" + integrity sha512-vu9V3uMM/1o5Hl5OekMUowo3FqXLJSw+s+66nt0fSWVWTtmosdzn45JHOB3cPtZoe6CTBDzvSw0RdOY85Q37+Q== "@babel/core@7.12.9": version "7.12.9" @@ -116,19 +116,19 @@ source-map "^0.5.0" "@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.13.16", "@babel/core@^7.7.5", "@babel/core@^7.7.7": - version "7.13.16" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.13.16.tgz#7756ab24396cc9675f1c3fcd5b79fcce192ea96a" - integrity sha512-sXHpixBiWWFti0AV2Zq7avpTasr6sIAu7Y396c608541qAU2ui4a193m0KSQmfPSKFZLnQ3cvlKDOm3XkuXm3Q== + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.14.0.tgz#47299ff3ec8d111b493f1a9d04bf88c04e728d88" + integrity sha512-8YqpRig5NmIHlMLw09zMlPTvUVMILjqCOtVgu+TVNWEBvy9b5I3RRyhqnrV4hjgEK7n8P9OqvkWJAFmEL6Wwfw== dependencies: "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.13.16" + "@babel/generator" "^7.14.0" "@babel/helper-compilation-targets" "^7.13.16" - "@babel/helper-module-transforms" "^7.13.14" - "@babel/helpers" "^7.13.16" - "@babel/parser" "^7.13.16" + "@babel/helper-module-transforms" "^7.14.0" + "@babel/helpers" "^7.14.0" + "@babel/parser" "^7.14.0" "@babel/template" "^7.12.13" - "@babel/traverse" "^7.13.15" - "@babel/types" "^7.13.16" + "@babel/traverse" "^7.14.0" + "@babel/types" "^7.14.0" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -136,12 +136,12 @@ semver "^6.3.0" source-map "^0.5.0" -"@babel/generator@^7.12.5", "@babel/generator@^7.13.16": - version "7.13.16" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.13.16.tgz#0befc287031a201d84cdfc173b46b320ae472d14" - integrity sha512-grBBR75UnKOcUWMp8WoDxNsWCFl//XCK6HWTrBQKTr5SV9f5g0pNOjdyzi/DTBv12S9GnYPInIXQBTky7OXEMg== +"@babel/generator@^7.12.5", "@babel/generator@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.0.tgz#0f35d663506c43e4f10898fbda0d752ec75494be" + integrity sha512-C6u00HbmsrNPug6A+CiNl8rEys7TsdcXwg12BHi2ca5rUfAs3+UwZsuDQSXnc+wCElCXMB8gMaJ3YXDdh8fAlg== dependencies: - "@babel/types" "^7.13.16" + "@babel/types" "^7.14.0" jsesc "^2.5.1" source-map "^0.5.0" @@ -160,7 +160,7 @@ "@babel/helper-explode-assignable-expression" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.13.13", "@babel/helper-compilation-targets@^7.13.16", "@babel/helper-compilation-targets@^7.13.8": +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.13.16", "@babel/helper-compilation-targets@^7.13.8": version "7.13.16" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.16.tgz#6e91dccf15e3f43e5556dffe32d860109887563c" integrity sha512-3gmkYIrpqsLlieFwjkGgLaSHmhnvlAYzZLlYVjlW+QwI+1zE17kGxuJGmIqDQdYp56XdmGeD+Bswx0UTyG18xA== @@ -170,15 +170,16 @@ browserslist "^4.14.5" semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.13.0": - version "7.13.11" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.13.11.tgz#30d30a005bca2c953f5653fc25091a492177f4f6" - integrity sha512-ays0I7XYq9xbjCSvT+EvysLgfc3tOkwCULHjrnscGT3A9qD4sk3wXnJ3of0MAWsWGjdinFvajHU2smYuqXKMrw== +"@babel/helper-create-class-features-plugin@^7.13.0", "@babel/helper-create-class-features-plugin@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.0.tgz#38367d3dab125b12f94273de418f4df23a11a15e" + integrity sha512-6pXDPguA5zC40Y8oI5mqr+jEUpjMJonKvknvA+vD8CYDz5uuXEwWBK8sRAsE/t3gfb1k15AQb9RhwpscC4nUJQ== dependencies: + "@babel/helper-annotate-as-pure" "^7.12.13" "@babel/helper-function-name" "^7.12.13" - "@babel/helper-member-expression-to-functions" "^7.13.0" + "@babel/helper-member-expression-to-functions" "^7.13.12" "@babel/helper-optimise-call-expression" "^7.12.13" - "@babel/helper-replace-supers" "^7.13.0" + "@babel/helper-replace-supers" "^7.13.12" "@babel/helper-split-export-declaration" "^7.12.13" "@babel/helper-create-regexp-features-plugin@^7.12.13": @@ -234,7 +235,7 @@ "@babel/traverse" "^7.13.15" "@babel/types" "^7.13.16" -"@babel/helper-member-expression-to-functions@^7.13.0", "@babel/helper-member-expression-to-functions@^7.13.12": +"@babel/helper-member-expression-to-functions@^7.13.12": version "7.13.12" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz#dfe368f26d426a07299d8d6513821768216e6d72" integrity sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw== @@ -248,19 +249,19 @@ dependencies: "@babel/types" "^7.13.12" -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.13.0", "@babel/helper-module-transforms@^7.13.14": - version "7.13.14" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.13.14.tgz#e600652ba48ccb1641775413cb32cfa4e8b495ef" - integrity sha512-QuU/OJ0iAOSIatyVZmfqB0lbkVP0kDRiKj34xy+QNsnVZi/PA6BoSoreeqnxxa9EHFAIL0R9XOaAR/G9WlIy5g== +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.13.0", "@babel/helper-module-transforms@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.14.0.tgz#8fcf78be220156f22633ee204ea81f73f826a8ad" + integrity sha512-L40t9bxIuGOfpIGA3HNkJhU9qYrf4y5A5LUSw7rGMSn+pcG8dfJ0g6Zval6YJGd2nEjI7oP00fRdnhLKndx6bw== dependencies: "@babel/helper-module-imports" "^7.13.12" "@babel/helper-replace-supers" "^7.13.12" "@babel/helper-simple-access" "^7.13.12" "@babel/helper-split-export-declaration" "^7.12.13" - "@babel/helper-validator-identifier" "^7.12.11" + "@babel/helper-validator-identifier" "^7.14.0" "@babel/template" "^7.12.13" - "@babel/traverse" "^7.13.13" - "@babel/types" "^7.13.14" + "@babel/traverse" "^7.14.0" + "@babel/types" "^7.14.0" "@babel/helper-optimise-call-expression@^7.12.13": version "7.12.13" @@ -298,7 +299,7 @@ "@babel/traverse" "^7.13.0" "@babel/types" "^7.13.12" -"@babel/helper-simple-access@^7.12.13", "@babel/helper-simple-access@^7.13.12": +"@babel/helper-simple-access@^7.13.12": version "7.13.12" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz#dd6c538afb61819d205a012c31792a39c7a5eaf6" integrity sha512-7FEjbrx5SL9cWvXioDbnlYTppcZGuCY6ow3/D5vMggb2Ywgu4dMrpTJX0JdQAIcRRUElOIxF3yEooa9gUb9ZbA== @@ -319,10 +320,10 @@ dependencies: "@babel/types" "^7.12.13" -"@babel/helper-validator-identifier@^7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" - integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== +"@babel/helper-validator-identifier@^7.12.11", "@babel/helper-validator-identifier@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz#d26cad8a47c65286b15df1547319a5d0bcf27288" + integrity sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A== "@babel/helper-validator-option@^7.12.17": version "7.12.17" @@ -339,28 +340,28 @@ "@babel/traverse" "^7.13.0" "@babel/types" "^7.13.0" -"@babel/helpers@^7.12.5", "@babel/helpers@^7.13.16": - version "7.13.17" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.13.17.tgz#b497c7a00e9719d5b613b8982bda6ed3ee94caf6" - integrity sha512-Eal4Gce4kGijo1/TGJdqp3WuhllaMLSrW6XcL0ulyUAQOuxHcCafZE8KHg9857gcTehsm/v7RcOx2+jp0Ryjsg== +"@babel/helpers@^7.12.5", "@babel/helpers@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.14.0.tgz#ea9b6be9478a13d6f961dbb5f36bf75e2f3b8f62" + integrity sha512-+ufuXprtQ1D1iZTO/K9+EBRn+qPWMJjZSw/S0KlFrxCw4tkrzv9grgpDHkY9MeQTjTY8i2sp7Jep8DfU6tN9Mg== dependencies: "@babel/template" "^7.12.13" - "@babel/traverse" "^7.13.17" - "@babel/types" "^7.13.17" + "@babel/traverse" "^7.14.0" + "@babel/types" "^7.14.0" "@babel/highlight@^7.10.4", "@babel/highlight@^7.12.13": - version "7.13.10" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.13.10.tgz#a8b2a66148f5b27d666b15d81774347a731d52d1" - integrity sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg== + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.0.tgz#3197e375711ef6bf834e67d0daec88e4f46113cf" + integrity sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg== dependencies: - "@babel/helper-validator-identifier" "^7.12.11" + "@babel/helper-validator-identifier" "^7.14.0" chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.12.7", "@babel/parser@^7.13.16": - version "7.13.16" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.16.tgz#0f18179b0448e6939b1f3f5c4c355a3a9bcdfd37" - integrity sha512-6bAg36mCwuqLO0hbR+z7PHuqWiCeP7Dzg73OpQwsAB1Eb8HnGEz5xYBzCfbu+YjoaJsJs+qheDxVAuqbt3ILEw== +"@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.12.7", "@babel/parser@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.0.tgz#2f0ebfed92bcddcc8395b91f1895191ce2760380" + integrity sha512-AHbfoxesfBALg33idaTBVUkLnfXtsgvJREf93p4p0Lwsz4ppfE7g1tpEXVm4vrxUcH4DVhAa9Z1m1zqf9WUC7Q== "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.13.12": version "7.13.12" @@ -388,6 +389,14 @@ "@babel/helper-create-class-features-plugin" "^7.13.0" "@babel/helper-plugin-utils" "^7.13.0" +"@babel/plugin-proposal-class-static-block@^7.13.11": + version "7.13.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.13.11.tgz#6fcbba4a962702c17e5371a0c7b39afde186d703" + integrity sha512-fJTdFI4bfnMjvxJyNuaf8i9mVcZ0UhetaGEUHaHV9KEnibLugJkZAtXikR8KcYj+NYmI4DZMS8yQAyg+hvfSqg== + dependencies: + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/plugin-syntax-class-static-block" "^7.12.13" + "@babel/plugin-proposal-dynamic-import@^7.13.8": version "7.13.8" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.13.8.tgz#876a1f6966e1dec332e8c9451afda3bebcdf2e1d" @@ -481,6 +490,16 @@ "@babel/helper-create-class-features-plugin" "^7.13.0" "@babel/helper-plugin-utils" "^7.13.0" +"@babel/plugin-proposal-private-property-in-object@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.14.0.tgz#b1a1f2030586b9d3489cc26179d2eb5883277636" + integrity sha512-59ANdmEwwRUkLjB7CRtwJxxwtjESw+X2IePItA+RGQh+oy5RmpCh/EvVVvh5XQc3yxsm5gtv0+i9oBZhaDNVTg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.12.13" + "@babel/helper-create-class-features-plugin" "^7.14.0" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/plugin-syntax-private-property-in-object" "^7.14.0" + "@babel/plugin-proposal-unicode-property-regex@^7.12.13", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.13.tgz#bebde51339be829c17aaaaced18641deb62b39ba" @@ -510,6 +529,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" +"@babel/plugin-syntax-class-static-block@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.12.13.tgz#8e3d674b0613e67975ceac2776c97b60cafc5c9c" + integrity sha512-ZmKQ0ZXR0nYpHZIIuj9zE7oIqCx2hw9TKi+lIo73NNrMPAZGHfS92/VRV0ZmPj6H2ffBgyFHXvJ5NYsNeEaP2A== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + "@babel/plugin-syntax-dynamic-import@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" @@ -594,6 +620,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-private-property-in-object@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.0.tgz#762a4babec61176fec6c88480dec40372b140c0b" + integrity sha512-bda3xF8wGl5/5btF794utNOL0Jw+9jE5C1sLZcoK7c4uonE/y3iQiyG+KbkF3WBV/paX58VCpjhxLPkdj5Fe4w== + dependencies: + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/plugin-syntax-top-level-await@^7.12.13", "@babel/plugin-syntax-top-level-await@^7.8.3": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.13.tgz#c5f0fa6e249f5b739727f923540cf7a806130178" @@ -631,7 +664,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-transform-block-scoping@^7.12.13": +"@babel/plugin-transform-block-scoping@^7.13.16": version "7.13.16" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.13.16.tgz#a9c0f10794855c63b1d629914c7dcfeddd185892" integrity sha512-ad3PHUxGnfWF4Efd3qFuznEtZKoBp0spS+DgqzVzRPV7urEBvPLue3y2j80w4Jf2YLzZHj8TOv/Lmvdmh3b2xg== @@ -658,7 +691,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.13.0" -"@babel/plugin-transform-destructuring@^7.13.0": +"@babel/plugin-transform-destructuring@^7.13.17": version "7.13.17" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.13.17.tgz#678d96576638c19d5b36b332504d3fd6e06dea27" integrity sha512-UAUqiLv+uRLO+xuBKKMEpC+t7YRNVRqBsWWq1yKXbBZBje/t3IXCiSinZhjn/DC3qzBfICeYd2EFGEbHsh5RLA== @@ -717,23 +750,23 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-transform-modules-amd@^7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.13.0.tgz#19f511d60e3d8753cc5a6d4e775d3a5184866cc3" - integrity sha512-EKy/E2NHhY/6Vw5d1k3rgoobftcNUmp9fGjb9XZwQLtTctsRBOTRO7RHHxfIky1ogMN5BxN7p9uMA3SzPfotMQ== +"@babel/plugin-transform-modules-amd@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.0.tgz#589494b5b290ff76cf7f59c798011f6d77026553" + integrity sha512-CF4c5LX4LQ03LebQxJ5JZes2OYjzBuk1TdiF7cG7d5dK4lAdw9NZmaxq5K/mouUdNeqwz3TNjnW6v01UqUNgpQ== dependencies: - "@babel/helper-module-transforms" "^7.13.0" + "@babel/helper-module-transforms" "^7.14.0" "@babel/helper-plugin-utils" "^7.13.0" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.13.8", "@babel/plugin-transform-modules-commonjs@^7.7.5": - version "7.13.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.13.8.tgz#7b01ad7c2dcf2275b06fa1781e00d13d420b3e1b" - integrity sha512-9QiOx4MEGglfYZ4XOnU79OHr6vIWUakIj9b4mioN8eQIoEh+pf5p/zEB36JpDFWA12nNMiRf7bfoRvl9Rn79Bw== +"@babel/plugin-transform-modules-commonjs@^7.13.8", "@babel/plugin-transform-modules-commonjs@^7.14.0", "@babel/plugin-transform-modules-commonjs@^7.7.5": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.0.tgz#52bc199cb581e0992edba0f0f80356467587f161" + integrity sha512-EX4QePlsTaRZQmw9BsoPeyh5OCtRGIhwfLquhxGp5e32w+dyL8htOcDwamlitmNFK6xBZYlygjdye9dbd9rUlQ== dependencies: - "@babel/helper-module-transforms" "^7.13.0" + "@babel/helper-module-transforms" "^7.14.0" "@babel/helper-plugin-utils" "^7.13.0" - "@babel/helper-simple-access" "^7.12.13" + "@babel/helper-simple-access" "^7.13.12" babel-plugin-dynamic-import-node "^2.3.3" "@babel/plugin-transform-modules-systemjs@^7.13.8": @@ -747,12 +780,12 @@ "@babel/helper-validator-identifier" "^7.12.11" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-umd@^7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.13.0.tgz#8a3d96a97d199705b9fd021580082af81c06e70b" - integrity sha512-D/ILzAh6uyvkWjKKyFE/W0FzWwasv6vPTSqPcjxFqn6QpX3u8DjRVliq4F2BamO2Wee/om06Vyy+vPkNrd4wxw== +"@babel/plugin-transform-modules-umd@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.0.tgz#2f8179d1bbc9263665ce4a65f305526b2ea8ac34" + integrity sha512-nPZdnWtXXeY7I87UZr9VlsWme3Y0cfFFE41Wbxz4bbaexAjNMInXPFUpRRUJ8NoMm0Cw+zxbqjdPmLhcjfazMw== dependencies: - "@babel/helper-module-transforms" "^7.13.0" + "@babel/helper-module-transforms" "^7.14.0" "@babel/helper-plugin-utils" "^7.13.0" "@babel/plugin-transform-named-capturing-groups-regex@^7.12.13": @@ -911,17 +944,18 @@ "@babel/helper-plugin-utils" "^7.12.13" "@babel/preset-env@^7.13.15": - version "7.13.15" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.13.15.tgz#c8a6eb584f96ecba183d3d414a83553a599f478f" - integrity sha512-D4JAPMXcxk69PKe81jRJ21/fP/uYdcTZ3hJDF5QX2HSI9bBxxYw/dumdR6dGumhjxlprHPE4XWoPaqzZUVy2MA== + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.14.0.tgz#236f88cd5da625e625dd40500d4824523f50e6c5" + integrity sha512-GWRCdBv2whxqqaSi7bo/BEXf070G/fWFMEdCnmoRg2CZJy4GK06ovFuEjJrZhDRXYgBsYtxVbG8GUHvw+UWBkQ== dependencies: - "@babel/compat-data" "^7.13.15" - "@babel/helper-compilation-targets" "^7.13.13" + "@babel/compat-data" "^7.14.0" + "@babel/helper-compilation-targets" "^7.13.16" "@babel/helper-plugin-utils" "^7.13.0" "@babel/helper-validator-option" "^7.12.17" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.13.12" "@babel/plugin-proposal-async-generator-functions" "^7.13.15" "@babel/plugin-proposal-class-properties" "^7.13.0" + "@babel/plugin-proposal-class-static-block" "^7.13.11" "@babel/plugin-proposal-dynamic-import" "^7.13.8" "@babel/plugin-proposal-export-namespace-from" "^7.12.13" "@babel/plugin-proposal-json-strings" "^7.13.8" @@ -932,9 +966,11 @@ "@babel/plugin-proposal-optional-catch-binding" "^7.13.8" "@babel/plugin-proposal-optional-chaining" "^7.13.12" "@babel/plugin-proposal-private-methods" "^7.13.0" + "@babel/plugin-proposal-private-property-in-object" "^7.14.0" "@babel/plugin-proposal-unicode-property-regex" "^7.12.13" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.12.13" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" "@babel/plugin-syntax-json-strings" "^7.8.3" @@ -944,14 +980,15 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.0" "@babel/plugin-syntax-top-level-await" "^7.12.13" "@babel/plugin-transform-arrow-functions" "^7.13.0" "@babel/plugin-transform-async-to-generator" "^7.13.0" "@babel/plugin-transform-block-scoped-functions" "^7.12.13" - "@babel/plugin-transform-block-scoping" "^7.12.13" + "@babel/plugin-transform-block-scoping" "^7.13.16" "@babel/plugin-transform-classes" "^7.13.0" "@babel/plugin-transform-computed-properties" "^7.13.0" - "@babel/plugin-transform-destructuring" "^7.13.0" + "@babel/plugin-transform-destructuring" "^7.13.17" "@babel/plugin-transform-dotall-regex" "^7.12.13" "@babel/plugin-transform-duplicate-keys" "^7.12.13" "@babel/plugin-transform-exponentiation-operator" "^7.12.13" @@ -959,10 +996,10 @@ "@babel/plugin-transform-function-name" "^7.12.13" "@babel/plugin-transform-literals" "^7.12.13" "@babel/plugin-transform-member-expression-literals" "^7.12.13" - "@babel/plugin-transform-modules-amd" "^7.13.0" - "@babel/plugin-transform-modules-commonjs" "^7.13.8" + "@babel/plugin-transform-modules-amd" "^7.14.0" + "@babel/plugin-transform-modules-commonjs" "^7.14.0" "@babel/plugin-transform-modules-systemjs" "^7.13.8" - "@babel/plugin-transform-modules-umd" "^7.13.0" + "@babel/plugin-transform-modules-umd" "^7.14.0" "@babel/plugin-transform-named-capturing-groups-regex" "^7.12.13" "@babel/plugin-transform-new-target" "^7.12.13" "@babel/plugin-transform-object-super" "^7.12.13" @@ -978,7 +1015,7 @@ "@babel/plugin-transform-unicode-escapes" "^7.12.13" "@babel/plugin-transform-unicode-regex" "^7.12.13" "@babel/preset-modules" "^0.1.4" - "@babel/types" "^7.13.14" + "@babel/types" "^7.14.0" babel-plugin-polyfill-corejs2 "^0.2.0" babel-plugin-polyfill-corejs3 "^0.2.0" babel-plugin-polyfill-regenerator "^0.2.0" @@ -1018,9 +1055,9 @@ "@babel/plugin-transform-typescript" "^7.13.0" "@babel/runtime-corejs3@^7.10.2": - version "7.13.17" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.13.17.tgz#9baf45f03d4d013f021760b992d6349a9d27deaf" - integrity sha512-RGXINY1YvduBlGrP+vHjJqd/nK7JVpfM4rmZLGMx77WoL3sMrhheA0qxii9VNn1VHnxJLEyxmvCB+Wqc+x/FMw== + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.14.0.tgz#6bf5fbc0b961f8e3202888cb2cd0fb7a0a9a3f66" + integrity sha512-0R0HTZWHLk6G8jIk0FtoX+AatCtKnswS98VhXwGImFc759PJRp4Tru0PQYZofyijTFUr+gT8Mu7sgXVJLQ0ceg== dependencies: core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" @@ -1033,9 +1070,9 @@ regenerator-runtime "^0.13.4" "@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.17", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.7", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": - version "7.13.17" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.17.tgz#8966d1fc9593bf848602f0662d6b4d0069e3a7ec" - integrity sha512-NCdgJEelPTSh+FEFylhnP1ylq848l1z9t9N0j1Lfbcw0+KXGjsTvUmkxy+voLLXB5SOKMbLLx4jxYliGrYQseA== + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6" + integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA== dependencies: regenerator-runtime "^0.13.4" @@ -1048,17 +1085,17 @@ "@babel/parser" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.13.13", "@babel/traverse@^7.13.15", "@babel/traverse@^7.13.17": - version "7.13.17" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.13.17.tgz#c85415e0c7d50ac053d758baec98b28b2ecfeea3" - integrity sha512-BMnZn0R+X6ayqm3C3To7o1j7Q020gWdqdyP50KEoVqaCO2c/Im7sYZSmVgvefp8TTMQ+9CtwuBp0Z1CZ8V3Pvg== +"@babel/traverse@^7.1.0", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.13.15", "@babel/traverse@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.14.0.tgz#cea0dc8ae7e2b1dec65f512f39f3483e8cc95aef" + integrity sha512-dZ/a371EE5XNhTHomvtuLTUyx6UEoJmYX+DT5zBCQN3McHemsuIaKKYqsc/fs26BEkHs/lBZy0J571LP5z9kQA== dependencies: "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.13.16" + "@babel/generator" "^7.14.0" "@babel/helper-function-name" "^7.12.13" "@babel/helper-split-export-declaration" "^7.12.13" - "@babel/parser" "^7.13.16" - "@babel/types" "^7.13.17" + "@babel/parser" "^7.14.0" + "@babel/types" "^7.14.0" debug "^4.1.0" globals "^11.1.0" @@ -1071,12 +1108,12 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@babel/types@^7.0.0", "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.12.6", "@babel/types@^7.12.7", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.13.14", "@babel/types@^7.13.16", "@babel/types@^7.13.17", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": - version "7.13.17" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.13.17.tgz#48010a115c9fba7588b4437dd68c9469012b38b4" - integrity sha512-RawydLgxbOPDlTLJNtoIypwdmAy//uQIzlKt2+iBiJaRlVuI6QLUxVAyWGNfOzp8Yu4L4lLIacoCyTNtpb4wiA== +"@babel/types@^7.0.0", "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.12.6", "@babel/types@^7.12.7", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.13.16", "@babel/types@^7.14.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.0.tgz#3fc3fc74e0cdad878182e5f66cc6bcab1915a802" + integrity sha512-O2LVLdcnWplaGxiPBz12d0HcdN8QdxdsWYhz5LSeuukV/5mn2xUUc3gBeU4QBYPJ18g/UToe8F532XJ608prmg== dependencies: - "@babel/helper-validator-identifier" "^7.12.11" + "@babel/helper-validator-identifier" "^7.14.0" to-fast-properties "^2.0.0" "@bcoe/v8-coverage@^0.2.3": @@ -1085,9 +1122,9 @@ integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== "@braintree/sanitize-url@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-5.0.0.tgz#3ba791f37b90e7f6170d252b63aacfcae943c039" - integrity sha512-WmKrB/575EJCzbeSJR3YQ5sET5FaizeljLRw1382qVUeGqzuWBgIS+AF5a0FO51uQTrDpoRgvuHC2IWVsgwkkA== + version "5.0.1" + resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-5.0.1.tgz#3c76855aea4a71904a35c92f433462c775583452" + integrity sha512-KzIC8q/UsT8g6bwRAQ0NbOCNxRoGbPKtqGBUtDaN8WN80xqsbHFs8z+Eq0fR0W1wcrcTB5oKNACsrbkK4X+FWA== "@changesets/apply-release-plan@^5.0.0": version "5.0.0" @@ -1437,17 +1474,18 @@ tslib "~2.2.0" "@graphql-tools/schema@^7.0.0", "@graphql-tools/schema@^7.1.3": - version "7.1.3" - resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-7.1.3.tgz#d816400da51fbac1f0086e35540ab63b5e30e858" - integrity sha512-ZY76hmcJlF1iyg3Im0sQ3ASRkiShjgv102vLTVcH22lEGJeCaCyyS/GF1eUHom418S60bS8Th6+autRUxfBiBg== + version "7.1.5" + resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-7.1.5.tgz#07b24e52b182e736a6b77c829fc48b84d89aa711" + integrity sha512-uyn3HSNSckf4mvQSq0Q07CPaVZMNFCYEVxroApOaw802m9DcZPgf9XVPy/gda5GWj9AhbijfRYVTZQgHnJ4CXA== dependencies: "@graphql-tools/utils" "^7.1.2" - tslib "~2.1.0" + tslib "~2.2.0" + value-or-promise "1.0.6" "@graphql-tools/utils@^7.1.2", "@graphql-tools/utils@^7.7.0": - version "7.7.3" - resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-7.7.3.tgz#1e34abc6b9fe1e6f8189bc23d1285b73bb07018d" - integrity sha512-zF8Ll1v7DOFfCsZVYGkJqvi3Zpwfga8NutOZkToXrumMlTPaMhEDFkiuwoIK4lV2PMVUke5ZCmpn9pc5pqy4Tw== + version "7.8.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-7.8.1.tgz#caa9f0f1b3c7ef12f48dc66215ef5413f288e131" + integrity sha512-LDbOweemjxPYgJuHXK5XZJgObsBkiD92ul98lcuZxgA49IzQazHho5Y1Hs3MluD93YtZpxsQg/f7gNPnAyR6yw== dependencies: "@ardatan/aggregate-error" "0.0.6" camel-case "4.1.2" @@ -1802,25 +1840,25 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" -"@next/env@10.1.3": - version "10.1.3" - resolved "https://registry.yarnpkg.com/@next/env/-/env-10.1.3.tgz#29e5d62919b4a7b1859f8d36169848dc3f5ddebe" - integrity sha512-q7z7NvmRs66lCQmVJtKjDxVtMTjSwP6ExVzaH46pbTH60MHgzEJ9H4jXrFLTihPmCIvpAv6Ai04jbS8dcg1ZMQ== +"@next/env@10.2.0": + version "10.2.0" + resolved "https://registry.yarnpkg.com/@next/env/-/env-10.2.0.tgz#154dbce2efa3ad067ebd20b7d0aa9aed775e7c97" + integrity sha512-tsWBsn1Rb6hXRaHc/pWMCpZ4Ipkf3OCbZ54ef5ukgIyEvzzGdGFXQshPP2AF7yb+8yMpunWs7vOMZW3e8oPF6A== "@next/mdx@^10.1.3": - version "10.1.3" - resolved "https://registry.yarnpkg.com/@next/mdx/-/mdx-10.1.3.tgz#2bb1e52969ec18b8dfff47dfdb89bbbc2edf9b1c" - integrity sha512-VpeT5jINIQjJ7TUKhawrNnVZEqEfRfZT2K//8RyoPAsjqp96vqHaISEk5NNd/d0hD7ZQpcWwKi8FpPel+wz3ew== + version "10.2.0" + resolved "https://registry.yarnpkg.com/@next/mdx/-/mdx-10.2.0.tgz#303bcc4ba4a6902aec8e6d2e677ad0b82dcc0336" + integrity sha512-2AwN5Q4Av6McSpVKps2dDGdKEEUdme0cjdmo0iNuBFdBPzMBMeMyIMrT9T/QPCDUtqeB747f6Zkf/Xt2uVwzBg== -"@next/polyfill-module@10.1.3": - version "10.1.3" - resolved "https://registry.yarnpkg.com/@next/polyfill-module/-/polyfill-module-10.1.3.tgz#beafe89bc4235d436fa0ed02c9d2a5d311fb0238" - integrity sha512-1DtUVcuoBJAn5IrxIZQjUG1KTPkiXMYloykPSkRxawimgvG9dRj2kscU+4KGNSFxHoxW9c68VRCb+7MDz5aGGw== +"@next/polyfill-module@10.2.0": + version "10.2.0" + resolved "https://registry.yarnpkg.com/@next/polyfill-module/-/polyfill-module-10.2.0.tgz#61f41110c4b465cc26d113e2054e205df61c3594" + integrity sha512-Nl3GexIUXsmuggkUqrRFyE/2k7UI44JaVzSywtXEyHzxpZm2a5bdMaWuC89pgLiFDDOqmbqyLAbtwm5lNxa7Eg== -"@next/react-dev-overlay@10.1.3": - version "10.1.3" - resolved "https://registry.yarnpkg.com/@next/react-dev-overlay/-/react-dev-overlay-10.1.3.tgz#ee1c6033b29be9b383e061bd9705021d131ea445" - integrity sha512-vIgUah3bR9+MKzwU1Ni5ONfYM0VdI42i7jZ+Ei1c0wjwkG9anVnDqhSQ3mVg62GP2nt7ExaaFyf9THbsw5KYXg== +"@next/react-dev-overlay@10.2.0": + version "10.2.0" + resolved "https://registry.yarnpkg.com/@next/react-dev-overlay/-/react-dev-overlay-10.2.0.tgz#4220121abac7e3404cbaf467784aeecca8be46cf" + integrity sha512-PRIAoWog41hLN4iJ8dChKp4ysOX0Q8yiNQ/cwzyqEd3EjugkDV5OiKl3mumGKaApJaIra1MX6j1wgQRuLhuWMA== dependencies: "@babel/code-frame" "7.12.11" anser "1.4.9" @@ -1834,10 +1872,10 @@ stacktrace-parser "0.1.10" strip-ansi "6.0.0" -"@next/react-refresh-utils@10.1.3": - version "10.1.3" - resolved "https://registry.yarnpkg.com/@next/react-refresh-utils/-/react-refresh-utils-10.1.3.tgz#65b3e1b9846c02452787fde1d54ad9c54b506dbd" - integrity sha512-P4GJZuLKfD/o42JvGZ/xP4Hxg68vd3NeZxOLqIuQKFjjaYgC2IrO+lE5PTwGmRkytjfprJC+9j7Jss/xQAS6QA== +"@next/react-refresh-utils@10.2.0": + version "10.2.0" + resolved "https://registry.yarnpkg.com/@next/react-refresh-utils/-/react-refresh-utils-10.2.0.tgz#55953b697769c6647f371bc6bcd865a24e1a22e9" + integrity sha512-3I31K9B4hEQRl7yQ44Umyz+szHtuMJrNdwsgJGhoEnUCXSBRHp5wv5Zv8eDa2NewSbe53b2C0oOpivrzmdBakw== "@nodelib/fs.scandir@2.1.4": version "2.1.4" @@ -2408,9 +2446,9 @@ "@testing-library/dom" "^7.28.1" "@testing-library/user-event@^13.1.5": - version "13.1.5" - resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-13.1.5.tgz#1ce11c37bf4df8f264fb7999ded7139e092a29bd" - integrity sha512-dD1FRHuWhfdcnb6H9/oaIIZHx9LQKGxbTtYV3i5Zru8I3GWWJoG2WtlAlXZ/56djO+6TvfsWPj5cXQvoTFQATQ== + version "13.1.8" + resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-13.1.8.tgz#9cbf342b88d837ee188f9f9f4df6d1beaaf179c2" + integrity sha512-M04HgOlJvxILf5xyrkJaEQfFOtcvhy3usLldQIEg9zgFIYQofSmFGVfFlS7BWowqlBGLrItwGMlPXCoBgoHSiw== dependencies: "@babel/runtime" "^7.12.5" @@ -2783,36 +2821,28 @@ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.1.tgz#283f669ff76d7b8260df8ab7a4262cc83d988256" integrity sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg== -"@types/node-fetch@2.5.7": - version "2.5.7" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c" - integrity sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw== - dependencies: - "@types/node" "*" - form-data "^3.0.0" - -"@types/node-fetch@2.5.8": - version "2.5.8" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.8.tgz#e199c835d234c7eb0846f6618012e558544ee2fb" - integrity sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw== +"@types/node-fetch@^2.5.10": + version "2.5.10" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.10.tgz#9b4d4a0425562f9fcea70b12cb3fcdd946ca8132" + integrity sha512-IpkX0AasN44hgEad0gEF/V6EgR5n69VEqPEgnmoM8GsIGro3PowbWs4tR6IhxUTyPLpOn+fiGG6nrQhcmoCuIQ== dependencies: "@types/node" "*" form-data "^3.0.0" "@types/node@*", "@types/node@>=8.1.0": - version "14.14.41" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.41.tgz#d0b939d94c1d7bd53d04824af45f1139b8c45615" - integrity sha512-dueRKfaJL4RTtSa7bWeTK1M+VH+Gns73oCgzvYfHZywRCoPSd8EkXBL0mZ9unPTveBn+D9phZBaxuzpwjWkW0g== + version "15.0.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-15.0.1.tgz#ef34dea0881028d11398be5bf4e856743e3dc35a" + integrity sha512-TMkXt0Ck1y0KKsGr9gJtWGjttxlZnnvDtphxUOSd0bfaR6Q1jle+sPvrzNR1urqYTWMinoKvjKfXUGsumaO1PA== "@types/node@^10.1.0": - version "10.17.58" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.58.tgz#10682f6016fd866725c36d22ce6bbbd029bf4545" - integrity sha512-Dn5RBxLohjdHFj17dVVw3rtrZAeXeWg+LQfvxDIW/fdPkSiuQk7h3frKMYtsQhtIW42wkErDcy9UMVxhGW4O7w== + version "10.17.59" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.59.tgz#03f440ccf746a27f7da6e141e6cbae64681dbd2f" + integrity sha512-7Uc8IRrL8yZz5ti45RaFxpbU8TxlzdC3HvxV+hOWo1EyLsuKv/w7y0n+TwZzwL3vdx3oZ2k3ubxPq131hNtXyg== "@types/node@^12.7.1": - version "12.20.10" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.10.tgz#4dcb8a85a8f1211acafb88d72fafc7e3d2685583" - integrity sha512-TxCmnSSppKBBOzYzPR2BR25YlX5Oay8z2XGwFBInuA/Co0V9xJhLlW4kjbxKtgeNo3NOMbQP1A5Rc03y+XecPw== + version "12.20.11" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.11.tgz#980832cd56efafff8c18aa148c4085eb02a483f4" + integrity sha512-gema+apZ6qLQK7k7F0dGkGCWQYsL0qqKORWOQO6tq46q+x+1C0vbOiOqOwRVlh4RAdbQwV/j/ryr3u5NOG1fPQ== "@types/nodemailer@^6.4.1": version "6.4.1" @@ -2949,9 +2979,9 @@ integrity sha512-dIPoZ3g5gcx9zZEszaxLSVTvMReD3xxyyDnQUjA6IYDG9Ba2AV0otMPs+77sG9ojB4Qr2N2Vk5RnKeuA0X/0bg== "@types/sizzle@^2.3.2": - version "2.3.2" - resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47" - integrity sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg== + version "2.3.3" + resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.3.tgz#ff5e2f1902969d305225a047c8a0fd5c915cebef" + integrity sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ== "@types/source-list-map@*": version "0.1.2" @@ -3052,9 +3082,9 @@ source-map "^0.6.0" "@types/ws@^7.0.0": - version "7.4.1" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.1.tgz#49eacb15a0534663d53a36fbf5b4d98f5ae9a73a" - integrity sha512-ISCK1iFnR+jYv7+jLNX0wDqesZ/5RAeY3wUx6QaphmocphU61h+b+PHjS18TF4WIPTu/MMzxIq2PHr32o2TS5Q== + version "7.4.2" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.2.tgz#bfe739b5f8b3a39742605fbe415ae7e88ee614c8" + integrity sha512-PbeN0Eydl7LQl4OIav29YmkO2LxbVuz3nZD/kb19lOS+wLgIkRbWMNmU/QQR7ABpOJ7D7xDOU8co7iohObewrw== dependencies: "@types/node" "*" @@ -3225,9 +3255,9 @@ acorn@^7.1.1, acorn@^7.4.0: integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== acorn@^8.1.0: - version "8.2.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.2.1.tgz#0d36af126fb6755095879c1dc6fd7edf7d60a5fb" - integrity sha512-z716cpm5TX4uzOzILx8PavOE6C6DKshHDw1aQN52M/yNSqE9s5O8SMfyhCCfCJ3HmTL0NkVOi+8a/55T7YB3bg== + version "8.2.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.2.2.tgz#c4574e4fea298d6e6ed4b85ab844b06dd59f26d6" + integrity sha512-VrMS8kxT0e7J1EX0p6rI/E0FbfOVcvBpbIqHThFv+f8YrZIlMfVotYcXKVPmTvPW8sW5miJzfUFrrvthUZg8VQ== agent-base@6: version "6.0.2" @@ -3260,9 +3290,9 @@ ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: uri-js "^4.2.2" ajv@^8.0.1: - version "8.1.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.1.0.tgz#45d5d3d36c7cdd808930cc3e603cf6200dbeb736" - integrity sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ== + version "8.2.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.2.0.tgz#c89d3380a784ce81b2085f48811c4c101df4c602" + integrity sha512-WSNGFuyWd//XO8n/m/EaOlNLtO0yL8EXT/74LqT4khdhpZjP7lkj/kT5uwRmGitKEVp/Oj7ZUHeGfPtgHhQ5CA== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" @@ -3360,40 +3390,30 @@ anymatch@^3.0.3, anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" -apollo-cache-control@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/apollo-cache-control/-/apollo-cache-control-0.12.0.tgz#45aea0a232d0704e33c2b1a3c428a5500b29818c" - integrity sha512-kClF5rfAm159Nboul1LxA+l58Tjz0M8L1GUknEMpZt0UHhILLAn3BfcG3ToX4TbNoR9M57kKMUcbPWLdy3Up7w== - dependencies: - apollo-server-env "^3.0.0" - apollo-server-plugin-base "^0.11.0" - -apollo-datasource@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/apollo-datasource/-/apollo-datasource-0.8.0.tgz#8cf9103e83558bd30b3b522cb8ec80725c3160ce" - integrity sha512-gXgsGVLuejLc138z/2jUjPAzadDQxWbcLJyBgaQsg5BaXJNkv5uW/NjiSPk00cK51hyZrb0Xx8a+L+wPk2qIBA== +apollo-cache-control@^0.13.0: + version "0.13.0" + resolved "https://registry.yarnpkg.com/apollo-cache-control/-/apollo-cache-control-0.13.0.tgz#cd63aa24a662b2fe89ef147a30df907c8061aedc" + integrity sha512-ImUXwVc/8K9QA3mQiKbKw8bOS4lMNL4DoP4hldIx+gwna8dgh3gBChgxW5guMOhcvH/55ximS7ZNWUglFmQY4Q== dependencies: - apollo-server-caching "^0.6.0" - apollo-server-env "^3.0.0" + apollo-server-env "^3.1.0" + apollo-server-plugin-base "^0.12.0" -apollo-env@^0.6.6: - version "0.6.6" - resolved "https://registry.yarnpkg.com/apollo-env/-/apollo-env-0.6.6.tgz#d7880805c4e96ee3d4142900a405176a04779438" - integrity sha512-hXI9PjJtzmD34XviBU+4sPMOxnifYrHVmxpjykqI/dUD2G3yTiuRaiQqwRwB2RCdwC1Ug/jBfoQ/NHDTnnjndQ== +apollo-datasource@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/apollo-datasource/-/apollo-datasource-0.9.0.tgz#b0b2913257a6103a5f4c03cb56d78a30e9d850db" + integrity sha512-y8H99NExU1Sk4TvcaUxTdzfq2SZo6uSj5dyh75XSQvbpH6gdAXIW9MaBcvlNC7n0cVPsidHmOcHOWxJ/pTXGjA== dependencies: - "@types/node-fetch" "2.5.7" - core-js "^3.0.1" - node-fetch "^2.2.0" - sha.js "^2.4.11" + apollo-server-caching "^0.7.0" + apollo-server-env "^3.1.0" -apollo-env@^0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/apollo-env/-/apollo-env-0.9.0.tgz#26555580e0bf7e253cf86feac7425b976409b513" - integrity sha512-oMSaFiCYEULXTv1sLhuPpAg0SykJNzEu5QWvCw0844yq14MyETXFERmAYD9b8nNjQLAdpjbbkBGKTWcw5wgd5Q== +apollo-env@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/apollo-env/-/apollo-env-0.10.0.tgz#8dd51bf974253a760ea15c81e870ff2c0d6e6820" + integrity sha512-7Geot+eyOl4jzPi9beiszeDmEEVZOVT11LSlkQluF5eaCNaIvld+xklZxITZGI/Wr+PQX380YJgQt1ndR2GtOg== dependencies: - "@types/node-fetch" "2.5.8" + "@types/node-fetch" "^2.5.10" core-js "^3.0.1" - node-fetch "^2.2.0" + node-fetch "^2.6.1" sha.js "^2.4.11" apollo-errors@^1.9.0: @@ -3404,13 +3424,14 @@ apollo-errors@^1.9.0: assert "^1.4.1" extendable-error "^0.1.5" -apollo-graphql@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/apollo-graphql/-/apollo-graphql-0.6.1.tgz#d0bf0aff76f445de3da10e08f6974f1bf65f5753" - integrity sha512-ZRXAV+k+hboCVS+FW86FW/QgnDR7gm/xMUwJPGXEbV53OLGuQQdIT0NCYK7AzzVkCfsbb7NJ3mmEclkZY9uuxQ== +apollo-graphql@^0.9.0: + version "0.9.2" + resolved "https://registry.yarnpkg.com/apollo-graphql/-/apollo-graphql-0.9.2.tgz#750ca9a97b59c868426defc95d9d9e1733ae4bdf" + integrity sha512-+c/vqC2LPq3e5kO7MfBxDDiljzLog/THZr9Pd46HVaKAhHUxFL0rJEbT17VhjdOoZGWFWLYG7x9hiN6EQD1xZQ== dependencies: - apollo-env "^0.6.6" + core-js-pure "^3.10.2" lodash.sortby "^4.7.0" + sha.js "^2.4.11" apollo-link@^1.2.14: version "1.2.14" @@ -3429,6 +3450,13 @@ apollo-reporting-protobuf@^0.6.2: dependencies: "@apollo/protobufjs" "^1.0.3" +apollo-reporting-protobuf@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/apollo-reporting-protobuf/-/apollo-reporting-protobuf-0.7.0.tgz#622352d3eea943dff2647741a509b39d464f98a9" + integrity sha512-PC+zDqPPJcseemqmvUEqFiDi45pz6UaPWt6czgmrrbcQ+9VWp6IEkm08V5xBKk7V1WGUw19YwiJ7kqXpcgVNyw== + dependencies: + "@apollo/protobufjs" "1.2.2" + apollo-server-caching@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/apollo-server-caching/-/apollo-server-caching-0.6.0.tgz#3140a023ce0be8c43ba0b2f5be9cc5d15d1a32f6" @@ -3436,29 +3464,36 @@ apollo-server-caching@^0.6.0: dependencies: lru-cache "^6.0.0" -apollo-server-core@^2.23.0: - version "2.23.0" - resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.23.0.tgz#65ac55a293205efa63eadbf09d30704d6a5974d3" - integrity sha512-3/a4LPgRADc8CdT/nRh7W0CAqQv3Q4DJvakWQgKqGSqDEb/0u4IBynYjlQKuPBi4wwKdeK2Hb1wiQLl+zu4StQ== +apollo-server-caching@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/apollo-server-caching/-/apollo-server-caching-0.7.0.tgz#e6d1e68e3bb571cba63a61f60b434fb771c6ff39" + integrity sha512-MsVCuf/2FxuTFVhGLK13B+TZH9tBd2qkyoXKKILIiGcZ5CDUEBO14vIV63aNkMkS1xxvK2U4wBcuuNj/VH2Mkw== dependencies: - "@apollographql/apollo-tools" "^0.4.3" + lru-cache "^6.0.0" + +apollo-server-core@^2.24.0: + version "2.24.0" + resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.24.0.tgz#60313e5bd265422d53fe0ffbd45760046465f5f0" + integrity sha512-uW7gykPzhin9fLgSvciN8tX7098mHnUM79W3+fWfK5J415JidIqW9O+JhYmEPo6BCgosu0cKSdYe7NB+FP4lFQ== + dependencies: + "@apollographql/apollo-tools" "^0.5.0" "@apollographql/graphql-playground-html" "1.6.27" "@apollographql/graphql-upload-8-fork" "^8.1.3" "@josephg/resolvable" "^1.0.0" "@types/ws" "^7.0.0" - apollo-cache-control "^0.12.0" - apollo-datasource "^0.8.0" - apollo-graphql "^0.6.0" - apollo-reporting-protobuf "^0.6.2" - apollo-server-caching "^0.6.0" - apollo-server-env "^3.0.0" + apollo-cache-control "^0.13.0" + apollo-datasource "^0.9.0" + apollo-graphql "^0.9.0" + apollo-reporting-protobuf "^0.7.0" + apollo-server-caching "^0.7.0" + apollo-server-env "^3.1.0" apollo-server-errors "^2.5.0" - apollo-server-plugin-base "^0.11.0" - apollo-server-types "^0.7.0" - apollo-tracing "^0.13.0" + apollo-server-plugin-base "^0.12.0" + apollo-server-types "^0.8.0" + apollo-tracing "^0.14.0" async-retry "^1.2.1" fast-json-stable-stringify "^2.0.0" - graphql-extensions "^0.13.0" + graphql-extensions "^0.14.0" graphql-tag "^2.11.0" graphql-tools "^4.0.8" loglevel "^1.6.7" @@ -3468,12 +3503,12 @@ apollo-server-core@^2.23.0: uuid "^8.0.0" ws "^6.0.0" -apollo-server-env@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/apollo-server-env/-/apollo-server-env-3.0.0.tgz#0157c51f52b63aee39af190760acf789ffc744d9" - integrity sha512-tPSN+VttnPsoQAl/SBVUpGbLA97MXG990XIwq6YUnJyAixrrsjW1xYG7RlaOqetxm80y5mBZKLrRDiiSsW/vog== +apollo-server-env@^3.0.0, apollo-server-env@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/apollo-server-env/-/apollo-server-env-3.1.0.tgz#0733c2ef50aea596cc90cf40a53f6ea2ad402cd0" + integrity sha512-iGdZgEOAuVop3vb0F2J3+kaBVi4caMoxefHosxmgzAbbSpvWehB8Y1QiSyyMeouYC38XNVk5wnZl+jdGSsWsIQ== dependencies: - node-fetch "^2.1.2" + node-fetch "^2.6.1" util.promisify "^1.0.0" apollo-server-errors@^2.5.0: @@ -3482,9 +3517,9 @@ apollo-server-errors@^2.5.0: integrity sha512-lO5oTjgiC3vlVg2RKr3RiXIIQ5pGXBFxYGGUkKDhTud3jMIhs+gel8L8zsEjKaKxkjHhCQAA/bcEfYiKkGQIvA== apollo-server-express@^2.23.0: - version "2.23.0" - resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-2.23.0.tgz#7a779e45522f3c8f68ac748fea1a09e982981549" - integrity sha512-tzil7c51ODH0rT1Bc5VMksdWzHrYGavdLtnDz4M0ePiTm18Gc81HD7X/4DPczorerEpfwwkf2YlADtPQfRSxlw== + version "2.24.0" + resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-2.24.0.tgz#f17444929fc776fa1c166d8bad9685bd65dfa1c9" + integrity sha512-wVoD53azxqVZt/i4yAm6cDDCXpbzr0AJpzOdNXVFW/KivInWEMF5ekCc80uMOawPeu78U7Skoc20akyvZKc+YA== dependencies: "@apollographql/graphql-playground-html" "1.6.27" "@types/accepts" "^1.3.5" @@ -3493,8 +3528,8 @@ apollo-server-express@^2.23.0: "@types/express" "4.17.11" "@types/express-serve-static-core" "4.17.19" accepts "^1.3.5" - apollo-server-core "^2.23.0" - apollo-server-types "^0.7.0" + apollo-server-core "^2.24.0" + apollo-server-types "^0.8.0" body-parser "^1.18.3" cors "^2.8.5" express "^4.17.1" @@ -3505,22 +3540,22 @@ apollo-server-express@^2.23.0: type-is "^1.6.16" apollo-server-micro@^2.23.0: - version "2.23.0" - resolved "https://registry.yarnpkg.com/apollo-server-micro/-/apollo-server-micro-2.23.0.tgz#a2b66a47515a09e256c417c514996e9f47de1aff" - integrity sha512-XQKM66cqpmJFIXmRbcNFjTMdZFhqD/TvXtd5Mid/fSUeyRro0FaZopEQ/gcx3QbqJmv4K86wznRx4kvYtuRFqw== + version "2.24.0" + resolved "https://registry.yarnpkg.com/apollo-server-micro/-/apollo-server-micro-2.24.0.tgz#b94a226d61fa87c384da90d9868f7618aff7709d" + integrity sha512-mXcp/ql+Sz5icxpNy1R3NHJq3ECVG8knkwTmp6v9hPiCTDXVl+Cbx/1xKT4AaqenqlwdWdyvY0pAJsB56n8qdQ== dependencies: "@apollographql/graphql-playground-html" "1.6.27" accept "^3.0.2" - apollo-server-core "^2.23.0" - apollo-server-types "^0.7.0" + apollo-server-core "^2.24.0" + apollo-server-types "^0.8.0" micro "^9.3.2" -apollo-server-plugin-base@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/apollo-server-plugin-base/-/apollo-server-plugin-base-0.11.0.tgz#6ceeb4d5f643ed739fd00e8b26d9981186c200d0" - integrity sha512-Du68x0XCyQ6EWlgoL9Z+1s8fJfXgY131QbKP7ao617StQPzwB0aGCwxBDfcMt1A75VXf4TkvV1rdUH5YeJFlhQ== +apollo-server-plugin-base@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/apollo-server-plugin-base/-/apollo-server-plugin-base-0.12.0.tgz#9063c47e84c849c4227b9398cd06994f13b3a4c3" + integrity sha512-jnNIztYz34ImE7off0t9LwseGCR/J0H1wlbiBGvdXvQY+ZiMfVF2oF8KdSAPxG2vT6scvWP4GFS/FsZcOyP1Xw== dependencies: - apollo-server-types "^0.7.0" + apollo-server-types "^0.8.0" apollo-server-types@^0.7.0: version "0.7.0" @@ -3531,13 +3566,22 @@ apollo-server-types@^0.7.0: apollo-server-caching "^0.6.0" apollo-server-env "^3.0.0" -apollo-tracing@^0.13.0: - version "0.13.0" - resolved "https://registry.yarnpkg.com/apollo-tracing/-/apollo-tracing-0.13.0.tgz#8621b1ae351f862bb48b6de7a85696288977d148" - integrity sha512-28z4T+XfLQ6t696usU0nTFDxVN8BfF3o74d2p/zsT4eu1OuoyoDOEmVJqdInmVRpyTJK0tDEOjkIuDJJHZftog== +apollo-server-types@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/apollo-server-types/-/apollo-server-types-0.8.0.tgz#5462c99e93c5b6896d686bc234c05850059b2efe" + integrity sha512-adHJnHbRV2kWUY0VQY1M2KpSdGfm+4mX4w+2lROPExqOnkyTI7CGfpJCdEwYMKrIn3aH8HIcOH0SnpWRet6TNw== dependencies: - apollo-server-env "^3.0.0" - apollo-server-plugin-base "^0.11.0" + apollo-reporting-protobuf "^0.7.0" + apollo-server-caching "^0.7.0" + apollo-server-env "^3.1.0" + +apollo-tracing@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/apollo-tracing/-/apollo-tracing-0.14.0.tgz#2b7e07e6f1cb9d6161f03dc6e51baaa8468735bd" + integrity sha512-KH4mOoicZ2CQkEYVuNP9avJth59LwNqku3fKZ4S0UYE1RfxzIoLLsEyuY8MuJEgNdtKKfkX5G5Kn5Rp4LCJ4RQ== + dependencies: + apollo-server-env "^3.1.0" + apollo-server-plugin-base "^0.12.0" apollo-upload-client@^14.1.3: version "14.1.3" @@ -4206,14 +4250,14 @@ browserslist@4.16.1: escalade "^3.1.1" node-releases "^1.1.69" -browserslist@^4.14.5, browserslist@^4.16.4: - version "4.16.5" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.5.tgz#952825440bca8913c62d0021334cbe928ef062ae" - integrity sha512-C2HAjrM1AI/djrpAUU/tr4pml1DqLIzJKSLDBXBrNErl9ZCCTXdhwxdJjYc16953+mBWf7Lw+uUJgpgb8cN71A== +browserslist@^4.14.5, browserslist@^4.16.5: + version "4.16.6" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2" + integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ== dependencies: - caniuse-lite "^1.0.30001214" + caniuse-lite "^1.0.30001219" colorette "^1.2.2" - electron-to-chromium "^1.3.719" + electron-to-chromium "^1.3.723" escalade "^3.1.1" node-releases "^1.1.71" @@ -4393,10 +4437,10 @@ camelcase@^6.0.0, camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== -caniuse-lite@^1.0.30001173, caniuse-lite@^1.0.30001179, caniuse-lite@^1.0.30001214: - version "1.0.30001214" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001214.tgz#70f153c78223515c6d37a9fde6cd69250da9d872" - integrity sha512-O2/SCpuaU3eASWVaesQirZv1MSjUNOvmugaD8zNSJqw6Vv5SGwoOpA9LJs3pNPfM745nxqPvfZY3MQKY4AKHYg== +caniuse-lite@^1.0.30001173, caniuse-lite@^1.0.30001179, caniuse-lite@^1.0.30001202, caniuse-lite@^1.0.30001219: + version "1.0.30001220" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001220.tgz#c080e1c8eefb99f6cc9685da6313840bdbaf4c36" + integrity sha512-pjC2T4DIDyGAKTL4dMvGUQaMUHRmhvPpAgNNTa14jaBWHu+bLQgvpFqElxh9L4829Fdx0PlKiMp3wnYldRtECA== capture-exit@^2.0.0: version "2.0.0" @@ -4921,17 +4965,17 @@ copy-to-clipboard@^3.3.1: toggle-selection "^1.0.6" core-js-compat@^3.9.0, core-js-compat@^3.9.1: - version "3.11.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.11.0.tgz#635683f43480a0b41e3f6be3b1c648dadb8b4390" - integrity sha512-3wsN9YZJohOSDCjVB0GequOyHax8zFiogSX3XWLE28M1Ew7dTU57tgHjIylSBKSIouwmLBp3g61sKMz/q3xEGA== + version "3.11.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.11.1.tgz#57a91e9b02d3bb8cf37f82eceaf44a3d646fa614" + integrity sha512-aZ0e4tmlG/aOBHj92/TuOuZwp6jFvn1WNabU5VOVixzhu5t5Ao+JZkQOPlgNXu6ynwLrwJxklT4Gw1G1VGEh+g== dependencies: - browserslist "^4.16.4" + browserslist "^4.16.5" semver "7.0.0" -core-js-pure@^3.0.0: - version "3.11.0" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.11.0.tgz#e07f25a8f616d178ec16b0354b008ad28b20b2f0" - integrity sha512-PxEiQGjzC+5qbvE7ZIs5Zn6BynNeZO9zHhrrWmkRff2SZLq0CE/H5LuZOJHhmOQ8L38+eMzEHAmPYWrUtDfuDQ== +core-js-pure@^3.0.0, core-js-pure@^3.10.2: + version "3.11.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.11.1.tgz#fd52fa8c8b7b797b3606524b3d97278a8d8e7f09" + integrity sha512-2JukQi8HgAOCD5CSimxWWXVrUBoA9Br796uIA5Z06bIjt7PBBI19ircFaAxplgE1mJf3x2BY6MkT/HWA/UryPg== core-js@3.6.5: version "3.6.5" @@ -4939,9 +4983,9 @@ core-js@3.6.5: integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== core-js@^3.0.1, core-js@^3.1.3: - version "3.11.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.11.0.tgz#05dac6aa70c0a4ad842261f8957b961d36eb8926" - integrity sha512-bd79DPpx+1Ilh9+30aT5O1sgpQd4Ttg8oqkqi51ZzhedMM1omD2e6IOF48Z/DzDCZ2svp49tN/3vneTK6ZBkXw== + version "3.11.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.11.1.tgz#f920392bf8ed63a0ec8e4e729857bfa3d121c525" + integrity sha512-k93Isqg7e4txZWMGNYwevZL9MiogLk8pd1PtwrmFmi8IBq4GXqUaVW/a33Llt6amSI36uSjd0GWwc9pTT9ALlQ== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -5138,21 +5182,19 @@ cssfilter@0.0.10: resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae" integrity sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4= -cssnano-preset-simple@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/cssnano-preset-simple/-/cssnano-preset-simple-1.2.2.tgz#c631bf79ffec7fdfc4069e2f2da3ca67d99d8413" - integrity sha512-gtvrcRSGtP3hA/wS8mFVinFnQdEsEpm3v4I/s/KmNjpdWaThV/4E5EojAzFXxyT5OCSRPLlHR9iQexAqKHlhGQ== +cssnano-preset-simple@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/cssnano-preset-simple/-/cssnano-preset-simple-2.0.0.tgz#b55e72cb970713f425560a0e141b0335249e2f96" + integrity sha512-HkufSLkaBJbKBFx/7aj5HmCK9Ni/JedRQm0mT2qBzMG/dEuJOLnMt2lK6K1rwOOyV4j9aSY+knbW9WoS7BYpzg== dependencies: - caniuse-lite "^1.0.30001179" - postcss "^7.0.32" + caniuse-lite "^1.0.30001202" -cssnano-simple@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/cssnano-simple/-/cssnano-simple-1.2.2.tgz#72c2c3970e67123c3b4130894a30dc1050267007" - integrity sha512-4slyYc1w4JhSbhVX5xi9G0aQ42JnRyPg+7l7cqoNyoIDzfWx40Rq3JQZnoAWDu60A4AvKVp9ln/YSUOdhDX68g== +cssnano-simple@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/cssnano-simple/-/cssnano-simple-2.0.0.tgz#930d9dcd8ba105c5a62ce719cb00854da58b5c05" + integrity sha512-0G3TXaFxlh/szPEG/o3VcmCwl0N3E60XNb9YZZijew5eIs6fLjJuOPxQd9yEBaX2p/YfJtt49i4vYi38iH6/6w== dependencies: - cssnano-preset-simple "1.2.2" - postcss "^7.0.32" + cssnano-preset-simple "^2.0.0" csso@^4.0.2: version "4.2.0" @@ -5566,9 +5608,9 @@ dom-accessibility-api@^0.5.4: integrity sha512-TvrjBckDy2c6v6RLxPv5QXOnU+SmF9nBII5621Ve5fu6Z/BDrENurBEvlC1f44lKEUVqOpK4w9E5Idc5/EgkLQ== dom-helpers@^5.0.1: - version "5.2.0" - resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.0.tgz#57fd054c5f8f34c52a3eeffdb7e7e93cd357d95b" - integrity sha512-Ru5o9+V8CpunKnz5LGgWXkmrH/20cGKwcHwS4m73zIvs54CN9epEmT/HLqFJW3kXpakAFkEdzgy1hzlJe3E4OQ== + version "5.2.1" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" + integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== dependencies: "@babel/runtime" "^7.8.7" csstype "^3.0.2" @@ -5656,10 +5698,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.634, electron-to-chromium@^1.3.719: - version "1.3.720" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.720.tgz#f5d66df8754d993006b7b2ded15ff7738c58bd94" - integrity sha512-B6zLTxxaOFP4WZm6DrvgRk8kLFYWNhQ5TrHMC0l5WtkMXhU5UbnvWoTfeEwqOruUSlNMhVLfYak7REX6oC5Yfw== +electron-to-chromium@^1.3.634, electron-to-chromium@^1.3.723: + version "1.3.725" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.725.tgz#04fc83f9189169aff50f0a00c6b4090b910cba85" + integrity sha512-2BbeAESz7kc6KBzs7WVrMc1BY5waUphk4D4DX5dSQXJhsc3tP5ZFaiyuL0AB7vUKzDYpIeYwTYlEfxyjsGUrhw== elegant-spinner@^1.0.1: version "1.0.1" @@ -6965,14 +7007,14 @@ grapheme-splitter@^1.0.4: resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== -graphql-extensions@^0.13.0: - version "0.13.0" - resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.13.0.tgz#34d7f9c1bf49d09c4f1fa8b5d33e6c961a1889fb" - integrity sha512-Bb7E97nvfX4gtrIdZ/i5YFlqOd6MGzrw8ED+t4wQVraYje6NQ+8P8MHMOV2WZLfbW8zsNTx8NdnnlbsdH5siag== +graphql-extensions@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.14.0.tgz#cddf2fd43168e18be1d0e9057a4b3647febdd35f" + integrity sha512-DFtD8G+6rSj/Xhtb0IPh4A/sB/qcSEm9MTS221ESCx+axrsME92wGEsr7ihVjn1/tEEIy+9V5lUQOH/dHkCb0A== dependencies: - "@apollographql/apollo-tools" "^0.4.3" - apollo-server-env "^3.0.0" - apollo-server-types "^0.7.0" + "@apollographql/apollo-tools" "^0.5.0" + apollo-server-env "^3.1.0" + apollo-server-types "^0.8.0" graphql-subscriptions@^1.0.0: version "1.2.1" @@ -6981,15 +7023,10 @@ graphql-subscriptions@^1.0.0: dependencies: iterall "^1.3.0" -graphql-tag@^2.11.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.11.0.tgz#1deb53a01c46a7eb401d6cb59dec86fa1cccbffd" - integrity sha512-VmsD5pJqWJnQZMUeRwrDhfgoyqcfwEkvtpANqcoUG8/tOLkwNgU9mzub/Mc78OJMhHjx7gfAMTxzdG43VGg3bA== - -graphql-tag@^2.12.0: - version "2.12.3" - resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.3.tgz#ac47bf9d51c67c68ada8a33fd527143ed15bb647" - integrity sha512-5wJMjSvj30yzdciEuk9dPuUBUR56AqDi3xncoYQl1i42pGdSqOJrJsdb/rz5BDoy+qoGvQwABcBeF0xXY3TrKw== +graphql-tag@^2.11.0, graphql-tag@^2.12.0: + version "2.12.4" + resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.4.tgz#d34066688a4f09e72d6f4663c74211e9b4b7c4bf" + integrity sha512-VV1U4O+9x99EkNpNmCUV5RZwq6MnK4+pGbRYWG+lA/m3uo7TSqJF81OkcOP148gFP6fzdl7JWYBrwWVTS9jXww== dependencies: tslib "^2.1.0" @@ -7457,9 +7494,9 @@ indent-string@^4.0.0: integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== inflection@^1.12.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416" - integrity sha1-ogCTVlbW9fa8TcdQLhrstwMihBY= + version "1.13.1" + resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.13.1.tgz#c5cadd80888a90cf84c2e96e340d7edc85d5f0cb" + integrity sha512-dldYtl2WlN0QDkIDtg8+xFwOS2Tbmp12t1cHa5/YClU6ZQjTFm7B66UcVbh9NQB+HvT5BAd2t5+yKsBkw5pcqA== inflight@^1.0.4: version "1.0.6" @@ -8677,14 +8714,6 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -line-column@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/line-column/-/line-column-1.0.2.tgz#d25af2936b6f4849172b312e4792d1d987bc34a2" - integrity sha1-0lryk2tvSEkXKzEuR5LR2Ye8NKI= - dependencies: - isarray "^1.0.0" - isobject "^2.0.0" - lines-and-columns@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" @@ -9514,7 +9543,7 @@ nan@^2.12.1: resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== -nanoid@^3.1.16: +nanoid@^3.1.22: version "3.1.22" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.22.tgz#b35f8fb7d151990a8aebd5aa5015c03cf726f844" integrity sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ== @@ -9572,16 +9601,16 @@ next-images@^1.7.0: url-loader "^4.0.0" next@^10.1.3: - version "10.1.3" - resolved "https://registry.yarnpkg.com/next/-/next-10.1.3.tgz#e26e8371343a42bc2ba9be5cb253a7d324d03673" - integrity sha512-8Jf38F+s0YcXXkJGF5iUxOqSmbHrey0fX5Epc43L0uwDKmN2jK9vhc2ihCwXC1pmu8d2m/8wfTiXRJKGti55yw== + version "10.2.0" + resolved "https://registry.yarnpkg.com/next/-/next-10.2.0.tgz#6654cc925d8abcb15474fa062fc6b3ee527dd6dc" + integrity sha512-PKDKCSF7s82xudu3kQhOEaokxggpbLEWouEUtzP6OqV0YqKYHF+Ff+BFLycEem8ixtTM2M6ElN0VRJcskJfxPQ== dependencies: "@babel/runtime" "7.12.5" "@hapi/accept" "5.0.1" - "@next/env" "10.1.3" - "@next/polyfill-module" "10.1.3" - "@next/react-dev-overlay" "10.1.3" - "@next/react-refresh-utils" "10.1.3" + "@next/env" "10.2.0" + "@next/polyfill-module" "10.2.0" + "@next/react-dev-overlay" "10.2.0" + "@next/react-refresh-utils" "10.2.0" "@opentelemetry/api" "0.14.0" assert "2.0.0" ast-types "0.13.2" @@ -9593,7 +9622,7 @@ next@^10.1.3: chokidar "3.5.1" constants-browserify "1.0.0" crypto-browserify "3.12.0" - cssnano-simple "1.2.2" + cssnano-simple "2.0.0" domain-browser "4.19.0" encoding "0.1.13" etag "1.8.1" @@ -9609,7 +9638,7 @@ next@^10.1.3: p-limit "3.1.0" path-browserify "1.0.1" pnp-webpack-plugin "1.6.4" - postcss "8.1.7" + postcss "8.2.13" process "0.11.10" prop-types "15.7.2" querystring-es3 "0.2.1" @@ -9640,7 +9669,7 @@ no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" -node-fetch@2.6.1, node-fetch@^2.1.2, node-fetch@^2.2.0, node-fetch@^2.5.0, node-fetch@^2.6.0, node-fetch@^2.6.1: +node-fetch@2.6.1, node-fetch@^2.5.0, node-fetch@^2.6.0, node-fetch@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== @@ -9709,9 +9738,9 @@ node-releases@^1.1.69, node-releases@^1.1.71: integrity sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg== nodemailer@^6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.5.0.tgz#d12c28d8d48778918e25f1999d97910231b175d9" - integrity sha512-Tm4RPrrIZbnqDKAvX+/4M+zovEReiKlEXWDzG4iwtpL9X34MJY+D5LnQPH/+eghe8DLlAVshHAJZAZWBGhkguw== + version "6.6.0" + resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.6.0.tgz#ed47bb572b48d9d0dca3913fdc156203f438f427" + integrity sha512-ikSMDU1nZqpo2WUPE0wTTw/NGGImTkwpJKDIFPZT+YvvR9Sj+ze5wzu95JHkBMglQLoG2ITxU21WukCC/XsFkg== normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.5.0: version "2.5.0" @@ -10472,24 +10501,14 @@ posix-character-classes@^0.1.0: resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= -postcss@8.1.7: - version "8.1.7" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.1.7.tgz#ff6a82691bd861f3354fd9b17b2332f88171233f" - integrity sha512-llCQW1Pz4MOPwbZLmOddGM9eIJ8Bh7SZ2Oj5sxZva77uVaotYDsYTch1WBTNu7fUY0fpWp0fdt7uW40D4sRiiQ== - dependencies: - colorette "^1.2.1" - line-column "^1.0.2" - nanoid "^3.1.16" - source-map "^0.6.1" - -postcss@^7.0.32: - version "7.0.35" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24" - integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg== +postcss@8.2.13: + version "8.2.13" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.13.tgz#dbe043e26e3c068e45113b1ed6375d2d37e2129f" + integrity sha512-FCE5xLH+hjbzRdpbRb1IMCvPv9yZx2QnDarBEYSN0N0HYk+TcXsEhwdFcFb+SRWOKzKGErhIEbBK2ogyLdTtfQ== dependencies: - chalk "^2.4.2" + colorette "^1.2.2" + nanoid "^3.1.22" source-map "^0.6.1" - supports-color "^6.1.0" preferred-pm@^3.0.0: version "3.0.3" @@ -11506,9 +11525,9 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: inherits "^2.0.1" rollup@^2.32.0: - version "2.45.2" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.45.2.tgz#8fb85917c9f35605720e92328f3ccbfba6f78b48" - integrity sha512-kRRU7wXzFHUzBIv0GfoFFIN3m9oteY4uAsKllIpQDId5cfnkWF2J130l+27dzDju0E6MScKiV0ZM5Bw8m4blYQ== + version "2.46.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.46.0.tgz#8cacf89d2ee31a34755f1af40a665168f592b829" + integrity sha512-qPGoUBNl+Z8uNu0z7pD3WPTABWRbcOwIrO/5ccDJzmrtzn0LVf6Lj91+L5CcWhXl6iWf23FQ6m8Jkl2CmN1O7Q== optionalDependencies: fsevents "~2.3.1" @@ -12390,13 +12409,6 @@ supports-color@^5.0.0, supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -supports-color@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" - integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== - dependencies: - has-flag "^3.0.0" - supports-color@^7.0.0, supports-color@^7.1.0, supports-color@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -12464,9 +12476,9 @@ tabbable@^5.2.0: integrity sha512-0uyt8wbP0P3T4rrsfYg/5Rg3cIJ8Shl1RJ54QMqYxm1TLdWqJD1u6+RQjr2Lor3wmfT7JRHkirIwy99ydBsyPg== table@^6.0.4: - version "6.5.1" - resolved "https://registry.yarnpkg.com/table/-/table-6.5.1.tgz#930885a7430f15f8766b35cd1e36de40793db523" - integrity sha512-xGDXWTBJxahkzPQCsn1S9ESHEenU7TbMD5Iv4FeopXv/XwJyWatFjfbor+6ipI10/MNPXBYUamYukOrbPZ9L/w== + version "6.6.0" + resolved "https://registry.yarnpkg.com/table/-/table-6.6.0.tgz#905654b79df98d9e9a973de1dd58682532c40e8e" + integrity sha512-iZMtp5tUvcnAdtHpZTWLPF0M7AgiQsURR2DwmxnJwSy8I3+cY+ozzVvYha3BOLG2TB+L0CqjIz+91htuj6yCXg== dependencies: ajv "^8.0.1" lodash.clonedeep "^4.5.0" @@ -12576,9 +12588,9 @@ terminal-link@^3.0.0: supports-hyperlinks "^2.2.0" terser@^5.2.1: - version "5.6.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.6.1.tgz#a48eeac5300c0a09b36854bf90d9c26fb201973c" - integrity sha512-yv9YLFQQ+3ZqgWCUk+pvNJwgUTdlIxUk1WTN+RnaFJe2L7ipG2csPT0ra2XRm7Cs8cxN7QXmK1rFzEwYEQkzXw== + version "5.7.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.7.0.tgz#a761eeec206bc87b605ab13029876ead938ae693" + integrity sha512-HP5/9hp2UaZt5fYkuhNBR8YyRcT8juw8+uFbAme53iN9hblvKnLUTKkmwJG6ocWpIKf8UK4DoeWG4ty0J6S6/g== dependencies: commander "^2.20.0" source-map "~0.7.2" @@ -12843,11 +12855,6 @@ tslib@~2.0.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c" integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ== -tslib@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" - integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== - tsutils@^3.17.1: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -13431,6 +13438,11 @@ validate-npm-package-name@^3.0.0: dependencies: builtins "^1.0.3" +value-or-promise@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.6.tgz#218aa4794aa2ee24dcf48a29aba4413ed584747f" + integrity sha512-9r0wQsWD8z/BxPOvnwbPf05ZvFngXyouE9EKB+5GbYix+BYnAwrIChCUyFIinfbf2FL/U71z+CPpbnmTdxrwBg== + vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" From b7aeb232db43b32cae0bca3fcb74479d6834c587 Mon Sep 17 00:00:00 2001 From: Charles Date: Mon, 3 May 2021 10:55:03 +1000 Subject: [PATCH 2/2] File field type (#5529) * file-field init * wip tests * tests * remove log * ammendments to naming logic * fix tests * add docs * fix package deps * convert createItem calls to createOne * revert to sindresorhus/slugify 1.1.0 * fix wrong case for config docs title * update slugify dep again * yarn.lock * remove log and unnecessary code * rename repo field move it away from first member in object * remove schema.graphql and schema.prisma frm exmaples-next basic * rearrange fied exports from field in alphabetical order * make error more explicit * Update packages-next/keystone/src/lib/context/createFilesContext.ts woopsies Co-authored-by: Mitchell Hamilton * remove file type check * remove file-type and filetype check from file field * leverage graphqlUploadExpress to declare max filesize * move maxFileSize config to server config, rater than file * remove slugify and add filenamify to deps * use filenamify rather than slugify for filename transform, stream file to writable stream rather than collecting chunks in memory * update docs and defaults, remove comments, update deps * Cosmetic changes * Simplify code * add a way for us to observe stream errors and delete on error * revert maxFileSize addition to config * add changesets * add beforeEach and afterEach hooks to remaining test files * remove maxSize from type * change comments for file types * throw unwrapped error * Update packages-next/keystone/src/lib/context/createFilesContext.ts Co-authored-by: Mitchell Hamilton * Update packages-next/keystone/src/lib/context/createFilesContext.ts Co-authored-by: Mitchell Hamilton * simplify directory creation logic in generateAdminUI * Update docs/pages/apis/fields.mdx Co-authored-by: Tim Leslie * rename fle field attachment in basic example schema * add transformFilename to config, refactor generateSafefilename to include this and id generation changes * change button to say copy ref and paste ref * update ref shape to explicitly include field type * fix ref in test-fixture file * replace mode with gql interface * fix implementation gql typo * make casing consistent in field * omit path separators * Wait for the write stream to close, not the read stream to end Co-authored-by: Mitchell Hamilton Co-authored-by: Tim Leslie --- .changeset/afraid-maps-brake.md | 5 + .changeset/dirty-bananas-lay.md | 5 + .changeset/silent-stingrays-check.md | 5 + .changeset/six-dodos-wink.md | 5 + .gitignore | 1 + docs/pages/apis/config.mdx | 28 ++ docs/pages/apis/fields.mdx | 28 +- examples/basic/keystone.ts | 1 + examples/basic/schema.ts | 3 + .../admin-ui/src/system/generateAdminUI.ts | 13 +- packages-next/fields/src/index.ts | 15 +- .../fields/src/types/file/Implementation.ts | 277 ++++++++------- packages-next/fields/src/types/file/index.ts | 25 +- .../fields/src/types/file/local-file.ts | 96 ------ .../test-files/{graphql.jpeg => graphql.jpg} | Bin .../src/types/file/test-files/keystone.jpg | Bin 0 -> 3250 bytes .../src/types/file/test-files/keystone.txt | Bin 0 -> 3250 bytes .../file/test-files/{react.jpeg => react.jpg} | Bin .../{thinkmill.jpeg => thinkmill.jpg} | Bin .../{thinkmill1.jpeg => thinkmill1.jpg} | Bin .../{thinkmill2.jpeg => thinkmill2.jpg} | Bin .../src/types/file/test-fixtures.skip.ts | 95 ----- .../src/types/file/tests/test-fixtures.ts | 225 ++++++++++++ .../fields/src/types/file/views/Field.tsx | 325 ++++++++++++++++++ .../fields/src/types/file/views/index.tsx | 119 +++++++ .../fields/src/types/image/views/Field.tsx | 7 +- .../fields/types/file/views/package.json | 4 + packages-next/keystone/package.json | 1 + .../keystone/src/lib/context/createContext.ts | 8 +- .../src/lib/context/createFilesContext.ts | 96 ++++++ .../keystone/src/lib/createSystem.ts | 1 + packages-next/types/src/config/index.ts | 22 +- packages-next/types/src/context.ts | 17 + packages/utils/src/index.ts | 20 +- tests/api-tests/fields/crud.test.ts | 22 ++ tests/api-tests/fields/filter.test.ts | 21 ++ tests/api-tests/fields/required.test.ts | 11 + tests/api-tests/fields/unique.test.ts | 11 + tests/api-tests/fields/unsupported.test.ts | 11 + yarn.lock | 28 ++ 40 files changed, 1209 insertions(+), 342 deletions(-) create mode 100644 .changeset/afraid-maps-brake.md create mode 100644 .changeset/dirty-bananas-lay.md create mode 100644 .changeset/silent-stingrays-check.md create mode 100644 .changeset/six-dodos-wink.md delete mode 100644 packages-next/fields/src/types/file/local-file.ts rename packages-next/fields/src/types/file/test-files/{graphql.jpeg => graphql.jpg} (100%) create mode 100644 packages-next/fields/src/types/file/test-files/keystone.jpg create mode 100644 packages-next/fields/src/types/file/test-files/keystone.txt rename packages-next/fields/src/types/file/test-files/{react.jpeg => react.jpg} (100%) rename packages-next/fields/src/types/file/test-files/{thinkmill.jpeg => thinkmill.jpg} (100%) rename packages-next/fields/src/types/file/test-files/{thinkmill1.jpeg => thinkmill1.jpg} (100%) rename packages-next/fields/src/types/file/test-files/{thinkmill2.jpeg => thinkmill2.jpg} (100%) delete mode 100644 packages-next/fields/src/types/file/test-fixtures.skip.ts create mode 100644 packages-next/fields/src/types/file/tests/test-fixtures.ts create mode 100644 packages-next/fields/src/types/file/views/Field.tsx create mode 100644 packages-next/fields/src/types/file/views/index.tsx create mode 100644 packages-next/fields/types/file/views/package.json create mode 100644 packages-next/keystone/src/lib/context/createFilesContext.ts diff --git a/.changeset/afraid-maps-brake.md b/.changeset/afraid-maps-brake.md new file mode 100644 index 00000000000..02190c03b17 --- /dev/null +++ b/.changeset/afraid-maps-brake.md @@ -0,0 +1,5 @@ +--- +'@keystone-next/admin-ui': minor +--- + +Added symlink logic for file storage. diff --git a/.changeset/dirty-bananas-lay.md b/.changeset/dirty-bananas-lay.md new file mode 100644 index 00000000000..dd3b79ca47b --- /dev/null +++ b/.changeset/dirty-bananas-lay.md @@ -0,0 +1,5 @@ +--- +'@keystone-next/fields': minor +--- + +Added file field type. diff --git a/.changeset/silent-stingrays-check.md b/.changeset/silent-stingrays-check.md new file mode 100644 index 00000000000..a0f29ad23ca --- /dev/null +++ b/.changeset/silent-stingrays-check.md @@ -0,0 +1,5 @@ +--- +'@keystone-next/utils-legacy': minor +--- + +Added `getFileRef` and `parseFileRef` to exported utilities. diff --git a/.changeset/six-dodos-wink.md b/.changeset/six-dodos-wink.md new file mode 100644 index 00000000000..c32b58cdfcb --- /dev/null +++ b/.changeset/six-dodos-wink.md @@ -0,0 +1,5 @@ +--- +'@keystone-next/api-tests-legacy': minor +--- + +Added beforeEach and afterEach hooks to test suite, added file config defaults. diff --git a/.gitignore b/.gitignore index c846e5f5086..bcda7e38dcb 100644 --- a/.gitignore +++ b/.gitignore @@ -89,6 +89,7 @@ dist/ # Used by the image field type tests as a storage target tmp_test_images/ +tmp_test_files/ # Created by https://www.gitignore.io/api/vim # Edit at https://www.gitignore.io/?templates=vim diff --git a/docs/pages/apis/config.mdx b/docs/pages/apis/config.mdx index 4d2dc51eade..7e19de52569 100644 --- a/docs/pages/apis/config.mdx +++ b/docs/pages/apis/config.mdx @@ -253,6 +253,34 @@ export default config({ See the [schema extension guide](../guides/schema-extension) for more details on how to use `graphQLSchemaExtension()` to extend your GraphQL API. +## files + +Keystone supports file handling via the [`file`](./fields#file) field type. +In order to use this field type you need to configure Keystone with information about where your files will be stored and served from. +At the moment Keystone supports storing files on the local filesystem, and is agnostic about how files are served. + +```typescript +import { config } from '@keystone-next/keystone/schema'; + +export default config({ + files: { + upload: 'local', + local: { + storagePath: 'public/files', + baseUrl: '/files', + }, + } + /* ... */ +}); +``` + +Options: + +- `upload`: The storage target when uploading files. Currently only `local` is supported. +- `local`: Configuration options when using the `local` storage target. + - `storagePath`: The path local files are uploaded to. + - `baseUrl`: The base of the URL local files will be served from, outside of keystone. + ## images Keystone supports image handling via the [`image`](./fields#image) field type. diff --git a/docs/pages/apis/fields.mdx b/docs/pages/apis/fields.mdx index 45a68cb5427..4bcb91bb787 100644 --- a/docs/pages/apis/fields.mdx +++ b/docs/pages/apis/fields.mdx @@ -551,7 +551,33 @@ File types allow you to upload different types of files to your Keystone system. ### file -(coming soon) +A `file` field represents a file of any type. + +See [`config.files`](./config#files) for details on how to configure your Keystone system with support for the `file` field type. + +Options: + +- `isRequired` (default: `false`): If `true` then this field can never be set to `null`. + +```typescript +import { config, createSchema, list } from '@keystone-next/keystone/schema'; +import { file } from '@keystone-next/fields'; + +export default config({ + lists: createSchema({ + ListName: list({ + fields: { + repo: file({ + isRequired: true, + }), + /* ... */ + }, + }), + /* ... */ + }), + /* ... */ +}); +``` ### image diff --git a/examples/basic/keystone.ts b/examples/basic/keystone.ts index adab06d2630..00f9b50d502 100644 --- a/examples/basic/keystone.ts +++ b/examples/basic/keystone.ts @@ -37,6 +37,7 @@ export default auth.withAuth( // isAccessAllowed, }, images: { upload: 'local' }, + files: { upload: 'local' }, lists, extendGraphqlSchema, session: withItemData( diff --git a/examples/basic/schema.ts b/examples/basic/schema.ts index c90a33b141c..b11974bf3eb 100644 --- a/examples/basic/schema.ts +++ b/examples/basic/schema.ts @@ -8,6 +8,7 @@ import { select, virtual, image, + file, } from '@keystone-next/fields'; import { document } from '@keystone-next/fields-document'; // import { cloudinaryImage } from '@keystone-next/cloudinary'; @@ -43,7 +44,9 @@ export const lists = createSchema({ name: text({ isRequired: true }), /** Email is used to log into the system. */ email: text({ isRequired: true, isUnique: true }), + /** Avatar upload for the users profile, stored locally */ avatar: image(), + attachment: file(), /** Used to log in. */ password: password(), /** Administrators have more access to various lists and fields. */ diff --git a/packages-next/admin-ui/src/system/generateAdminUI.ts b/packages-next/admin-ui/src/system/generateAdminUI.ts index d197425b9c0..525d0ce11cb 100644 --- a/packages-next/admin-ui/src/system/generateAdminUI.ts +++ b/packages-next/admin-ui/src/system/generateAdminUI.ts @@ -52,15 +52,24 @@ export const generateAdminUI = async ( ) => { // Nuke any existing files in our target directory await fs.remove(projectAdminPath); + const publicDirectory = Path.join(projectAdminPath, 'public'); - if (config.images) { - const publicDirectory = Path.join(projectAdminPath, 'public'); + if (config.images || config.files) { await fs.mkdir(publicDirectory, { recursive: true }); + } + + if (config.images) { const storagePath = Path.resolve(config.images.local?.storagePath ?? './public/images'); await fs.mkdir(storagePath, { recursive: true }); await fs.symlink(storagePath, Path.join(publicDirectory, 'images'), 'junction'); } + if (config.files) { + const storagePath = Path.resolve(config.files.local?.storagePath ?? './public/files'); + await fs.mkdir(storagePath, { recursive: true }); + await fs.symlink(storagePath, Path.join(publicDirectory, 'files'), 'junction'); + } + // Write out the files configured by the user const userPages = config.ui?.getAdditionalFiles?.map(x => x(config)) ?? []; const userFilesToWrite = (await Promise.all(userPages)).flat(); diff --git a/packages-next/fields/src/index.ts b/packages-next/fields/src/index.ts index c10d5c6e760..28299dac720 100644 --- a/packages-next/fields/src/index.ts +++ b/packages-next/fields/src/index.ts @@ -1,14 +1,15 @@ +export { autoIncrement } from './types/autoIncrement'; export { checkbox } from './types/checkbox'; +export { decimal } from './types/decimal'; +export { file } from './types/file'; +export { float } from './types/float'; +export { integer } from './types/integer'; +export { image } from './types/image'; +export { password } from './types/password'; export { relationship } from './types/relationship'; +export { select } from './types/select'; export { text } from './types/text'; -export { password } from './types/password'; export { timestamp } from './types/timestamp'; -export { integer } from './types/integer'; -export { float } from './types/float'; -export { decimal } from './types/decimal'; -export { autoIncrement } from './types/autoIncrement'; -export { select } from './types/select'; export { virtual } from './types/virtual'; export { Implementation } from './Implementation'; export type { FieldConfigArgs, FieldExtraArgs } from './Implementation'; -export { image } from './types/image'; diff --git a/packages-next/fields/src/types/file/Implementation.ts b/packages-next/fields/src/types/file/Implementation.ts index 7b377984a27..0ff6f4eb7af 100644 --- a/packages-next/fields/src/types/file/Implementation.ts +++ b/packages-next/fields/src/types/file/Implementation.ts @@ -1,156 +1,113 @@ -import cuid from 'cuid'; import { FileUpload } from 'graphql-upload'; import { PrismaFieldAdapter, PrismaListAdapter } from '@keystone-next/adapter-prisma-legacy'; -import { BaseKeystoneList } from '@keystone-next/types'; -import { FieldConfigArgs, FieldExtraArgs, Implementation } from '../../Implementation'; -import { LocalFileAdapter } from './local-file'; - -type StoredFile = { - id: string; - filename: string; - originalFilename: string; - mimetype: any; - encoding: any; - _meta?: Record; -}; - -export class File

extends Implementation

{ - graphQLOutputType: string; - fileAdapter: LocalFileAdapter; +import { getFileRef } from '@keystone-next/utils-legacy'; +import { FileData, KeystoneContext, BaseKeystoneList } from '@keystone-next/types'; +import { Implementation } from '../../Implementation'; - constructor( - path: P, - { adapter, ...configArgs }: FieldConfigArgs & { adapter: LocalFileAdapter }, - extraArgs: FieldExtraArgs - ) { - super(path, { adapter, ...configArgs }, extraArgs); - this.graphQLOutputType = 'File'; - this.fileAdapter = adapter; +const MISSING_CONFIG_ERROR = + 'File context is undefined, this most likely means that you havent configurd keystone with a file config, see https://next.keystonejs.com/apis/config#files for details'; - if (!this.fileAdapter) { - throw new Error(`No file adapter provided for File field.`); - } - } +export class FileImplementation

extends Implementation

{ get _supportsUnique() { return false; } gqlOutputFields() { - return [`${this.path}: ${this.graphQLOutputType}`]; - } - gqlQueryInputFields() { - return [...this.equalityInputFields('String'), ...this.inInputFields('String')]; - } - getFileUploadType() { - return 'Upload'; + return [`${this.path}: FileFieldOutput`]; } + getGqlAuxTypes() { return [ ` - type ${this.graphQLOutputType} { - id: ID - path: String - filename: String - originalFilename: String - mimetype: String - encoding: String - publicUrl: String + input FileFieldInput { + upload: Upload + ref: String + } + interface FileFieldOutput { + filename: String! + filesize: Int! + ref: String! + src: String! } - `, + type LocalFileFieldOutput implements FileFieldOutput { + filename: String! + filesize: Int! + ref: String! + src: String! + }`, ]; } - // Called on `User.avatar` for example - gqlOutputFieldResolvers() { - return { - [this.path]: (item: Record) => { - let itemValues = item[this.path]; - if (!itemValues) { - return null; - } - if (this.adapter.listAdapter.parentAdapter.provider === 'sqlite') { - // we store document data as a string on sqlite because Prisma doesn't support Json on sqlite - // https://github.com/prisma/prisma/issues/3786 - try { - itemValues = JSON.parse(itemValues); - } catch (err) {} - } - return { - publicUrl: this.fileAdapter.publicUrl(itemValues), - ...itemValues, - }; + gqlAuxFieldResolvers() { + return { + FileFieldOutput: { + __resolveType() { + return 'LocalFileFieldOutput'; + }, + }, + LocalFileFieldOutput: { + src(data: FileData, _args: any, context: KeystoneContext) { + if (!context.files) { + throw new Error(MISSING_CONFIG_ERROR); + } + return context.files.getSrc(data.mode, data.filename); + }, + ref(data: FileData, _args: any, context: KeystoneContext) { + if (!context.files) { + throw new Error(MISSING_CONFIG_ERROR); + } + return getFileRef(data.mode, data.filename); + }, }, }; } + // Called on `User.avatar` for example + gqlOutputFieldResolvers() { + return { [`${this.path}`]: (item: Record) => item[this.path] }; + } async resolveInput({ resolvedData, - existingItem, + context, }: { - resolvedData: Record; - existingItem?: Record; + resolvedData: Record; + context: KeystoneContext; }) { - const previousData = existingItem && existingItem[this.path]; - const uploadData = resolvedData[this.path]; - - // NOTE: The following two conditions could easily be combined into a - // single `if (!uploadData) return uploadData`, but that would lose the - // nuance of returning `undefined` vs `null`. - // Premature Optimisers; be ware! - if (typeof uploadData === 'undefined') { - // Nothing was passed in, so we can bail early. + const data = resolvedData[this.path]; + if (data === null) { + return null; + } + if (data === undefined) { return undefined; } - if (uploadData === null) { - // `null` was specifically uploaded, and we should set the field value to - // null. To do that we... return `null` - return null; + type FileInput = { + upload?: Promise | null; + ref?: string | null; + }; + const { ref, upload }: FileInput = data; + if (ref) { + if (upload) { + throw new Error('Only one of ref and upload can be passed to FileFieldInput'); + } + return context.files!.getDataFromRef(ref); } - - const { createReadStream, filename: originalFilename, mimetype, encoding } = await uploadData; - const stream = createReadStream(); - - if (!stream && previousData) { - // TODO: FIXME: Handle when stream is null. Can happen when: - // Updating some other part of the item, but not the file (gets null - // because no File DOM element is uploaded) - return previousData; + if (!upload) { + throw new Error('Either ref or upload must be passed to FileFieldInput'); } - const { id, filename } = await this.fileAdapter.save({ - stream, - filename: originalFilename, - id: cuid(), - }); - - const ret = { id, filename, originalFilename, mimetype, encoding, _meta: undefined }; - if (this.adapter.listAdapter.parentAdapter.provider === 'sqlite') { - // we store document data as a string on sqlite because Prisma doesn't support Json on sqlite - // https://github.com/prisma/prisma/issues/3786 - return JSON.stringify(ret); - } - return ret; + const uploadedFile = await upload; + return context.files!.getDataFromStream(uploadedFile.createReadStream(), uploadedFile.filename); } gqlUpdateInputFields() { - return [`${this.path}: ${this.getFileUploadType()}`]; + return [`${this.path}: FileFieldInput`]; } gqlCreateInputFields() { - return [`${this.path}: ${this.getFileUploadType()}`]; + return [`${this.path}: FileFieldInput`]; } getBackingTypes() { - const type = `null | { - id: string; - path: string; - filename: string; - originalFilename: string; - mimetype: string; - encoding: string; - _meta: Record - } - `; - return { [this.path]: { optional: true, type } }; + return { [this.path]: { optional: true, type: 'Record | null' } }; } } @@ -158,7 +115,7 @@ export class PrismaFileInterface

extends PrismaFieldAdapter

constructor( fieldName: string, path: P, - field: File

, + field: FileImplementation

, listAdapter: PrismaListAdapter, getListByKey: (arg: string) => BaseKeystoneList | undefined, config = {} @@ -167,25 +124,89 @@ export class PrismaFileInterface

extends PrismaFieldAdapter

// Error rather than ignoring invalid config // We totally can index these values, it's just not trivial. See issue #1297 if (this.config.isIndexed) { - throw ( + throw new Error( `The File field type doesn't support indexes on Prisma. ` + - `Check the config for ${this.path} on the ${this.field.listKey} list` + `Check the config for ${this.path} on the ${this.field.listKey} list` ); } } + getPrismaSchema() { - // we store document data as a string on sqlite because Prisma doesn't support Json on sqlite - // https://github.com/prisma/prisma/issues/3786 return [ - this._schemaField({ - type: this.listAdapter.parentAdapter.provider === 'sqlite' ? 'String' : 'Json', - }), + `${this.path}_filesize Int?`, + `${this.path}_mode String?`, + `${this.path}_filename String?`, ]; } - getQueryConditions(dbPath: string) { - return { - ...this.equalityConditions(dbPath), - ...this.inConditions(dbPath), - }; + + getQueryConditions() { + return {}; + } + + setupHooks({ + addPreSaveHook, + addPostReadHook, + }: { + addPreSaveHook: (hook: any) => void; + addPostReadHook: (hook: any) => void; + }) { + const field_path = this.path; + const filesize_field = `${this.path}_filesize`; + const mode_field = `${this.path}_mode`; + const name_field = `${this.path}_filename`; + + addPreSaveHook( + (item: Record): Record => { + if (!Object.prototype.hasOwnProperty.call(item, field_path)) { + return item; + } + if (item[field_path as P] === null) { + // If the property exists on the field but is null or falsey + // all split fields are null + // delete the original field item + // return the item + const newItem = { + [filesize_field]: null, + [name_field]: null, + [mode_field]: null, + ...item, + }; + delete newItem[field_path]; + return newItem; + } else { + const { mode, filesize, filename } = item[field_path]; + + const newItem = { + [filesize_field]: filesize, + [name_field]: filename, + [mode_field]: mode, + ...item, + }; + + delete newItem[field_path]; + + return newItem; + } + } + ); + addPostReadHook( + (item: Record): Record => { + if (!item[filesize_field] || !item[name_field] || !item[mode_field]) { + item[field_path] = null; + return item; + } + item[field_path] = { + filesize: item[filesize_field], + filename: item[name_field], + mode: item[mode_field], + }; + + delete item[filesize_field]; + delete item[name_field]; + delete item[mode_field]; + + return item; + } + ); } } diff --git a/packages-next/fields/src/types/file/index.ts b/packages-next/fields/src/types/file/index.ts index b8d587b8fa1..bdf7f8c481d 100644 --- a/packages-next/fields/src/types/file/index.ts +++ b/packages-next/fields/src/types/file/index.ts @@ -1,7 +1,22 @@ -import { File, PrismaFileInterface } from './Implementation'; +import type { FieldType, BaseGeneratedListTypes } from '@keystone-next/types'; +import { resolveView } from '../../resolve-view'; +import type { FieldConfig } from '../../interfaces'; +import { FileImplementation, PrismaFileInterface } from './Implementation'; -export default { - type: 'File', - implementation: File, - adapter: PrismaFileInterface, +export type FileFieldConfig< + TGeneratedListTypes extends BaseGeneratedListTypes +> = FieldConfig & { + isRequired?: boolean; }; + +export const file = ( + config: FileFieldConfig = {} +): FieldType => ({ + type: { + type: 'File', + implementation: FileImplementation, + adapter: PrismaFileInterface, + }, + config, + views: resolveView('file/views'), +}); diff --git a/packages-next/fields/src/types/file/local-file.ts b/packages-next/fields/src/types/file/local-file.ts deleted file mode 100644 index 9a1bb05ca12..00000000000 --- a/packages-next/fields/src/types/file/local-file.ts +++ /dev/null @@ -1,96 +0,0 @@ -import fs from 'fs'; -import path from 'path'; -// @ts-ignore -import mkdirp from 'mkdirp'; - -export class LocalFileAdapter { - src: string; - path: string; - getFilename: (arg: { id: string; originalFilename: string }) => string; - constructor({ - src, - path: inputPath, - getFilename, - }: { - src: string; - path?: string; - getFilename?: (arg: { id: string; originalFilename: string }) => string; - }) { - this.src = path.resolve(src); - this.path = inputPath || ''; - this.getFilename = getFilename || (({ id, originalFilename }) => `${id}-${originalFilename}`); - - if (!this.src) { - throw new Error('LocalFileAdapter requires a src attribute.'); - } - - if (!this.path) { - this.path = src; - } - - mkdirp.sync(this.src); - } - - /** - * Params: { stream, filename, mimetype, encoding, id } - */ - save({ - stream, - filename: originalFilename, - id, - }: { - stream: fs.ReadStream; - filename: string; - id: string; - }): Promise<{ filename: string; id: string }> { - const filename = this.getFilename({ id, originalFilename }); - if (!filename) { - throw new Error( - 'Custom function LocalFileAdapter.getFilename() returned no or invalid value.' - ); - } - - const filePath = path.join(this.src, filename); - return new Promise((resolve, reject) => - stream - .on('error', error => { - // @ts-ignore - if (stream.truncated) { - // Delete the truncated file - fs.unlinkSync(filePath); - } - reject(error); - }) - .pipe(fs.createWriteStream(filePath)) - .on('error', error => reject(error)) - .on('finish', () => resolve({ filename, id })) - ); - } - - /** - * Deletes the file from disk - * @param file File field data - */ - delete(file?: { filename: string }): Promise { - return new Promise((resolve, reject) => { - if (file) { - fs.unlink(path.join(this.src, file.filename), error => { - if (error) { - reject(error); - } else { - resolve(); - } - }); - } else { - reject(new Error("Missing required argument 'file'.")); - } - }); - } - - /** - * Params: { id, filename } - */ - publicUrl({ filename }: { filename: string }) { - return `${this.path}/${filename}`; - } -} diff --git a/packages-next/fields/src/types/file/test-files/graphql.jpeg b/packages-next/fields/src/types/file/test-files/graphql.jpg similarity index 100% rename from packages-next/fields/src/types/file/test-files/graphql.jpeg rename to packages-next/fields/src/types/file/test-files/graphql.jpg diff --git a/packages-next/fields/src/types/file/test-files/keystone.jpg b/packages-next/fields/src/types/file/test-files/keystone.jpg new file mode 100644 index 0000000000000000000000000000000000000000..01ad6bd6c5932d41db2b2bfada053c2dd42b8b07 GIT binary patch literal 3250 zcmbuBcU)6h7RPTW5}MSgpb!uO2}M-uNHbu7fP&O0DzPEOHXumVATptjC<90@5rlw{ zK`BZx3Q+`6q$}#ui=gz-leZ6ccXoIF+Hyay-1qJ|_jAAR{?0iM`Uv#{acc{r1wbGW zV6#C3z>E;+bpe1QM}Qjq3JDOAUVsnoZCJ=|8u1(ifEVs<`W!@T-v92uF%EqO=0I3b zP+;>A6ok7QO;}J^SVR~;Ma4xVwu){Qk(80d$jV{lWYD{CxNR7HT|HT~{U(~Yy)uT1 zQX7*X1dvGB3neU!(vXvp)A+9&^a4mAK?+FbMeGJV5(r)i1jGVpc;);s@gLCeGY>Bx z{}utHppYE?IXSa*1cS$l3CeH zltbH$vi4cua6zGM+jq#wVpLSII5izzJ$-|p4wxSzSXf#StsR}5T}a1{yPiAme!;`j z%ln$2|Mh^tpy1mPzfdEiqGJ+%OH4|>pOTtJdytp^u%M7$^!Q16MP=2~XVvu$tXHoa z-!wJ1cXW1j_k8@+J1{sjJTf{q{%vA*ZhnEixU{^oy1|72ynn;`gX~XS5-=AJA0IED zzy=qBCtw3yf{$Nu-xf){y}%hCsonc;A*Idk<(9n^RMK{sL7nw&6WXS%Gk}@hK-(ny z&%na}C$c}l{>jw~M0gSK=J84ZQ_xvc^RzCtAcKClh|!#TP-rjUDQ<5kbrX~y#kY>A zs*Gr|^78YFz{X_V7~}4zWPSydSPTsTTL!Qn6m0-Wu140fEWxAqWsEf|3IIXC+J16F$z* zemr(2AGL)o8G|jIZ#8pHKV^FK`Mk+nUTdY-b3$R-AKas)Kid$euP9dD@}1k|v1}jm z1dVr#KjXe7`!cFrX~gYR{PA7vYitM@tH*ASb&|AkX|>_M9Z3CB9%EqoT{MInn$2B{ zg+NRm1R^M87)SLVIBkUt!!-wn`!WPlCn)X?QxFiFGwL6go#9K@13W}8MSy5hzW=Ct zBGjg2C4XVk(!@1kPoCq_N6K4WrQf+)^I5KS89Ec4k-CJ7Stcsd^w#9`x(IlSN}m8) z43>wD(Zu*&R#e!eVGDo*>C`|S z`t&J_5tHjO6&7fJyY&i_v8u7Yc#AsEwn%NG7F|J7w(=28DdH);KEJS?&%(6z1x`;W zIgT5yaSXa?F)Q9l7zbO2ui0m8GrS09h6<$tEZ3e-5|1vEIcfyXBz<(p=MNAFxT%57My&Z_6N7qabD_igOUl!38|L3;}Dn=?qE)aLqMA}L5+ui zLY*P^sn)#i&F3zRS=b;jn~~i=-j60XCHt-?u$OXU>k*D)sD43&P~G{ zI6sCN04JBlncfCet$HOkQ7wMLjy~&eJ3z&wnU#7>sTG+zaif*Ot?-Jd zub!*{yt?T>zFPB4>z`3XCx8RIuN`fv%4SIc=Kj>2mY zUjSdCO3e8(f{{am8ugCTd4Jto~ zOKiZh?Izx8dY9*%RdZC>6L{$dhZBxy`rK6PzS;T1{Zij}TO|e-k7lMFp8JMF5$X^# za~^AsVht)qMr!xv_VOV4#PKqGehO_T8>tmn_mOO$Ud`OjLB-E1Ov)_D)jiKxVCxn( z$9++D7Mf-78zizdO++oaZGsH0)=8%{-NCmp8`p>4U%5P1o^>Lq=Tezow_N5iw79!t8dFHeoJ_~;;XK87B0&v^NJlav#)~?p>@{tc9@J7oP0;R(1 z@5n{6rt9Gg)2sc=maf$mS0?LzvB^Z_%!6^}?w!o#g<1$Of|v`uZfD%G1K^;#pUs}u z=Z0NuQSW(cA|tQjGiyGoX85{k_db$^NL&H`v0dS!!Q0}CR0=NbxVz_U{TBuH_x@n? ze0%Lw$+xABZ$0*34h5n$=)G1=BX$d=EpBooYI?~XjcvGrvC`IS?c;?dr3y9S>QOuW zd`m}+8_$Y89rt!!Nlv@&(fu&3`X?rAQ%>zDm_Lgizg9L^vvRrfwH;i6CP_8-2cO-4oW&6n*jw+*yeL|oLX8ncea|xZ zfAbA>nrp0OI{BBY9MF?OD)84FlYV)f zc@0zhKq0iv#N@b=Diz&L@5%RGJ$WFX9yQ<*uX$B0;Z8%P6Gs3E|)QuWe?dtWSQ-iZmz|@Nh@H!yZ_?}us9dbIpRbL`y|+?{33^-OYQ-Ds^b)d0N<im(icMnlgwh@^?pmPf1L)KOw`9k#-g_ClXKuMcDD2nS(uHe?%TF zhIW@4gMGLUhou!hFt=-C%N@alILAFYED`(E&FVe;Q=neY8k%S?##(e+K8t+OPAA%u JYD}R|e+3ja^(6oR literal 0 HcmV?d00001 diff --git a/packages-next/fields/src/types/file/test-files/keystone.txt b/packages-next/fields/src/types/file/test-files/keystone.txt new file mode 100644 index 0000000000000000000000000000000000000000..01ad6bd6c5932d41db2b2bfada053c2dd42b8b07 GIT binary patch literal 3250 zcmbuBcU)6h7RPTW5}MSgpb!uO2}M-uNHbu7fP&O0DzPEOHXumVATptjC<90@5rlw{ zK`BZx3Q+`6q$}#ui=gz-leZ6ccXoIF+Hyay-1qJ|_jAAR{?0iM`Uv#{acc{r1wbGW zV6#C3z>E;+bpe1QM}Qjq3JDOAUVsnoZCJ=|8u1(ifEVs<`W!@T-v92uF%EqO=0I3b zP+;>A6ok7QO;}J^SVR~;Ma4xVwu){Qk(80d$jV{lWYD{CxNR7HT|HT~{U(~Yy)uT1 zQX7*X1dvGB3neU!(vXvp)A+9&^a4mAK?+FbMeGJV5(r)i1jGVpc;);s@gLCeGY>Bx z{}utHppYE?IXSa*1cS$l3CeH zltbH$vi4cua6zGM+jq#wVpLSII5izzJ$-|p4wxSzSXf#StsR}5T}a1{yPiAme!;`j z%ln$2|Mh^tpy1mPzfdEiqGJ+%OH4|>pOTtJdytp^u%M7$^!Q16MP=2~XVvu$tXHoa z-!wJ1cXW1j_k8@+J1{sjJTf{q{%vA*ZhnEixU{^oy1|72ynn;`gX~XS5-=AJA0IED zzy=qBCtw3yf{$Nu-xf){y}%hCsonc;A*Idk<(9n^RMK{sL7nw&6WXS%Gk}@hK-(ny z&%na}C$c}l{>jw~M0gSK=J84ZQ_xvc^RzCtAcKClh|!#TP-rjUDQ<5kbrX~y#kY>A zs*Gr|^78YFz{X_V7~}4zWPSydSPTsTTL!Qn6m0-Wu140fEWxAqWsEf|3IIXC+J16F$z* zemr(2AGL)o8G|jIZ#8pHKV^FK`Mk+nUTdY-b3$R-AKas)Kid$euP9dD@}1k|v1}jm z1dVr#KjXe7`!cFrX~gYR{PA7vYitM@tH*ASb&|AkX|>_M9Z3CB9%EqoT{MInn$2B{ zg+NRm1R^M87)SLVIBkUt!!-wn`!WPlCn)X?QxFiFGwL6go#9K@13W}8MSy5hzW=Ct zBGjg2C4XVk(!@1kPoCq_N6K4WrQf+)^I5KS89Ec4k-CJ7Stcsd^w#9`x(IlSN}m8) z43>wD(Zu*&R#e!eVGDo*>C`|S z`t&J_5tHjO6&7fJyY&i_v8u7Yc#AsEwn%NG7F|J7w(=28DdH);KEJS?&%(6z1x`;W zIgT5yaSXa?F)Q9l7zbO2ui0m8GrS09h6<$tEZ3e-5|1vEIcfyXBz<(p=MNAFxT%57My&Z_6N7qabD_igOUl!38|L3;}Dn=?qE)aLqMA}L5+ui zLY*P^sn)#i&F3zRS=b;jn~~i=-j60XCHt-?u$OXU>k*D)sD43&P~G{ zI6sCN04JBlncfCet$HOkQ7wMLjy~&eJ3z&wnU#7>sTG+zaif*Ot?-Jd zub!*{yt?T>zFPB4>z`3XCx8RIuN`fv%4SIc=Kj>2mY zUjSdCO3e8(f{{am8ugCTd4Jto~ zOKiZh?Izx8dY9*%RdZC>6L{$dhZBxy`rK6PzS;T1{Zij}TO|e-k7lMFp8JMF5$X^# za~^AsVht)qMr!xv_VOV4#PKqGehO_T8>tmn_mOO$Ud`OjLB-E1Ov)_D)jiKxVCxn( z$9++D7Mf-78zizdO++oaZGsH0)=8%{-NCmp8`p>4U%5P1o^>Lq=Tezow_N5iw79!t8dFHeoJ_~;;XK87B0&v^NJlav#)~?p>@{tc9@J7oP0;R(1 z@5n{6rt9Gg)2sc=maf$mS0?LzvB^Z_%!6^}?w!o#g<1$Of|v`uZfD%G1K^;#pUs}u z=Z0NuQSW(cA|tQjGiyGoX85{k_db$^NL&H`v0dS!!Q0}CR0=NbxVz_U{TBuH_x@n? ze0%Lw$+xABZ$0*34h5n$=)G1=BX$d=EpBooYI?~XjcvGrvC`IS?c;?dr3y9S>QOuW zd`m}+8_$Y89rt!!Nlv@&(fu&3`X?rAQ%>zDm_Lgizg9L^vvRrfwH;i6CP_8-2cO-4oW&6n*jw+*yeL|oLX8ncea|xZ zfAbA>nrp0OI{BBY9MF?OD)84FlYV)f zc@0zhKq0iv#N@b=Diz&L@5%RGJ$WFX9yQ<*uX$B0;Z8%P6Gs3E|)QuWe?dtWSQ-iZmz|@Nh@H!yZ_?}us9dbIpRbL`y|+?{33^-OYQ-Ds^b)d0N<im(icMnlgwh@^?pmPf1L)KOw`9k#-g_ClXKuMcDD2nS(uHe?%TF zhIW@4gMGLUhou!hFt=-C%N@alILAFYED`(E&FVe;Q=neY8k%S?##(e+K8t+OPAA%u JYD}R|e+3ja^(6oR literal 0 HcmV?d00001 diff --git a/packages-next/fields/src/types/file/test-files/react.jpeg b/packages-next/fields/src/types/file/test-files/react.jpg similarity index 100% rename from packages-next/fields/src/types/file/test-files/react.jpeg rename to packages-next/fields/src/types/file/test-files/react.jpg diff --git a/packages-next/fields/src/types/file/test-files/thinkmill.jpeg b/packages-next/fields/src/types/file/test-files/thinkmill.jpg similarity index 100% rename from packages-next/fields/src/types/file/test-files/thinkmill.jpeg rename to packages-next/fields/src/types/file/test-files/thinkmill.jpg diff --git a/packages-next/fields/src/types/file/test-files/thinkmill1.jpeg b/packages-next/fields/src/types/file/test-files/thinkmill1.jpg similarity index 100% rename from packages-next/fields/src/types/file/test-files/thinkmill1.jpeg rename to packages-next/fields/src/types/file/test-files/thinkmill1.jpg diff --git a/packages-next/fields/src/types/file/test-files/thinkmill2.jpeg b/packages-next/fields/src/types/file/test-files/thinkmill2.jpg similarity index 100% rename from packages-next/fields/src/types/file/test-files/thinkmill2.jpeg rename to packages-next/fields/src/types/file/test-files/thinkmill2.jpg diff --git a/packages-next/fields/src/types/file/test-fixtures.skip.ts b/packages-next/fields/src/types/file/test-fixtures.skip.ts deleted file mode 100644 index c4627068c82..00000000000 --- a/packages-next/fields/src/types/file/test-fixtures.skip.ts +++ /dev/null @@ -1,95 +0,0 @@ -import fs from 'fs'; -import path from 'path'; -// @ts-ignore -import { Upload } from 'graphql-upload'; -import mime from 'mime'; -import { ProviderName } from '@keystone-next/test-utils-legacy'; -import { LocalFileAdapter } from './local-file'; -import File from './'; - -export const name = 'File'; -export const type = File; -export const supportsUnique = false; -export const fieldName = 'image'; -export const subfieldName = 'originalFilename'; - -// Grab all the image files from the directory -const directory = './files'; - -const prepareFile = (_filePath: string) => { - const filePath = path.resolve(`packages/fields/src/types/File/test-files/${_filePath}`); - const upload = new Upload(); - upload.resolve({ - createReadStream: () => fs.createReadStream(filePath), - filename: path.basename(filePath), - // @ts-ignore - mimetype: mime.getType(filePath), - encoding: 'utf-8', - }); - return upload; -}; - -export const exampleValue = () => prepareFile('graphql.jpeg'); -export const exampleValue2 = () => prepareFile('keystone.jpeg'); -export const createReturnedValue = exampleValue().file.filename; -export const updateReturnedValue = exampleValue2().file.filename; - -const fileAdapter = new LocalFileAdapter({ src: directory, path: '/files' }); - -export const fieldConfig = () => ({ adapter: fileAdapter }); - -export const getTestFields = () => ({ - // name: { type: Text }, - image: { type, adapter: fileAdapter }, -}); - -export const initItems = () => [ - { image: prepareFile('graphql.jpeg'), name: 'file0' }, - { image: prepareFile('keystone.jpeg'), name: 'file1' }, - { image: prepareFile('react.jpeg'), name: 'file2' }, - { image: prepareFile('thinkmill.jpeg'), name: 'file3' }, - { image: prepareFile('thinkmill1.jpeg'), name: 'file4' }, - { image: null, name: 'file5' }, - { image: null, name: 'file6' }, -]; - -export const storedValues = () => [ - { image: { originalFilename: 'graphql.jpeg' }, name: 'file0' }, - { image: { originalFilename: 'keystone.jpeg' }, name: 'file1' }, - { image: { originalFilename: 'react.jpeg' }, name: 'file2' }, - { image: { originalFilename: 'thinkmill.jpeg' }, name: 'file3' }, - { image: { originalFilename: 'thinkmill1.jpeg' }, name: 'file4' }, - { image: null, name: 'file5' }, - { image: null, name: 'file6' }, -]; - -export const beforeAll = () => { - // Ensures 'directory' exist - if (!fs.existsSync(directory)) { - fs.mkdirSync(directory); - } -}; - -// Remove all the files in the './files' directory after all the tests are completed -export const afterAll = (): Promise => { - return new Promise(resolve => { - fs.readdir(directory, (err, files) => { - if (err) throw err; - - for (const file of files) { - fs.unlink(path.join(directory, file), err => { - if (err) { - throw err; - } else { - resolve(); - } - }); - } - }); - }); -}; - -export const supportedFilters = (provider: ProviderName) => [ - 'null_equality', - !['postgresql'].includes(provider) && 'in_empty_null', -]; diff --git a/packages-next/fields/src/types/file/tests/test-fixtures.ts b/packages-next/fields/src/types/file/tests/test-fixtures.ts new file mode 100644 index 00000000000..124a685e497 --- /dev/null +++ b/packages-next/fields/src/types/file/tests/test-fixtures.ts @@ -0,0 +1,225 @@ +import path from 'path'; +import fs from 'fs-extra'; +// @ts-ignore +import { Upload } from 'graphql-upload'; +import mime from 'mime'; +import { text } from '../../text'; +import { file } from '..'; + +const prepareFile = (_filePath: string) => { + const filePath = path.resolve(`packages-next/fields/src/types/file/test-files/${_filePath}`); + const upload = new Upload(); + upload.resolve({ + createReadStream: () => fs.createReadStream(filePath), + filename: path.basename(filePath), + // @ts-ignore + mimetype: mime.getType(filePath), + encoding: 'utf-8', + }); + return { upload }; +}; + +export const name = 'File'; +export const typeFunction = file; + +export const exampleValue = () => prepareFile('keystone.jpg'); +export const exampleValue2 = () => prepareFile('react.jpg'); +export const createReturnedValue = 3250; +export const updateReturnedValue = 5562; + +export const supportsUnique = false; +export const fieldName = 'secretFile'; +export const subfieldName = 'filesize'; + +export const getTestFields = () => ({ name: text(), secretFile: file() }); + +export const afterEach = async () => { + // This matches the storagePath in the keystone config in the various test files. + fs.rmdirSync('tmp_test_files', { recursive: true }); +}; + +export const initItems = () => [ + { secretFile: prepareFile('graphql.jpg'), name: 'file0' }, + { secretFile: prepareFile('keystone.jpg'), name: 'file1' }, + { secretFile: prepareFile('react.jpg'), name: 'file2' }, + { secretFile: prepareFile('thinkmill.jpg'), name: 'file3' }, + { secretFile: prepareFile('thinkmill1.jpg'), name: 'file4' }, + { secretFile: null, name: 'file5' }, + { secretFile: null, name: 'file6' }, +]; + +export const storedValues = () => [ + { secretFile: { filesize: 2759 }, name: 'file0' }, + { secretFile: { filesize: 3250 }, name: 'file1' }, + { secretFile: { filesize: 5562 }, name: 'file2' }, + { secretFile: { filesize: 1028 }, name: 'file3' }, + { secretFile: { filesize: 1028 }, name: 'file4' }, + { secretFile: null, name: 'file5' }, + { secretFile: null, name: 'file6' }, +]; + +export const supportedFilters = () => []; + +export const crudTests = (keystoneTestWrapper: any) => { + describe('Create - upload', () => { + test( + 'upload values should match expected', + keystoneTestWrapper(async ({ context }: { context: any }) => { + const filename = 'keystone.jpeg'; + const data = await context.lists.Test.createOne({ + data: { secretFile: prepareFile(filename) }, + query: ` + secretFile { + filename + __typename + filesize + ref + src + } + `, + }); + expect(data).not.toBe(null); + expect(data.secretFile.ref).toEqual(`local:file:${data.secretFile.filename}`); + expect(data.secretFile.src).toEqual(`/files/${data.secretFile.filename}`); + expect(data.secretFile.filesize).toEqual(3250); + expect(data.secretFile.__typename).toEqual('LocalFileFieldOutput'); + }) + ); + }); + describe('Create - ref', () => { + test( + 'From existing item succeeds', + keystoneTestWrapper(async ({ context }: { context: any }) => { + // Create an initial item + const initialItem = await context.lists.Test.createOne({ + data: { secretFile: prepareFile('keystone.jpg') }, + query: ` + secretFile { + filename + __typename + filesize + ref + src + } + `, + }); + expect(initialItem).not.toBe(null); + + // Create a new item base on the first items ref + const ref = initialItem.secretFile.ref; + const newItem = await context.lists.Test.createOne({ + data: { secretFile: { ref } }, + query: ` + secretFile { + filename + __typename + filesize + ref + src + } + `, + }); + expect(newItem).not.toBe(null); + + // Check that the details of both items match + expect(newItem.secretFile).toEqual(initialItem.secretFile); + }) + ); + test( + 'From invalid ref fails', + keystoneTestWrapper(async ({ context }: { context: any }) => { + const { data, errors } = await context.graphql.raw({ + query: ` + mutation ($item: TestCreateInput) { + createTest(data: $item) { + secretFile { + filename + } + } + } + `, + variables: { item: { secretFile: { ref: 'Invalid ref!' } } }, + }); + expect(data).toEqual({ createTest: null }); + expect(errors).toHaveLength(1); + expect(errors![0].message).toEqual('Invalid file reference'); + }) + ); + test( + 'From null ref fails', + keystoneTestWrapper(async ({ context }: { context: any }) => { + const { data, errors } = await context.graphql.raw({ + query: ` + mutation ($item: TestCreateInput) { + createTest(data: $item) { + secretFile { + filename + } + } + } + `, + variables: { item: { secretFile: { ref: null } } }, + }); + expect(data).toEqual({ createTest: null }); + expect(errors).toHaveLength(1); + expect(errors![0].message).toEqual('Either ref or upload must be passed to FileFieldInput'); + }) + ); + test( + 'Both upload and ref fails - valid ref', + keystoneTestWrapper(async ({ context }: { context: any }) => { + const initialItem = await context.lists.Test.createOne({ + data: { secretFile: prepareFile('keystone.jpg') }, + query: `secretFile { ref }`, + }); + expect(initialItem).not.toBe(null); + + const { data, errors } = await context.graphql.raw({ + query: ` + mutation ($item: TestCreateInput) { + createTest(data: $item) { + secretFile { + filename + } + } + } + `, + variables: { + item: { + secretFile: { ref: initialItem.secretFile.ref, ...prepareFile('keystone.jpg') }, + }, + }, + }); + expect(data).toEqual({ createTest: null }); + expect(errors).toHaveLength(1); + expect(errors![0].message).toEqual( + 'Only one of ref and upload can be passed to FileFieldInput' + ); + }) + ); + test( + 'Both upload and ref fails - invalid ref', + keystoneTestWrapper(async ({ context }: { context: any }) => { + const { data, errors } = await context.graphql.raw({ + query: ` + mutation ($item: TestCreateInput) { + createTest(data: $item) { + secretFile { + filename + } + } + } + `, + variables: { + item: { secretFile: { ref: 'Invalid', ...prepareFile('keystone.jpg') } }, + }, + }); + expect(data).toEqual({ createTest: null }); + expect(errors).toHaveLength(1); + expect(errors![0].message).toEqual( + 'Only one of ref and upload can be passed to FileFieldInput' + ); + }) + ); + }); +}; diff --git a/packages-next/fields/src/types/file/views/Field.tsx b/packages-next/fields/src/types/file/views/Field.tsx new file mode 100644 index 00000000000..e7dd714270f --- /dev/null +++ b/packages-next/fields/src/types/file/views/Field.tsx @@ -0,0 +1,325 @@ +/** @jsx jsx */ +import { Fragment, useMemo, useRef, RefObject } from 'react'; +import copy from 'copy-to-clipboard'; +import bytes from 'bytes'; + +import { jsx, Stack, Text } from '@keystone-ui/core'; +import { useToasts } from '@keystone-ui/toast'; +import { FieldContainer, FieldLabel } from '@keystone-ui/fields'; + +import { TextInput } from '@keystone-ui/fields'; +import { parseFileRef } from '@keystone-next/utils-legacy'; +import { Pill } from '@keystone-ui/pill'; +import { Button } from '@keystone-ui/button'; +import { FieldProps } from '@keystone-next/types'; + +import { FileValue } from './index'; + +export function validateRef({ ref }: { ref: string }) { + if (!parseFileRef(ref)) { + return 'Invalid ref'; + } +} + +const RefView = ({ + onChange, + onCancel, + error, +}: { + onChange: (value: string) => void; + onCancel: () => void; + error?: string; +}) => { + return ( + + { + onChange(event.target.value); + }} + css={{ + width: '100%', + }} + /> + + {error ? ( + + {error} + + ) : null} + + ); +}; + +export function Field({ + autoFocus, + field, + value, + forceValidation, + onChange, +}: FieldProps) { + const inputRef = useRef(null); + + const errorMessage = createErrorMessage(value, forceValidation); + + const onUploadChange = ({ + currentTarget: { validity, files }, + }: React.SyntheticEvent) => { + const file = files?.[0]; + if (!file) return; // bail if the user cancels from the file browser + onChange?.({ + kind: 'upload', + data: { file, validity }, + previous: value, + }); + }; + + // Generate a random input key when the value changes, to ensure the file input is unmounted and + // remounted (this is the only way to reset its value and ensure onChange will fire again if + // the user selects the same file again) + const inputKey = useMemo(() => Math.random(), [value]); + + return ( + + {field.label} + {value.kind === 'ref' ? ( + { + onChange?.({ + kind: 'ref', + data: { ref }, + previous: value.previous, + }); + }} + error={forceValidation && errorMessage ? errorMessage : undefined} + onCancel={() => { + onChange?.(value.previous); + }} + /> + ) : ( + + )} + + + ); +} + +function FileView({ + errorMessage, + value, + onChange, + inputRef, +}: { + errorMessage?: string; + value: Exclude; + onChange?: (value: FileValue) => void; + inputRef: RefObject; +}) { + const { addToast } = useToasts(); + + // const imagePathFromUpload = useObjectURL( + // errorMessage === undefined && value.kind === 'upload' ? value.data.file : undefined + // ); + const onSuccess = () => { + addToast({ title: 'Copied file ref to clipboard', tone: 'positive' }); + }; + const onFailure = () => { + addToast({ title: 'Failed to copy file ref to clipboard', tone: 'negative' }); + }; + + const copyRef = () => { + if (value.kind !== 'from-server') { + return; + } + + if (navigator) { + // use the new navigator.clipboard API if it exists + navigator.clipboard.writeText(value?.data.ref).then(onSuccess, onFailure); + return; + } else { + // Fallback to a library that leverages document.execCommand + // for browser versions that dont' support the navigator object. + // As document.execCommand + try { + copy(value?.data.ref); + } catch (e) { + addToast({ title: 'Faild to oopy to clipboard', tone: 'negative' }); + } + + return; + } + }; + return value.kind === 'from-server' || value.kind === 'upload' ? ( + + {onChange && ( + + {value.kind === 'from-server' && ( + + + + + {`${value.data.filename}`} + + + + + {bytes(value.data.filesize)} + + )} + + + {value.kind !== 'upload' ? ( + + ) : null} + {value.kind === 'from-server' && ( + + )} + {value.kind === 'upload' && ( + + )} + {errorMessage ? ( + + {errorMessage} + + ) : ( + value.kind === 'upload' && ( + + Save to upload this file + + ) + )} + + + )} + + ) : ( + + + + + {value.kind === 'remove' && value.previous && ( + + )} + {value.kind === 'remove' && + // NOTE -- UX decision is to not display this, I think it would only be relevant + // for deleting uploaded images (and we don't support that yet) + // + // Save to remove this image + // + null} + + + ); +} + +function createErrorMessage(value: FileValue, forceValidation?: boolean) { + if (value.kind === 'upload') { + return validateFile(value.data); + } else if (value.kind === 'ref') { + return forceValidation ? validateRef(value.data) : undefined; + } +} + +export function validateFile({ validity }: { validity: ValidityState }): string | undefined { + if (!validity.valid) { + return 'Something went wrong, please reload and try again.'; + } +} diff --git a/packages-next/fields/src/types/file/views/index.tsx b/packages-next/fields/src/types/file/views/index.tsx new file mode 100644 index 00000000000..65e3c52c306 --- /dev/null +++ b/packages-next/fields/src/types/file/views/index.tsx @@ -0,0 +1,119 @@ +/* @jsx jsx */ + +import { jsx } from '@keystone-ui/core'; +import { + CardValueComponent, + CellComponent, + FieldController, + FieldControllerConfig, +} from '@keystone-next/types'; + +import { FieldContainer, FieldLabel } from '@keystone-ui/fields'; +import { validateFile, validateRef } from './Field'; + +export { Field } from './Field'; + +export const Cell: CellComponent = ({ item, field }) => { + const data = item[field.path]; + if (!data) return null; + return ( +

+ {data.filename} +
+ ); +}; + +export const CardValue: CardValueComponent = ({ item, field }) => { + const data = item[field.path]; + return ( + + {field.label} + {data && data.filename} + + ); +}; + +type FileData = { + src: string; + ref: string; + filesize: number; + filename: string; +}; + +export type FileValue = + | { kind: 'empty' } + | { + kind: 'ref'; + data: { + ref: string; + }; + previous: FileValue; + } + | { + kind: 'from-server'; + data: FileData; + } + | { + kind: 'upload'; + data: { + file: File; + validity: ValidityState; + }; + previous: FileValue; + } + | { kind: 'remove'; previous?: Exclude }; + +type FileController = FieldController; + +export const controller = (config: FieldControllerConfig): FileController => { + return { + path: config.path, + label: config.label, + graphqlSelection: `${config.path} { + src + filename + ref + filesize + }`, + defaultValue: { kind: 'empty' }, + deserialize(item) { + const value = item[config.path]; + if (!value) return { kind: 'empty' }; + return { + kind: 'from-server', + data: { + src: value.src, + filename: value.filename, + ref: value.ref, + filesize: value.filesize, + }, + }; + }, + validate(value): boolean { + if (value.kind === 'ref') { + return validateRef(value.data) === undefined; + } + return value.kind !== 'upload' || validateFile(value.data) === undefined; + }, + serialize(value) { + if (value.kind === 'upload') { + return { [config.path]: { upload: value.data.file } }; + } + if (value.kind === 'ref') { + return { [config.path]: { ref: value.data.ref } }; + } + if (value.kind === 'remove') { + return { [config.path]: null }; + } + return {}; + }, + }; +}; diff --git a/packages-next/fields/src/types/image/views/Field.tsx b/packages-next/fields/src/types/image/views/Field.tsx index 0e006209ef3..938677ca1b4 100644 --- a/packages-next/fields/src/types/image/views/Field.tsx +++ b/packages-next/fields/src/types/image/views/Field.tsx @@ -1,12 +1,13 @@ /** @jsx jsx */ +import copy from 'copy-to-clipboard'; +import bytes from 'bytes'; +import { ReactNode, RefObject, useEffect, useMemo, useRef, useState } from 'react'; + import { jsx, Stack, useTheme, Text } from '@keystone-ui/core'; import { useToasts } from '@keystone-ui/toast'; import { TextInput } from '@keystone-ui/fields'; import { parseImageRef } from '@keystone-next/utils-legacy'; -import copy from 'copy-to-clipboard'; -import bytes from 'bytes'; -import { ReactNode, RefObject, useEffect, useMemo, useRef, useState } from 'react'; import { FieldContainer, FieldLabel } from '@keystone-ui/fields'; import { Pill } from '@keystone-ui/pill'; diff --git a/packages-next/fields/types/file/views/package.json b/packages-next/fields/types/file/views/package.json new file mode 100644 index 00000000000..0a2b32cebb5 --- /dev/null +++ b/packages-next/fields/types/file/views/package.json @@ -0,0 +1,4 @@ +{ + "main": "dist/fields.cjs.js", + "module": "dist/fields.esm.js" +} diff --git a/packages-next/keystone/package.json b/packages-next/keystone/package.json index 76f5b226d0e..c10d24dce7f 100644 --- a/packages-next/keystone/package.json +++ b/packages-next/keystone/package.json @@ -60,6 +60,7 @@ "cuid": "^2.1.8", "execa": "^5.0.0", "express": "^4.17.1", + "filenamify": "^4.3.0", "fs-extra": "^9.1.0", "graphql": "^15.5.0", "graphql-type-json": "^0.3.2", diff --git a/packages-next/keystone/src/lib/context/createContext.ts b/packages-next/keystone/src/lib/context/createContext.ts index 86906bd5ea9..29db71d95a8 100644 --- a/packages-next/keystone/src/lib/context/createContext.ts +++ b/packages-next/keystone/src/lib/context/createContext.ts @@ -6,24 +6,29 @@ import type { KeystoneGraphQLAPI, BaseKeystone, ImagesConfig, + FilesConfig, } from '@keystone-next/types'; import { getDbAPIFactory, itemAPIForList } from './itemAPI'; import { accessControlContext, skipAccessControlContext } from './createAccessControlContext'; import { createImagesContext } from './createImagesContext'; +import { createFilesContext } from './createFilesContext'; export function makeCreateContext({ graphQLSchema, internalSchema, keystone, imagesConfig, + filesConfig, }: { graphQLSchema: GraphQLSchema; internalSchema: GraphQLSchema; keystone: BaseKeystone; - imagesConfig?: ImagesConfig; + imagesConfig: ImagesConfig | undefined; + filesConfig: FilesConfig | undefined; }) { const images = createImagesContext(imagesConfig); + const files = createFilesContext(filesConfig); // We precompute these helpers here rather than every time createContext is called // because they involve creating a new GraphQLSchema, creating a GraphQL document AST(programmatically, not by parsing) and validating the // note this isn't as big of an optimisation as you would imagine(at least in comparison with the rest of the system), @@ -94,6 +99,7 @@ export function makeCreateContext({ // We may want to remove it once the updated itemAPI w/ query is available. gqlNames: (listKey: string) => keystone.lists[listKey].gqlNames, images, + files, }; const dbAPIFactories = schemaName === 'public' ? publicDbApiFactories : internalDbApiFactories; for (const listKey of Object.keys(keystone.lists)) { diff --git a/packages-next/keystone/src/lib/context/createFilesContext.ts b/packages-next/keystone/src/lib/context/createFilesContext.ts new file mode 100644 index 00000000000..1efc4f53049 --- /dev/null +++ b/packages-next/keystone/src/lib/context/createFilesContext.ts @@ -0,0 +1,96 @@ +import path from 'path'; +import crypto from 'crypto'; +import filenamify from 'filenamify'; +import { FilesConfig, FilesContext } from '@keystone-next/types'; +import fs from 'fs-extra'; + +import { parseFileRef } from '@keystone-next/utils-legacy'; +import slugify from '@sindresorhus/slugify'; + +const DEFAULT_BASE_URL = '/files'; +const DEFAULT_STORAGE_PATH = './public/files'; + +const defaultTransformer = (str: string) => slugify(str); + +const generateSafeFilename = ( + filename: string, + transformFilename: (str: string) => string = defaultTransformer +) => { + // Appends a UUID to the filename so that people can't brute-force guess stored filenames + // + // This regex lazily matches for any characters that aren't a new line + // it then optionally matches the last instance of a "." symbol + // followed by any alphabetical character before the end of the string + const [, name, ext] = filename.match(/^([^:\n].*?)(\.[A-Za-z]+)?$/) as RegExpMatchArray; + + const id = crypto + .randomBytes(24) + .toString('base64') + .replace(/[^a-zA-Z0-9]/g, '') + .slice(12); + + // console.log(id, id.length, id.slice(12).length); + const urlSafeName = filenamify(transformFilename(name), { + maxLength: 100 - id.length, + replacement: '-', + }); + if (ext) { + return `${urlSafeName}-${id}${ext}`; + } + return `${urlSafeName}-${id}`; +}; + +export function createFilesContext(config?: FilesConfig): FilesContext | undefined { + if (!config) { + return; + } + + const { baseUrl = DEFAULT_BASE_URL, storagePath = DEFAULT_STORAGE_PATH } = config.local || {}; + + fs.mkdirSync(storagePath, { recursive: true }); + + return { + getSrc: (mode, filename) => { + return `${baseUrl}/${filename}`; + }, + getDataFromRef: async (ref: string) => { + const fileRef = parseFileRef(ref); + if (!fileRef) { + throw new Error('Invalid file reference'); + } + const { size: filesize } = await fs.stat(path.join(storagePath, fileRef.filename)); + return { filesize, ...fileRef }; + }, + getDataFromStream: async (stream, filename) => { + const { upload: mode } = config; + const safeFilename = generateSafeFilename(filename, config.transformFilename); + const writeStream = fs.createWriteStream(path.join(storagePath, safeFilename)); + const observeStreamErrors: Promise = new Promise((resolve, reject) => { + writeStream.on('close', () => { + resolve(); + }); + // reject on both writeStream and read stream errors + writeStream.on('error', err => { + reject(err); + }); + stream.on('error', err => { + reject(err); + }); + }); + + for await (let chunk of stream) { + writeStream.write(chunk); + } + writeStream.close(); + + try { + await observeStreamErrors; + const { size: filesize } = await fs.stat(path.join(storagePath, safeFilename)); + return { mode, filesize, filename: safeFilename }; + } catch (e) { + await fs.remove(path.join(storagePath, safeFilename)); + throw e; + } + }, + }; +} diff --git a/packages-next/keystone/src/lib/createSystem.ts b/packages-next/keystone/src/lib/createSystem.ts index 3fb8afdaa8b..3bb9736918d 100644 --- a/packages-next/keystone/src/lib/createSystem.ts +++ b/packages-next/keystone/src/lib/createSystem.ts @@ -16,6 +16,7 @@ export function createSystem(config: KeystoneConfig, prismaClient?: any) { graphQLSchema, internalSchema, imagesConfig: config.images, + filesConfig: config.files, }); return { keystone, graphQLSchema, createContext }; diff --git a/packages-next/types/src/config/index.ts b/packages-next/types/src/config/index.ts index 5a80fa2ea1e..3b486ac9ea5 100644 --- a/packages-next/types/src/config/index.ts +++ b/packages-next/types/src/config/index.ts @@ -3,7 +3,7 @@ import { CorsOptions } from 'cors'; import type { GraphQLSchema } from 'graphql'; import type { Config } from 'apollo-server-express'; -import type { ImageMode, KeystoneContext } from '..'; +import type { ImageMode, FileMode, KeystoneContext } from '..'; import { CreateContext } from '../core'; import type { BaseKeystone } from '../base'; @@ -28,6 +28,7 @@ export type KeystoneConfig = { session?: () => SessionStrategy; graphql?: GraphQLConfig; extendGraphqlSchema?: ExtendGraphqlSchema; + files?: FilesConfig; images?: ImagesConfig; /** Experimental config options */ experimental?: { @@ -145,6 +146,25 @@ export type GraphQLConfig = { export type ExtendGraphqlSchema = (schema: GraphQLSchema, keystone: BaseKeystone) => GraphQLSchema; +// config.files + +export type FilesConfig = { + upload: FileMode; + transformFilename?: (str: string) => string; + local?: { + /** + * The path local files are uploaded to. + * @default 'public/files' + */ + storagePath?: string; + /** + * The base of the URL local files will be served from, outside of keystone. + * @default '/files' + */ + baseUrl?: string; + }; +}; + // config.images export type ImagesConfig = { diff --git a/packages-next/types/src/context.ts b/packages-next/types/src/context.ts index d8a9a600e8f..352c4a2f90d 100644 --- a/packages-next/types/src/context.ts +++ b/packages-next/types/src/context.ts @@ -14,6 +14,7 @@ export type KeystoneContext = { withSession: (session: any) => KeystoneContext; // TODO: Correctly type this as a prisma client prisma: any; + files: FilesContext | undefined; images: ImagesContext | undefined; totalResults: number; maxTotalResults: number; @@ -151,6 +152,22 @@ export type SessionContext = { endSession(): Promise; }; +// Files API + +export type FileMode = 'local'; + +export type FileData = { + mode: FileMode; + filename: string; + filesize: number; +}; + +export type FilesContext = { + getSrc: (mode: FileMode, filename: string) => string; + getDataFromRef: (ref: string) => Promise; + getDataFromStream: (stream: Readable, filename: string) => Promise; +}; + // Images API export type ImageMode = 'local'; diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 8f76813c904..761cad12768 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -1,7 +1,7 @@ import pLazy from 'p-lazy'; import pReflect from 'p-reflect'; import semver from 'semver'; -import { ImageMode, ImageExtension } from '@keystone-next/types'; +import { FileMode, ImageMode, ImageExtension } from '@keystone-next/types'; export const noop = (x: T): T => x; export const identity = noop; @@ -258,17 +258,31 @@ export const humanize = (str: string) => { .join(' '); }; -const REFREGEX = /^(local):([^:\n]+)\.(gif|jpg|png|webp)$/; +const IMAGEREGEX = /^(local):([^:\n]+)\.(gif|jpg|png|webp)$/; +const FILEREGEX = /^(local):file:([^\\\/:\n]+)/; export const getImageRef = (mode: ImageMode, id: string, extension: ImageExtension) => `${mode}:${id}.${extension}`; +export const getFileRef = (mode: FileMode, name: string) => `${mode}:file:${name}`; +export const parseFileRef = (ref: string) => { + const match = ref.match(FILEREGEX); + if (match) { + const [, mode, filename] = match; + return { + mode: mode as FileMode, + filename: filename as string, + }; + } + return undefined; +}; + export const SUPPORTED_IMAGE_EXTENSIONS = ['jpg', 'png', 'webp', 'gif']; export const parseImageRef = ( ref: string ): { mode: ImageMode; id: string; extension: ImageExtension } | undefined => { - const match = ref.match(REFREGEX); + const match = ref.match(IMAGEREGEX); if (match) { const [, mode, id, ext] = match; return { diff --git a/tests/api-tests/fields/crud.test.ts b/tests/api-tests/fields/crud.test.ts index 878823e3db2..987dcc5341c 100644 --- a/tests/api-tests/fields/crud.test.ts +++ b/tests/api-tests/fields/crud.test.ts @@ -30,6 +30,7 @@ multiAdapterRunners().map(({ runner, provider }) => [listKey]: list({ fields: mod.getTestFields(matrixValue) }), }), images: { upload: 'local', local: { storagePath: 'tmp_test_images' } }, + files: { upload: 'local', local: { storagePath: 'tmp_test_files' } }, }), }), @@ -49,6 +50,16 @@ multiAdapterRunners().map(({ runner, provider }) => mod.beforeAll(); } }); + afterEach(async () => { + if (mod.afterEach) { + await mod.afterEach(); + } + }); + beforeEach(() => { + if (mod.beforeEach) { + mod.beforeEach(); + } + }); afterAll(async () => { if (mod.afterAll) { await mod.afterAll(); @@ -60,16 +71,27 @@ multiAdapterRunners().map(({ runner, provider }) => if (!mod.skipCommonCrudTest) { describe(`${mod.name} - ${matrixValue} - CRUD operations`, () => { + beforeEach(() => { + if (mod.beforeEach) { + mod.beforeEach(); + } + }); beforeAll(() => { if (mod.beforeAll) { mod.beforeAll(); } }); + afterEach(async () => { + if (mod.afterEach) { + await mod.afterEach(); + } + }); afterAll(async () => { if (mod.afterAll) { await mod.afterAll(); } }); + const { fieldName, exampleValue, diff --git a/tests/api-tests/fields/filter.test.ts b/tests/api-tests/fields/filter.test.ts index fe930332eca..5f9c316fc13 100644 --- a/tests/api-tests/fields/filter.test.ts +++ b/tests/api-tests/fields/filter.test.ts @@ -29,6 +29,7 @@ multiAdapterRunners().map(({ runner, provider }) => [listKey]: list({ fields: mod.getTestFields(matrixValue) }), }), images: { upload: 'local', local: { storagePath: 'tmp_test_images' } }, + files: { upload: 'local', local: { storagePath: 'tmp_test_files' } }, }), }); @@ -44,6 +45,16 @@ multiAdapterRunners().map(({ runner, provider }) => if (mod.filterTests) { describe(`${mod.name} - ${matrixValue} - Custom Filtering`, () => { + beforeEach(() => { + if (mod.beforeEach) { + mod.beforeEach(); + } + }); + afterEach(async () => { + if (mod.afterEach) { + await mod.afterEach(); + } + }); beforeAll(() => { if (mod.beforeAll) { mod.beforeAll(); @@ -60,6 +71,16 @@ multiAdapterRunners().map(({ runner, provider }) => if (!mod.skipCommonFilterTest) { describe(`${mod.name} - ${matrixValue} - Common Filtering`, () => { + beforeEach(() => { + if (mod.beforeEach) { + mod.beforeEach(); + } + }); + afterEach(async () => { + if (mod.afterEach) { + await mod.afterEach(); + } + }); beforeAll(() => { if (mod.beforeAll) { mod.beforeAll(); diff --git a/tests/api-tests/fields/required.test.ts b/tests/api-tests/fields/required.test.ts index 8194cbf7dbe..008e6c7fa8f 100644 --- a/tests/api-tests/fields/required.test.ts +++ b/tests/api-tests/fields/required.test.ts @@ -17,6 +17,16 @@ multiAdapterRunners().map(({ runner, provider }) => .forEach(mod => { (mod.testMatrix || ['default']).forEach((matrixValue: string) => { describe(`${mod.name} - ${matrixValue} - isRequired`, () => { + beforeEach(() => { + if (mod.beforeEach) { + mod.beforeEach(); + } + }); + afterEach(async () => { + if (mod.afterEach) { + await mod.afterEach(); + } + }); beforeAll(() => { if (mod.beforeAll) { mod.beforeAll(); @@ -45,6 +55,7 @@ multiAdapterRunners().map(({ runner, provider }) => }), }), images: { upload: 'local', local: { storagePath: 'tmp_test_images' } }, + files: { upload: 'local', local: { storagePath: 'tmp_test_files' } }, }), }), testFn diff --git a/tests/api-tests/fields/unique.test.ts b/tests/api-tests/fields/unique.test.ts index 3c28869558a..f7ca0b2c4a0 100644 --- a/tests/api-tests/fields/unique.test.ts +++ b/tests/api-tests/fields/unique.test.ts @@ -19,6 +19,16 @@ multiAdapterRunners().map(({ runner, provider, after }) => .forEach(mod => { (mod.testMatrix || ['default']).forEach((matrixValue: string) => { describe(`${mod.name} - ${matrixValue} - isUnique`, () => { + beforeEach(() => { + if (mod.beforeEach) { + mod.beforeEach(); + } + }); + afterEach(async () => { + if (mod.afterEach) { + await mod.afterEach(); + } + }); beforeAll(() => { if (mod.beforeAll) { mod.beforeAll(); @@ -153,6 +163,7 @@ multiAdapterRunners().map(({ runner, provider, after }) => }), }), images: { upload: 'local', local: { storagePath: 'tmp_test_images' } }, + files: { upload: 'local', local: { storagePath: 'tmp_test_files' } }, }), }); } catch (error) { diff --git a/tests/api-tests/fields/unsupported.test.ts b/tests/api-tests/fields/unsupported.test.ts index fc5c698a2c7..7f89ce50dd2 100644 --- a/tests/api-tests/fields/unsupported.test.ts +++ b/tests/api-tests/fields/unsupported.test.ts @@ -20,6 +20,16 @@ multiAdapterRunners().map(({ provider, after }) => { const listKey = 'Test'; describe(`${mod.name} - Unsupported field type`, () => { + beforeEach(() => { + if (mod.beforeEach) { + mod.beforeEach(); + } + }); + afterEach(async () => { + if (mod.afterEach) { + await mod.afterEach(); + } + }); beforeAll(() => { if (mod.beforeAll) { mod.beforeAll(); @@ -42,6 +52,7 @@ multiAdapterRunners().map(({ provider, after }) => { [listKey]: list({ fields: mod.getTestFields(matrixValue) }), }), images: { upload: 'local', local: { storagePath: 'tmp_test_images' } }, + files: { upload: 'local', local: { storagePath: 'tmp_test_files' } }, }), }) ).rejects.toThrow(Error); diff --git a/yarn.lock b/yarn.lock index 913e2e57e3d..80da1048ff5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6475,6 +6475,20 @@ file-uri-to-path@1.0.0: resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== +filename-reserved-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229" + integrity sha1-q/c9+rc10EVECr/qLZHzieu/oik= + +filenamify@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-4.3.0.tgz#62391cb58f02b09971c9d4f9d63b3cf9aba03106" + integrity sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg== + dependencies: + filename-reserved-regex "^2.0.0" + strip-outer "^1.0.1" + trim-repeated "^1.0.0" + fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -12318,6 +12332,13 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +strip-outer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631" + integrity sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg== + dependencies: + escape-string-regexp "^1.0.2" + stripe@^8.145.0: version "8.145.0" resolved "https://registry.yarnpkg.com/stripe/-/stripe-8.145.0.tgz#5d5c18ffb86b247ef67d7a162bab3753f650ab10" @@ -12796,6 +12817,13 @@ trim-newlines@^3.0.0: resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.0.tgz#79726304a6a898aa8373427298d54c2ee8b1cb30" integrity sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA== +trim-repeated@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21" + integrity sha1-42RqLqTokTEr9+rObPsFOAvAHCE= + dependencies: + escape-string-regexp "^1.0.2" + trim-trailing-lines@^1.0.0: version "1.1.4" resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz#bd4abbec7cc880462f10b2c8b5ce1d8d1ec7c2c0"