From 452a776aef4216abb9c9d46b62f366f80fd7da21 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Apr 2022 22:36:00 +0000 Subject: [PATCH 1/9] Bump @google-cloud/functions-framework from 3.0.0 to 3.1.0 Bumps [@google-cloud/functions-framework](https://github.com/GoogleCloudPlatform/functions-framework-nodejs) from 3.0.0 to 3.1.0. - [Release notes](https://github.com/GoogleCloudPlatform/functions-framework-nodejs/releases) - [Changelog](https://github.com/GoogleCloudPlatform/functions-framework-nodejs/blob/master/CHANGELOG.md) - [Commits](https://github.com/GoogleCloudPlatform/functions-framework-nodejs/compare/v3.0.0...v3.1.0) --- updated-dependencies: - dependency-name: "@google-cloud/functions-framework" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- packages/import-handler/package.json | 2 +- packages/inbound-email-handler/package.json | 2 +- packages/pdf-handler/package.json | 2 +- yarn.lock | 422 ++++++++++++++++++-- 4 files changed, 401 insertions(+), 27 deletions(-) diff --git a/packages/import-handler/package.json b/packages/import-handler/package.json index cf6a5d1a6..0380b15d8 100644 --- a/packages/import-handler/package.json +++ b/packages/import-handler/package.json @@ -25,7 +25,7 @@ }, "dependencies": { "@fast-csv/parse": "^4.3.6", - "@google-cloud/functions-framework": "3.0.0", + "@google-cloud/functions-framework": "3.1.0", "@google-cloud/pubsub": "^2.16.3", "@google-cloud/storage": "^5.18.1", "@types/express": "^4.17.13", diff --git a/packages/inbound-email-handler/package.json b/packages/inbound-email-handler/package.json index bde778019..412971762 100644 --- a/packages/inbound-email-handler/package.json +++ b/packages/inbound-email-handler/package.json @@ -26,7 +26,7 @@ "eslint-plugin-prettier": "^4.0.0" }, "dependencies": { - "@google-cloud/functions-framework": "3.0.0", + "@google-cloud/functions-framework": "3.1.0", "@google-cloud/pubsub": "^2.18.4", "@sendgrid/client": "^7.6.0", "@sentry/serverless": "^6.16.1", diff --git a/packages/pdf-handler/package.json b/packages/pdf-handler/package.json index bc22b2951..bc333dc5d 100644 --- a/packages/pdf-handler/package.json +++ b/packages/pdf-handler/package.json @@ -23,7 +23,7 @@ "@types/node": "^14.11.2" }, "dependencies": { - "@google-cloud/functions-framework": "3.0.0", + "@google-cloud/functions-framework": "3.1.0", "@google-cloud/pubsub": "^2.16.3", "@google-cloud/storage": "^5.18.1", "axios": "^0.26.0", diff --git a/yarn.lock b/yarn.lock index 2e0ae8cf2..e0965634a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1681,7 +1681,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.17.7", "@babel/runtime@^7.8.4": +"@babel/runtime@^7.14.6", "@babel/runtime@^7.17.7", "@babel/runtime@^7.8.4": version "7.17.8" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.8.tgz#3e56e4aff81befa55ac3ac6a0967349fd1c5bca2" integrity sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA== @@ -1834,6 +1834,38 @@ dependencies: "@cspotcode/source-map-consumer" "0.8.0" +"@cypress/request@^2.88.10": + version "2.88.10" + resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.10.tgz#b66d76b07f860d3a4b8d7a0604d020c662752cce" + integrity sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + http-signature "~1.3.6" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^8.3.2" + +"@cypress/xvfb@^1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@cypress/xvfb/-/xvfb-1.2.4.tgz#2daf42e8275b39f4aa53c14214e557bd14e7748a" + integrity sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q== + dependencies: + debug "^3.1.0" + lodash.once "^4.1.1" + "@dabh/diagnostics@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.2.tgz#290d08f7b381b8f94607dc8f471a12c675f9db31" @@ -2071,13 +2103,13 @@ google-gax "^2.24.1" protobufjs "^6.8.6" -"@google-cloud/functions-framework@3.0.0", "@google-cloud/functions-framework@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@google-cloud/functions-framework/-/functions-framework-3.0.0.tgz#2b7e6454ee9fe4d1eaaa08384fc01de4a72cd081" - integrity sha512-+K9+y39/5ig4QrbnaCM8BOzt4+Qx5SRMu2dj5QDTNFc5s8f/Lubty8u3aBQN6JC86M0NuHL9zIj8xs8Awj7C+w== +"@google-cloud/functions-framework@3.1.0", "@google-cloud/functions-framework@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@google-cloud/functions-framework/-/functions-framework-3.1.0.tgz#7e17614dd17e70992581d382c3990c34e5445f0e" + integrity sha512-hdHxohi4S34H0lLMuXiEBsTXVbYBG7VH8PE4UCcGOn0mbjKXbSP4H6hBxMbQMonIPfO/JJjEeLaTCal8fiTmaA== dependencies: body-parser "^1.18.3" - cloudevents "^5.1.0" + cloudevents "^5.3.2" express "^4.16.4" minimist "^1.2.5" on-finished "^2.3.0" @@ -5887,6 +5919,14 @@ dependencies: defer-to-connect "^1.0.1" +"@testing-library/cypress@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@testing-library/cypress/-/cypress-8.0.2.tgz#b13f0ff2424dec4368b6670dfbfb7e43af8eefc9" + integrity sha512-KVdm7n37sg/A4e3wKMD4zUl0NpzzVhx06V9Tf0hZHZ7nrZ4yFva6Zwg2EFF1VzHkEfN/ahUzRtT1qiW+vuWnJw== + dependencies: + "@babel/runtime" "^7.14.6" + "@testing-library/dom" "^8.1.0" + "@testing-library/dom@^8.0.0": version "8.1.0" resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.1.0.tgz#f8358b1883844ea569ba76b7e94582168df5370d" @@ -5901,6 +5941,20 @@ lz-string "^1.4.4" pretty-format "^27.0.2" +"@testing-library/dom@^8.1.0": + version "8.12.0" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.12.0.tgz#fef5e545533fb084175dda6509ee71d7d2f72e23" + integrity sha512-rBrJk5WjI02X1edtiUcZhgyhgBhiut96r5Jp8J5qktKdcvLcZpKDW8i2hkGMMItxrghjXuQ5AM6aE0imnFawaw== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/runtime" "^7.12.5" + "@types/aria-query" "^4.2.0" + aria-query "^5.0.0" + chalk "^4.1.0" + dom-accessibility-api "^0.5.9" + lz-string "^1.4.4" + pretty-format "^27.0.2" + "@testing-library/jest-dom@^5.16.1": version "5.16.2" resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.2.tgz#f329b36b44aa6149cd6ced9adf567f8b6aa1c959" @@ -6417,6 +6471,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.32.tgz#2ca61c9ef8c77f6fa1733be9e623ceb0d372ad96" integrity sha512-JcII3D5/OapPGx+eJ+Ik1SQGyt6WvuqdRfh9jUwL6/iHGjmyOriBDciBUu7lEIBTL2ijxwrR70WUnw5AEDmFvQ== +"@types/node@^14.14.31": + version "14.18.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.12.tgz#0d4557fd3b94497d793efd4e7d92df2f83b4ef24" + integrity sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A== + "@types/nodemailer@^6.4.4": version "6.4.4" resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.4.tgz#c265f7e7a51df587597b3a49a023acaf0c741f4b" @@ -6567,6 +6626,16 @@ "@types/mime" "^1" "@types/node" "*" +"@types/sinonjs__fake-timers@8.1.1": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz#b49c2c70150141a15e0fa7e79cf1f92a72934ce3" + integrity sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g== + +"@types/sizzle@^2.3.2": + version "2.3.3" + resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.3.tgz#ff5e2f1902969d305225a047c8a0fd5c915cebef" + integrity sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ== + "@types/sockjs@^0.3.33": version "0.3.33" resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" @@ -7216,6 +7285,13 @@ ansi-escapes@^4.2.1, ansi-escapes@^4.3.1: dependencies: type-fest "^0.11.0" +ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + ansi-html-community@^0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" @@ -7417,6 +7493,11 @@ aproba@^2.0.0: resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== +arch@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" + integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== + archy@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" @@ -7614,6 +7695,11 @@ ast-types-flow@^0.0.7: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + async-retry@^1.2.1, async-retry@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280" @@ -7628,7 +7714,7 @@ async@^2.6.2: dependencies: lodash "^4.17.14" -async@^3.2.3: +async@^3.2.0, async@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/async/-/async-3.2.3.tgz#ac53dafd3f4720ee9e8a160628f18ea91df196c9" integrity sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g== @@ -7928,6 +8014,16 @@ bl@^4.0.3, bl@^4.1.0: inherits "^2.0.4" readable-stream "^3.4.0" +blob-util@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb" + integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ== + +bluebird@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + body-parser@1.19.0: version "1.19.0" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" @@ -8092,7 +8188,7 @@ buffer-writer@2.0.0: resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== -buffer@^5.2.1, buffer@^5.5.0, buffer@^5.7.0: +buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0, buffer@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -8199,6 +8295,11 @@ cacheable-request@^6.0.0: normalize-url "^4.1.0" responselike "^1.0.2" +cachedir@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8" + integrity sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw== + caching-transform@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-4.0.0.tgz#00d297a4206d71e2163c39eaffa8157ac0651f0f" @@ -8420,6 +8521,11 @@ check-error@^1.0.2: resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= +check-more-types@^2.24.0: + version "2.24.0" + resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" + integrity sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA= + chokidar@3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" @@ -8563,6 +8669,15 @@ cli-spinners@^2.5.0: resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d" integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== +cli-table3@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.1.tgz#36ce9b7af4847f288d3cdd081fbd09bf7bd237b8" + integrity sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA== + dependencies: + string-width "^4.2.0" + optionalDependencies: + colors "1.4.0" + cli-truncate@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" @@ -8571,6 +8686,14 @@ cli-truncate@^0.2.1: slice-ansi "0.0.4" string-width "^1.0.1" +cli-truncate@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" + integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== + dependencies: + slice-ansi "^3.0.0" + string-width "^4.2.0" + cli-width@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" @@ -8615,7 +8738,7 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= -cloudevents@^5.1.0: +cloudevents@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/cloudevents/-/cloudevents-5.3.2.tgz#1338f0d51a2baac40ef7ea2b3577394447994d49" integrity sha512-ZjEFjx0BJnio8SED1TzD7GHA118zCk04Mz6aDMMii+4/ZvX5LPgn1D4lT5Jj7HodCbdeRS6dX88unH06Qc3mkA== @@ -8704,11 +8827,16 @@ colorette@^1.3.0: resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.3.0.tgz#ff45d2f0edb244069d3b772adeb04fed38d0a0af" integrity sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w== -colorette@^2.0.10, colorette@^2.0.14: +colorette@^2.0.10, colorette@^2.0.14, colorette@^2.0.16: version "2.0.16" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== +colors@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + colorspace@1.1.x: version "1.1.2" resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.2.tgz#e0128950d082b86a2168580796a0aa5d6c68d8c5" @@ -9200,6 +9328,54 @@ csv-parser@^3.0.0: dependencies: minimist "^1.2.0" +cypress@^9.5.3: + version "9.5.3" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-9.5.3.tgz#7c56b50fc1f1aa69ef10b271d895aeb4a1d7999e" + integrity sha512-ItelIVmqMTnKYbo1JrErhsGgQGjWOxCpHT1TfMvwnIXKXN/OSlPjEK7rbCLYDZhejQL99PmUqul7XORI24Ik0A== + dependencies: + "@cypress/request" "^2.88.10" + "@cypress/xvfb" "^1.2.4" + "@types/node" "^14.14.31" + "@types/sinonjs__fake-timers" "8.1.1" + "@types/sizzle" "^2.3.2" + arch "^2.2.0" + blob-util "^2.0.2" + bluebird "^3.7.2" + buffer "^5.6.0" + cachedir "^2.3.0" + chalk "^4.1.0" + check-more-types "^2.24.0" + cli-cursor "^3.1.0" + cli-table3 "~0.6.1" + commander "^5.1.0" + common-tags "^1.8.0" + dayjs "^1.10.4" + debug "^4.3.2" + enquirer "^2.3.6" + eventemitter2 "^6.4.3" + execa "4.1.0" + executable "^4.1.1" + extract-zip "2.0.1" + figures "^3.2.0" + fs-extra "^9.1.0" + getos "^3.2.1" + is-ci "^3.0.0" + is-installed-globally "~0.4.0" + lazy-ass "^1.6.0" + listr2 "^3.8.3" + lodash "^4.17.21" + log-symbols "^4.0.0" + minimist "^1.2.6" + ospath "^1.2.2" + pretty-bytes "^5.6.0" + proxy-from-env "1.0.0" + request-progress "^3.0.0" + semver "^7.3.2" + supports-color "^8.1.1" + tmp "~0.2.1" + untildify "^4.0.0" + yauzl "^2.10.0" + damerau-levenshtein@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz#64368003512a1a6992593741a09a9d31a836f55d" @@ -9260,6 +9436,11 @@ dateformat@^3.0.0: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== +dayjs@^1.10.4: + version "1.11.0" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.0.tgz#009bf7ef2e2ea2d5db2e6583d2d39a4b5061e805" + integrity sha512-JLC809s6Y948/FuCZPm5IX8rRhQwOiyMb2TfVVQEixG7P8Lm/gt5S7yoQZmC8x1UehI9Pb7sksEt4xx14m+7Ug== + debounce@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.0.tgz#44a540abc0ea9943018dc0eaa95cce87f65cd131" @@ -9293,7 +9474,7 @@ debug@4.3.1: dependencies: ms "2.1.2" -debug@^3.1.1, debug@^3.2.7: +debug@^3.1.0, debug@^3.1.1, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -9647,6 +9828,11 @@ dom-accessibility-api@^0.5.6: resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.7.tgz#8c2aa6325968f2933160a0b7dbb380893ddf3e7d" integrity sha512-ml3lJIq9YjUfM9TUnEPvEYWFSwivwIGBPKpewX7tii7fwCazA8yCioGdqQcNsItPpfFvSJ3VIdMQPj60LJhcQA== +dom-accessibility-api@^0.5.9: + version "0.5.13" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.13.tgz#102ee5f25eacce09bdf1cfa5a298f86da473be4b" + integrity sha512-R305kwb5CcMDIpSHUnLyIAp7SrSPBx6F0VfQFB3M75xVMHhXJJIdePYgbPPh1o57vCHNu5QztokWUPsLjWzFqw== + dom-serializer@^1.0.1: version "1.3.2" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" @@ -9890,7 +10076,7 @@ enhanced-resolve@^5.9.2: graceful-fs "^4.2.4" tapable "^2.2.0" -enquirer@^2.3.5: +enquirer@^2.3.5, enquirer@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== @@ -10326,6 +10512,11 @@ event-target-shim@^5.0.0: resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== +eventemitter2@^6.4.3: + version "6.4.5" + resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.5.tgz#97380f758ae24ac15df8353e0cc27f8b95644655" + integrity sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw== + eventemitter3@^3.1.0: version "3.1.2" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" @@ -10348,6 +10539,21 @@ events@^3.2.0: resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== +execa@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" + integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -10363,6 +10569,13 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" +executable@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" + integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg== + dependencies: + pify "^2.2.0" + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -10643,7 +10856,7 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" -figures@^3.0.0: +figures@^3.0.0, figures@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== @@ -11079,7 +11292,7 @@ get-stream@^4.1.0: dependencies: pump "^3.0.0" -get-stream@^5.1.0: +get-stream@^5.0.0, get-stream@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== @@ -11109,6 +11322,13 @@ getopts@2.2.5: resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.2.5.tgz#67a0fe471cacb9c687d817cab6450b96dde8313b" integrity sha512-9jb7AW5p3in+IiJWhQiZmmwkpLaR/ccTWdWQCtZM66HJcHHLegowh4q4tSD7gouUyeNvFWRavfK9GXosQHDpFA== +getos@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/getos/-/getos-3.2.1.tgz#0134d1f4e00eb46144c5a9c0ac4dc087cbb27dc5" + integrity sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q== + dependencies: + async "^3.2.0" + getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -11890,6 +12110,15 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" +http-signature@~1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.3.6.tgz#cb6fbfdf86d1c974f343be94e87f7fc128662cf9" + integrity sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw== + dependencies: + assert-plus "^1.0.0" + jsprim "^2.0.2" + sshpk "^1.14.1" + https-proxy-agent@5.0.0, https-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" @@ -11898,6 +12127,11 @@ https-proxy-agent@5.0.0, https-proxy-agent@^5.0.0: agent-base "6" debug "4" +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -12261,6 +12495,13 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" +is-ci@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867" + integrity sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ== + dependencies: + ci-info "^3.2.0" + is-core-module@^2.2.0, is-core-module@^2.5.0: version "2.6.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.6.0.tgz#d7553b2526fe59b92ba3e40c8df757ec8a709e19" @@ -12391,7 +12632,7 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" -is-installed-globally@^0.4.0: +is-installed-globally@^0.4.0, is-installed-globally@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ== @@ -13394,6 +13635,11 @@ json-schema@0.2.3: resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" @@ -13478,6 +13724,16 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +jsprim@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-2.0.2.tgz#77ca23dbcd4135cd364800d22ff82c2185803d4d" + integrity sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + "jsx-ast-utils@^2.4.1 || ^3.0.0": version "3.2.0" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz#41108d2cec408c3453c1bbe8a4aae9e1e2bd8f82" @@ -13652,6 +13908,11 @@ latest-version@5.1.0, latest-version@^5.1.0: dependencies: package-json "^6.3.0" +lazy-ass@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" + integrity sha1-eZllXoZGwX8In90YfRUNMyTVRRM= + lerna@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/lerna/-/lerna-4.0.0.tgz#b139d685d50ea0ca1be87713a7c2f44a5b678e9e" @@ -13792,6 +14053,20 @@ listr-verbose-renderer@^0.5.0: date-fns "^1.27.2" figures "^2.0.0" +listr2@^3.8.3: + version "3.14.0" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.14.0.tgz#23101cc62e1375fd5836b248276d1d2b51fdbe9e" + integrity sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g== + dependencies: + cli-truncate "^2.1.0" + colorette "^2.0.16" + log-update "^4.0.0" + p-map "^4.0.0" + rfdc "^1.3.0" + rxjs "^7.5.1" + through "^2.3.8" + wrap-ansi "^7.0.0" + listr@^0.14.3: version "0.14.3" resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586" @@ -13988,7 +14263,7 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash.once@^4.0.0: +lodash.once@^4.0.0, lodash.once@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= @@ -14071,6 +14346,16 @@ log-update@^2.3.0: cli-cursor "^2.0.0" wrap-ansi "^3.0.1" +log-update@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" + integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== + dependencies: + ansi-escapes "^4.3.0" + cli-cursor "^3.1.0" + slice-ansi "^4.0.0" + wrap-ansi "^6.2.0" + logform@^2.3.2, logform@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/logform/-/logform-2.4.0.tgz#131651715a17d50f09c2a2c1a524ff1a4164bcfe" @@ -14188,10 +14473,10 @@ lru_map@^0.3.3: resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" integrity sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0= -luxon@^1.25.0, luxon@^1.26.0: - version "1.28.0" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.28.0.tgz#e7f96daad3938c06a62de0fb027115d251251fbf" - integrity sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ== +luxon@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-2.3.1.tgz#f276b1b53fd9a740a60e666a541a7f6dbed4155a" + integrity sha512-I8vnjOmhXsMSlNMZlMkSOvgrxKJl0uOsEzdGgGNZuZPaS9KlefpE9KV95QFftlJSC+1UyCC9/I69R02cz/zcCA== lz-string@^1.4.4: version "1.4.4" @@ -14527,7 +14812,7 @@ minimist-options@4.1.0: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.5: +minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: version "1.2.6" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== @@ -15203,7 +15488,7 @@ npm-registry-fetch@^9.0.0: minizlib "^2.0.0" npm-package-arg "^8.0.0" -npm-run-path@^4.0.1: +npm-run-path@^4.0.0, npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== @@ -15556,6 +15841,11 @@ osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" +ospath@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b" + integrity sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs= + p-cancelable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" @@ -16061,7 +16351,7 @@ picomatch@^2.2.3: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== -pify@^2.3.0: +pify@^2.2.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= @@ -16256,6 +16546,11 @@ prettier@^2.5.1: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a" integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg== +pretty-bytes@^5.6.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" + integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== + pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.0.6: version "27.0.6" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.0.6.tgz#ab770c47b2c6f893a21aefc57b75da63ef49a11f" @@ -16410,6 +16705,11 @@ proxy-addr@~2.0.5: forwarded "0.2.0" ipaddr.js "1.9.1" +proxy-from-env@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" + integrity sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4= + proxy-from-env@1.1.0, proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" @@ -17029,6 +17329,13 @@ replaceall@^0.1.6: resolved "https://registry.yarnpkg.com/replaceall/-/replaceall-0.1.6.tgz#81d81ac7aeb72d7f5c4942adf2697a3220688d8e" integrity sha1-gdgax663LX9cSUKt8ml6MiBojY4= +request-progress@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-3.0.0.tgz#4ca754081c7fec63f505e4faa825aa06cd669dbe" + integrity sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4= + dependencies: + throttleit "^1.0.0" + request@^2.88.0, request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" @@ -17195,6 +17502,11 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== +rfdc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" + integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -17233,6 +17545,13 @@ rxjs@^7.2.0: dependencies: tslib "^2.1.0" +rxjs@^7.5.1: + version "7.5.5" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.5.tgz#2ebad89af0f560f460ad5cc4213219e1f7dd4e9f" + integrity sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw== + dependencies: + tslib "^2.1.0" + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -17585,6 +17904,24 @@ slice-ansi@0.0.4: resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= +slice-ansi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" + integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + slide@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" @@ -17863,6 +18200,21 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= +sshpk@^1.14.1: + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + sshpk@^1.7.0: version "1.16.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" @@ -18194,7 +18546,7 @@ supertest@^6.2.2: methods "^1.1.2" superagent "^7.1.0" -supports-color@8.1.1, supports-color@^8.0.0, supports-color@^8.1.0: +supports-color@8.1.1, supports-color@^8.0.0, supports-color@^8.1.0, supports-color@^8.1.1: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== @@ -18450,6 +18802,11 @@ throat@^6.0.1: resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375" integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w== +throttleit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c" + integrity sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw= + through2@^2.0.0: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" @@ -18507,6 +18864,13 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" +tmp@~0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== + dependencies: + rimraf "^3.0.0" + tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" @@ -18807,6 +19171,11 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + type-fest@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.4.1.tgz#8bdf77743385d8a4f13ba95f610f5ccd68c728f8" @@ -19045,6 +19414,11 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" +untildify@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" + integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== + upath@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/upath/-/upath-2.0.1.tgz#50c73dea68d6f6b990f51d279ce6081665d61a8b" From 8df6e750dcc4c863b7d7dd49a6eb2b5e0332e0a0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Apr 2022 22:36:25 +0000 Subject: [PATCH 2/9] Bump googleapis from 59.0.0 to 100.0.0 Bumps [googleapis](https://github.com/googleapis/google-api-nodejs-client) from 59.0.0 to 100.0.0. - [Release notes](https://github.com/googleapis/google-api-nodejs-client/releases) - [Changelog](https://github.com/googleapis/google-api-nodejs-client/blob/main/CHANGELOG.md) - [Commits](https://github.com/googleapis/google-api-nodejs-client/compare/v59.0.0...googleapis-v100.0.0) --- updated-dependencies: - dependency-name: googleapis dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- packages/api/package.json | 4 +- yarn.lock | 455 ++++++++++++++++++++++++++++++++++---- 2 files changed, 409 insertions(+), 50 deletions(-) diff --git a/packages/api/package.json b/packages/api/package.json index 8e4a08657..b52128b1c 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -50,7 +50,7 @@ "dotenv": "^8.2.0", "express": "^4.17.1", "firebase-admin": "^10.0.2", - "googleapis": "^59.0.0", + "googleapis": "^100.0.0", "graphql": "^15.3.0", "graphql-middleware": "^6.0.10", "graphql-shield": "^7.5.0", @@ -62,7 +62,7 @@ "jwks-rsa": "^2.0.3", "knex": "0.21.12", "knex-stringcase": "^1.4.2", - "luxon": "^1.25.0", + "luxon": "^2.3.1", "nanoid": "^3.1.25", "nodemailer": "^6.7.3", "normalize-url": "^6.1.0", diff --git a/yarn.lock b/yarn.lock index 2e0ae8cf2..fa356d52f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1681,7 +1681,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.17.7", "@babel/runtime@^7.8.4": +"@babel/runtime@^7.14.6", "@babel/runtime@^7.17.7", "@babel/runtime@^7.8.4": version "7.17.8" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.8.tgz#3e56e4aff81befa55ac3ac6a0967349fd1c5bca2" integrity sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA== @@ -1834,6 +1834,38 @@ dependencies: "@cspotcode/source-map-consumer" "0.8.0" +"@cypress/request@^2.88.10": + version "2.88.10" + resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.10.tgz#b66d76b07f860d3a4b8d7a0604d020c662752cce" + integrity sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + http-signature "~1.3.6" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^8.3.2" + +"@cypress/xvfb@^1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@cypress/xvfb/-/xvfb-1.2.4.tgz#2daf42e8275b39f4aa53c14214e557bd14e7748a" + integrity sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q== + dependencies: + debug "^3.1.0" + lodash.once "^4.1.1" + "@dabh/diagnostics@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.2.tgz#290d08f7b381b8f94607dc8f471a12c675f9db31" @@ -5887,6 +5919,14 @@ dependencies: defer-to-connect "^1.0.1" +"@testing-library/cypress@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@testing-library/cypress/-/cypress-8.0.2.tgz#b13f0ff2424dec4368b6670dfbfb7e43af8eefc9" + integrity sha512-KVdm7n37sg/A4e3wKMD4zUl0NpzzVhx06V9Tf0hZHZ7nrZ4yFva6Zwg2EFF1VzHkEfN/ahUzRtT1qiW+vuWnJw== + dependencies: + "@babel/runtime" "^7.14.6" + "@testing-library/dom" "^8.1.0" + "@testing-library/dom@^8.0.0": version "8.1.0" resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.1.0.tgz#f8358b1883844ea569ba76b7e94582168df5370d" @@ -5901,6 +5941,20 @@ lz-string "^1.4.4" pretty-format "^27.0.2" +"@testing-library/dom@^8.1.0": + version "8.12.0" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.12.0.tgz#fef5e545533fb084175dda6509ee71d7d2f72e23" + integrity sha512-rBrJk5WjI02X1edtiUcZhgyhgBhiut96r5Jp8J5qktKdcvLcZpKDW8i2hkGMMItxrghjXuQ5AM6aE0imnFawaw== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/runtime" "^7.12.5" + "@types/aria-query" "^4.2.0" + aria-query "^5.0.0" + chalk "^4.1.0" + dom-accessibility-api "^0.5.9" + lz-string "^1.4.4" + pretty-format "^27.0.2" + "@testing-library/jest-dom@^5.16.1": version "5.16.2" resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.2.tgz#f329b36b44aa6149cd6ced9adf567f8b6aa1c959" @@ -6417,6 +6471,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.32.tgz#2ca61c9ef8c77f6fa1733be9e623ceb0d372ad96" integrity sha512-JcII3D5/OapPGx+eJ+Ik1SQGyt6WvuqdRfh9jUwL6/iHGjmyOriBDciBUu7lEIBTL2ijxwrR70WUnw5AEDmFvQ== +"@types/node@^14.14.31": + version "14.18.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.12.tgz#0d4557fd3b94497d793efd4e7d92df2f83b4ef24" + integrity sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A== + "@types/nodemailer@^6.4.4": version "6.4.4" resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.4.tgz#c265f7e7a51df587597b3a49a023acaf0c741f4b" @@ -6567,6 +6626,16 @@ "@types/mime" "^1" "@types/node" "*" +"@types/sinonjs__fake-timers@8.1.1": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz#b49c2c70150141a15e0fa7e79cf1f92a72934ce3" + integrity sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g== + +"@types/sizzle@^2.3.2": + version "2.3.3" + resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.3.tgz#ff5e2f1902969d305225a047c8a0fd5c915cebef" + integrity sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ== + "@types/sockjs@^0.3.33": version "0.3.33" resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" @@ -7216,6 +7285,13 @@ ansi-escapes@^4.2.1, ansi-escapes@^4.3.1: dependencies: type-fest "^0.11.0" +ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + ansi-html-community@^0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" @@ -7417,6 +7493,11 @@ aproba@^2.0.0: resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== +arch@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" + integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== + archy@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" @@ -7614,6 +7695,11 @@ ast-types-flow@^0.0.7: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + async-retry@^1.2.1, async-retry@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280" @@ -7628,7 +7714,7 @@ async@^2.6.2: dependencies: lodash "^4.17.14" -async@^3.2.3: +async@^3.2.0, async@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/async/-/async-3.2.3.tgz#ac53dafd3f4720ee9e8a160628f18ea91df196c9" integrity sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g== @@ -7928,6 +8014,16 @@ bl@^4.0.3, bl@^4.1.0: inherits "^2.0.4" readable-stream "^3.4.0" +blob-util@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb" + integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ== + +bluebird@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + body-parser@1.19.0: version "1.19.0" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" @@ -8092,7 +8188,7 @@ buffer-writer@2.0.0: resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== -buffer@^5.2.1, buffer@^5.5.0, buffer@^5.7.0: +buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0, buffer@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -8199,6 +8295,11 @@ cacheable-request@^6.0.0: normalize-url "^4.1.0" responselike "^1.0.2" +cachedir@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8" + integrity sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw== + caching-transform@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-4.0.0.tgz#00d297a4206d71e2163c39eaffa8157ac0651f0f" @@ -8420,6 +8521,11 @@ check-error@^1.0.2: resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= +check-more-types@^2.24.0: + version "2.24.0" + resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" + integrity sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA= + chokidar@3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" @@ -8563,6 +8669,15 @@ cli-spinners@^2.5.0: resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d" integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== +cli-table3@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.1.tgz#36ce9b7af4847f288d3cdd081fbd09bf7bd237b8" + integrity sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA== + dependencies: + string-width "^4.2.0" + optionalDependencies: + colors "1.4.0" + cli-truncate@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" @@ -8571,6 +8686,14 @@ cli-truncate@^0.2.1: slice-ansi "0.0.4" string-width "^1.0.1" +cli-truncate@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" + integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== + dependencies: + slice-ansi "^3.0.0" + string-width "^4.2.0" + cli-width@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" @@ -8704,11 +8827,16 @@ colorette@^1.3.0: resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.3.0.tgz#ff45d2f0edb244069d3b772adeb04fed38d0a0af" integrity sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w== -colorette@^2.0.10, colorette@^2.0.14: +colorette@^2.0.10, colorette@^2.0.14, colorette@^2.0.16: version "2.0.16" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== +colors@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + colorspace@1.1.x: version "1.1.2" resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.2.tgz#e0128950d082b86a2168580796a0aa5d6c68d8c5" @@ -9200,6 +9328,54 @@ csv-parser@^3.0.0: dependencies: minimist "^1.2.0" +cypress@^9.5.3: + version "9.5.3" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-9.5.3.tgz#7c56b50fc1f1aa69ef10b271d895aeb4a1d7999e" + integrity sha512-ItelIVmqMTnKYbo1JrErhsGgQGjWOxCpHT1TfMvwnIXKXN/OSlPjEK7rbCLYDZhejQL99PmUqul7XORI24Ik0A== + dependencies: + "@cypress/request" "^2.88.10" + "@cypress/xvfb" "^1.2.4" + "@types/node" "^14.14.31" + "@types/sinonjs__fake-timers" "8.1.1" + "@types/sizzle" "^2.3.2" + arch "^2.2.0" + blob-util "^2.0.2" + bluebird "^3.7.2" + buffer "^5.6.0" + cachedir "^2.3.0" + chalk "^4.1.0" + check-more-types "^2.24.0" + cli-cursor "^3.1.0" + cli-table3 "~0.6.1" + commander "^5.1.0" + common-tags "^1.8.0" + dayjs "^1.10.4" + debug "^4.3.2" + enquirer "^2.3.6" + eventemitter2 "^6.4.3" + execa "4.1.0" + executable "^4.1.1" + extract-zip "2.0.1" + figures "^3.2.0" + fs-extra "^9.1.0" + getos "^3.2.1" + is-ci "^3.0.0" + is-installed-globally "~0.4.0" + lazy-ass "^1.6.0" + listr2 "^3.8.3" + lodash "^4.17.21" + log-symbols "^4.0.0" + minimist "^1.2.6" + ospath "^1.2.2" + pretty-bytes "^5.6.0" + proxy-from-env "1.0.0" + request-progress "^3.0.0" + semver "^7.3.2" + supports-color "^8.1.1" + tmp "~0.2.1" + untildify "^4.0.0" + yauzl "^2.10.0" + damerau-levenshtein@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz#64368003512a1a6992593741a09a9d31a836f55d" @@ -9260,6 +9436,11 @@ dateformat@^3.0.0: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== +dayjs@^1.10.4: + version "1.11.0" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.0.tgz#009bf7ef2e2ea2d5db2e6583d2d39a4b5061e805" + integrity sha512-JLC809s6Y948/FuCZPm5IX8rRhQwOiyMb2TfVVQEixG7P8Lm/gt5S7yoQZmC8x1UehI9Pb7sksEt4xx14m+7Ug== + debounce@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.0.tgz#44a540abc0ea9943018dc0eaa95cce87f65cd131" @@ -9293,7 +9474,7 @@ debug@4.3.1: dependencies: ms "2.1.2" -debug@^3.1.1, debug@^3.2.7: +debug@^3.1.0, debug@^3.1.1, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -9647,6 +9828,11 @@ dom-accessibility-api@^0.5.6: resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.7.tgz#8c2aa6325968f2933160a0b7dbb380893ddf3e7d" integrity sha512-ml3lJIq9YjUfM9TUnEPvEYWFSwivwIGBPKpewX7tii7fwCazA8yCioGdqQcNsItPpfFvSJ3VIdMQPj60LJhcQA== +dom-accessibility-api@^0.5.9: + version "0.5.13" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.13.tgz#102ee5f25eacce09bdf1cfa5a298f86da473be4b" + integrity sha512-R305kwb5CcMDIpSHUnLyIAp7SrSPBx6F0VfQFB3M75xVMHhXJJIdePYgbPPh1o57vCHNu5QztokWUPsLjWzFqw== + dom-serializer@^1.0.1: version "1.3.2" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" @@ -9890,7 +10076,7 @@ enhanced-resolve@^5.9.2: graceful-fs "^4.2.4" tapable "^2.2.0" -enquirer@^2.3.5: +enquirer@^2.3.5, enquirer@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== @@ -10326,6 +10512,11 @@ event-target-shim@^5.0.0: resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== +eventemitter2@^6.4.3: + version "6.4.5" + resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.5.tgz#97380f758ae24ac15df8353e0cc27f8b95644655" + integrity sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw== + eventemitter3@^3.1.0: version "3.1.2" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" @@ -10348,6 +10539,21 @@ events@^3.2.0: resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== +execa@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" + integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -10363,6 +10569,13 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" +executable@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" + integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg== + dependencies: + pify "^2.2.0" + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -10643,7 +10856,7 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" -figures@^3.0.0: +figures@^3.0.0, figures@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== @@ -11079,7 +11292,7 @@ get-stream@^4.1.0: dependencies: pump "^3.0.0" -get-stream@^5.1.0: +get-stream@^5.0.0, get-stream@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== @@ -11109,6 +11322,13 @@ getopts@2.2.5: resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.2.5.tgz#67a0fe471cacb9c687d817cab6450b96dde8313b" integrity sha512-9jb7AW5p3in+IiJWhQiZmmwkpLaR/ccTWdWQCtZM66HJcHHLegowh4q4tSD7gouUyeNvFWRavfK9GXosQHDpFA== +getos@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/getos/-/getos-3.2.1.tgz#0134d1f4e00eb46144c5a9c0ac4dc087cbb27dc5" + integrity sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q== + dependencies: + async "^3.2.0" + getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -11290,25 +11510,10 @@ goober@^2.1.1: resolved "https://registry.yarnpkg.com/goober/-/goober-2.1.8.tgz#e592c04d093cb38f77b38cfcb012b7811c85765e" integrity sha512-S0C85gCzcfFCMSdjD/CxyQMt1rbf2qEg6hmDzxk2FfD7+7Ogk55m8ZFUMtqNaZM4VVX/qaU9AzSORG+Gf4ZpAQ== -google-auth-library@^6.0.0: - version "6.1.6" - resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-6.1.6.tgz#deacdcdb883d9ed6bac78bb5d79a078877fdf572" - integrity sha512-Q+ZjUEvLQj/lrVHF/IQwRo6p3s8Nc44Zk/DALsN+ac3T4HY/g/3rrufkgtl+nZ1TW7DNAw5cTChdVp4apUXVgQ== - dependencies: - arrify "^2.0.0" - base64-js "^1.3.0" - ecdsa-sig-formatter "^1.0.11" - fast-text-encoding "^1.0.0" - gaxios "^4.0.0" - gcp-metadata "^4.2.0" - gtoken "^5.0.4" - jws "^4.0.0" - lru-cache "^6.0.0" - -google-auth-library@^7.0.0, google-auth-library@^7.0.2, google-auth-library@^7.6.1, google-auth-library@^7.9.2: - version "7.11.0" - resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-7.11.0.tgz#b63699c65037310a424128a854ba7e736704cbdb" - integrity sha512-3S5jn2quRumvh9F/Ubf7GFrIq71HZ5a6vqosgdIu105kkk0WtSqc2jGCRqtWWOLRS8SX3AHACMOEDxhyWAQIcg== +google-auth-library@^7.0.0, google-auth-library@^7.0.2, google-auth-library@^7.14.0, google-auth-library@^7.6.1, google-auth-library@^7.9.2: + version "7.14.1" + resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-7.14.1.tgz#e3483034162f24cc71b95c8a55a210008826213c" + integrity sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA== dependencies: arrify "^2.0.0" base64-js "^1.3.0" @@ -11354,25 +11559,25 @@ google-proto-files@^2.1.0: protobufjs "^6.8.0" walkdir "^0.4.0" -googleapis-common@^4.4.0: - version "4.4.3" - resolved "https://registry.yarnpkg.com/googleapis-common/-/googleapis-common-4.4.3.tgz#a2063adf17b14501a5f426b9cb0685496d835b7d" - integrity sha512-W46WKCk3QtlCCfmZyQIH5zxmDOyeV5Qj+qs7nr2ox08eRkEJMWp6iwv542R/PsokXaGUSrmif4vCC4+rGzRSsQ== +googleapis-common@^5.0.2: + version "5.1.0" + resolved "https://registry.yarnpkg.com/googleapis-common/-/googleapis-common-5.1.0.tgz#845a79471c787e522e03c50d415467140e9e356a" + integrity sha512-RXrif+Gzhq1QAzfjxulbGvAY3FPj8zq/CYcvgjzDbaBNCD6bUl+86I7mUs4DKWHGruuK26ijjR/eDpWIDgNROA== dependencies: extend "^3.0.2" gaxios "^4.0.0" - google-auth-library "^6.0.0" + google-auth-library "^7.14.0" qs "^6.7.0" url-template "^2.0.8" uuid "^8.0.0" -googleapis@^59.0.0: - version "59.0.0" - resolved "https://registry.yarnpkg.com/googleapis/-/googleapis-59.0.0.tgz#aec5c6f5b0b347c9c6996d45fa8ad8176e585fae" - integrity sha512-GV/E4KRN89a4GxSk7D7cwUfRYgcJHR05sOgm/WGdwc/u8dxNXG5lWmz9gF5ZwFGk2yKtVxL4VZNn4zBuZ6rmGg== +googleapis@^100.0.0: + version "100.0.0" + resolved "https://registry.yarnpkg.com/googleapis/-/googleapis-100.0.0.tgz#baeeba7877ee7dd3250643b3803c4a9c24bcf8dd" + integrity sha512-RToFQGY54B756IDbjdyjb1vWFmn03bYpXHB2lIf0eq2UBYsIbYOLZ0kqSomfJnpclEukwEmMF7Jn6Wsev871ew== dependencies: - google-auth-library "^6.0.0" - googleapis-common "^4.4.0" + google-auth-library "^7.0.2" + googleapis-common "^5.0.2" got@^9.6.0: version "9.6.0" @@ -11890,6 +12095,15 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" +http-signature@~1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.3.6.tgz#cb6fbfdf86d1c974f343be94e87f7fc128662cf9" + integrity sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw== + dependencies: + assert-plus "^1.0.0" + jsprim "^2.0.2" + sshpk "^1.14.1" + https-proxy-agent@5.0.0, https-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" @@ -11898,6 +12112,11 @@ https-proxy-agent@5.0.0, https-proxy-agent@^5.0.0: agent-base "6" debug "4" +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -12261,6 +12480,13 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" +is-ci@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867" + integrity sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ== + dependencies: + ci-info "^3.2.0" + is-core-module@^2.2.0, is-core-module@^2.5.0: version "2.6.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.6.0.tgz#d7553b2526fe59b92ba3e40c8df757ec8a709e19" @@ -12391,7 +12617,7 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" -is-installed-globally@^0.4.0: +is-installed-globally@^0.4.0, is-installed-globally@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ== @@ -13394,6 +13620,11 @@ json-schema@0.2.3: resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" @@ -13478,6 +13709,16 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +jsprim@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-2.0.2.tgz#77ca23dbcd4135cd364800d22ff82c2185803d4d" + integrity sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + "jsx-ast-utils@^2.4.1 || ^3.0.0": version "3.2.0" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz#41108d2cec408c3453c1bbe8a4aae9e1e2bd8f82" @@ -13652,6 +13893,11 @@ latest-version@5.1.0, latest-version@^5.1.0: dependencies: package-json "^6.3.0" +lazy-ass@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" + integrity sha1-eZllXoZGwX8In90YfRUNMyTVRRM= + lerna@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/lerna/-/lerna-4.0.0.tgz#b139d685d50ea0ca1be87713a7c2f44a5b678e9e" @@ -13792,6 +14038,20 @@ listr-verbose-renderer@^0.5.0: date-fns "^1.27.2" figures "^2.0.0" +listr2@^3.8.3: + version "3.14.0" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.14.0.tgz#23101cc62e1375fd5836b248276d1d2b51fdbe9e" + integrity sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g== + dependencies: + cli-truncate "^2.1.0" + colorette "^2.0.16" + log-update "^4.0.0" + p-map "^4.0.0" + rfdc "^1.3.0" + rxjs "^7.5.1" + through "^2.3.8" + wrap-ansi "^7.0.0" + listr@^0.14.3: version "0.14.3" resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586" @@ -13988,7 +14248,7 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash.once@^4.0.0: +lodash.once@^4.0.0, lodash.once@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= @@ -14071,6 +14331,16 @@ log-update@^2.3.0: cli-cursor "^2.0.0" wrap-ansi "^3.0.1" +log-update@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" + integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== + dependencies: + ansi-escapes "^4.3.0" + cli-cursor "^3.1.0" + slice-ansi "^4.0.0" + wrap-ansi "^6.2.0" + logform@^2.3.2, logform@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/logform/-/logform-2.4.0.tgz#131651715a17d50f09c2a2c1a524ff1a4164bcfe" @@ -14188,10 +14458,10 @@ lru_map@^0.3.3: resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" integrity sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0= -luxon@^1.25.0, luxon@^1.26.0: - version "1.28.0" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.28.0.tgz#e7f96daad3938c06a62de0fb027115d251251fbf" - integrity sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ== +luxon@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-2.3.1.tgz#f276b1b53fd9a740a60e666a541a7f6dbed4155a" + integrity sha512-I8vnjOmhXsMSlNMZlMkSOvgrxKJl0uOsEzdGgGNZuZPaS9KlefpE9KV95QFftlJSC+1UyCC9/I69R02cz/zcCA== lz-string@^1.4.4: version "1.4.4" @@ -14527,7 +14797,7 @@ minimist-options@4.1.0: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.5: +minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: version "1.2.6" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== @@ -15203,7 +15473,7 @@ npm-registry-fetch@^9.0.0: minizlib "^2.0.0" npm-package-arg "^8.0.0" -npm-run-path@^4.0.1: +npm-run-path@^4.0.0, npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== @@ -15556,6 +15826,11 @@ osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" +ospath@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b" + integrity sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs= + p-cancelable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" @@ -16061,7 +16336,7 @@ picomatch@^2.2.3: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== -pify@^2.3.0: +pify@^2.2.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= @@ -16256,6 +16531,11 @@ prettier@^2.5.1: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a" integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg== +pretty-bytes@^5.6.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" + integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== + pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.0.6: version "27.0.6" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.0.6.tgz#ab770c47b2c6f893a21aefc57b75da63ef49a11f" @@ -16410,6 +16690,11 @@ proxy-addr@~2.0.5: forwarded "0.2.0" ipaddr.js "1.9.1" +proxy-from-env@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" + integrity sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4= + proxy-from-env@1.1.0, proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" @@ -17029,6 +17314,13 @@ replaceall@^0.1.6: resolved "https://registry.yarnpkg.com/replaceall/-/replaceall-0.1.6.tgz#81d81ac7aeb72d7f5c4942adf2697a3220688d8e" integrity sha1-gdgax663LX9cSUKt8ml6MiBojY4= +request-progress@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-3.0.0.tgz#4ca754081c7fec63f505e4faa825aa06cd669dbe" + integrity sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4= + dependencies: + throttleit "^1.0.0" + request@^2.88.0, request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" @@ -17195,6 +17487,11 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== +rfdc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" + integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -17233,6 +17530,13 @@ rxjs@^7.2.0: dependencies: tslib "^2.1.0" +rxjs@^7.5.1: + version "7.5.5" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.5.tgz#2ebad89af0f560f460ad5cc4213219e1f7dd4e9f" + integrity sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw== + dependencies: + tslib "^2.1.0" + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -17585,6 +17889,24 @@ slice-ansi@0.0.4: resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= +slice-ansi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" + integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + slide@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" @@ -17863,6 +18185,21 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= +sshpk@^1.14.1: + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + sshpk@^1.7.0: version "1.16.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" @@ -18194,7 +18531,7 @@ supertest@^6.2.2: methods "^1.1.2" superagent "^7.1.0" -supports-color@8.1.1, supports-color@^8.0.0, supports-color@^8.1.0: +supports-color@8.1.1, supports-color@^8.0.0, supports-color@^8.1.0, supports-color@^8.1.1: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== @@ -18450,6 +18787,11 @@ throat@^6.0.1: resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375" integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w== +throttleit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c" + integrity sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw= + through2@^2.0.0: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" @@ -18507,6 +18849,13 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" +tmp@~0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== + dependencies: + rimraf "^3.0.0" + tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" @@ -18807,6 +19156,11 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + type-fest@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.4.1.tgz#8bdf77743385d8a4f13ba95f610f5ccd68c728f8" @@ -19045,6 +19399,11 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" +untildify@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" + integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== + upath@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/upath/-/upath-2.0.1.tgz#50c73dea68d6f6b990f51d279ce6081665d61a8b" From 28ae767657df865b66a58fcdc88feb6c459f03ca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Apr 2022 22:37:12 +0000 Subject: [PATCH 3/9] Bump next from 12.1.0 to 12.1.4 Bumps [next](https://github.com/vercel/next.js) from 12.1.0 to 12.1.4. - [Release notes](https://github.com/vercel/next.js/releases) - [Changelog](https://github.com/vercel/next.js/blob/canary/release.js) - [Commits](https://github.com/vercel/next.js/compare/v12.1.0...v12.1.4) --- updated-dependencies: - dependency-name: next dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- yarn.lock | 571 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 469 insertions(+), 102 deletions(-) diff --git a/yarn.lock b/yarn.lock index 2e0ae8cf2..421e4acfa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1681,7 +1681,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.17.7", "@babel/runtime@^7.8.4": +"@babel/runtime@^7.14.6", "@babel/runtime@^7.17.7", "@babel/runtime@^7.8.4": version "7.17.8" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.8.tgz#3e56e4aff81befa55ac3ac6a0967349fd1c5bca2" integrity sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA== @@ -1834,6 +1834,38 @@ dependencies: "@cspotcode/source-map-consumer" "0.8.0" +"@cypress/request@^2.88.10": + version "2.88.10" + resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.10.tgz#b66d76b07f860d3a4b8d7a0604d020c662752cce" + integrity sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + http-signature "~1.3.6" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^8.3.2" + +"@cypress/xvfb@^1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@cypress/xvfb/-/xvfb-1.2.4.tgz#2daf42e8275b39f4aa53c14214e557bd14e7748a" + integrity sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q== + dependencies: + debug "^3.1.0" + lodash.once "^4.1.1" + "@dabh/diagnostics@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.2.tgz#290d08f7b381b8f94607dc8f471a12c675f9db31" @@ -3593,10 +3625,10 @@ resolved "https://registry.yarnpkg.com/@n1ru4l/graphql-live-query/-/graphql-live-query-0.9.0.tgz#defaebdd31f625bee49e6745934f36312532b2bc" integrity sha512-BTpWy1e+FxN82RnLz4x1+JcEewVdfmUhV1C6/XYD5AjS7PQp9QFF7K8bCD6gzPTr2l+prvqOyVueQhFJxB1vfg== -"@next/env@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/env/-/env-12.1.0.tgz#73713399399b34aa5a01771fb73272b55b22c314" - integrity sha512-nrIgY6t17FQ9xxwH3jj0a6EOiQ/WDHUos35Hghtr+SWN/ntHIQ7UpuvSi0vaLzZVHQWaDupKI+liO5vANcDeTQ== +"@next/env@12.1.4": + version "12.1.4" + resolved "https://registry.yarnpkg.com/@next/env/-/env-12.1.4.tgz#5af629b43075281ecd7f87938802b7cf5b67e94b" + integrity sha512-7gQwotJDKnfMxxXd8xJ2vsX5AzyDxO3zou0+QOXX8/unypA6icw5+wf6A62yKZ6qQ4UZHHxS68pb6UV+wNneXg== "@next/eslint-plugin-next@12.0.7": version "12.0.7" @@ -3605,60 +3637,65 @@ dependencies: glob "7.1.7" -"@next/swc-android-arm64@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.1.0.tgz#865ba3a9afc204ff2bdeea49dd64d58705007a39" - integrity sha512-/280MLdZe0W03stA69iL+v6I+J1ascrQ6FrXBlXGCsGzrfMaGr7fskMa0T5AhQIVQD4nA/46QQWxG//DYuFBcA== +"@next/swc-android-arm-eabi@12.1.4": + version "12.1.4" + resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.1.4.tgz#c3dae178b7c15ad627d2e9b8dfb38caecb5c4ac7" + integrity sha512-FJg/6a3s2YrUaqZ+/DJZzeZqfxbbWrynQMT1C5wlIEq9aDLXCFpPM/PiOyJh0ahxc0XPmi6uo38Poq+GJTuKWw== -"@next/swc-darwin-arm64@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.1.0.tgz#08e8b411b8accd095009ed12efbc2f1d4d547135" - integrity sha512-R8vcXE2/iONJ1Unf5Ptqjk6LRW3bggH+8drNkkzH4FLEQkHtELhvcmJwkXcuipyQCsIakldAXhRbZmm3YN1vXg== +"@next/swc-android-arm64@12.1.4": + version "12.1.4" + resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.1.4.tgz#f320d60639e19ecffa1f9034829f2d95502a9a51" + integrity sha512-LXraazvQQFBgxIg3Htny6G5V5he9EK7oS4jWtMdTGIikmD/OGByOv8ZjLuVLZLtVm3UIvaAiGtlQSLecxJoJDw== -"@next/swc-darwin-x64@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.1.0.tgz#fcd684497a76e8feaca88db3c394480ff0b007cd" - integrity sha512-ieAz0/J0PhmbZBB8+EA/JGdhRHBogF8BWaeqR7hwveb6SYEIJaDNQy0I+ZN8gF8hLj63bEDxJAs/cEhdnTq+ug== +"@next/swc-darwin-arm64@12.1.4": + version "12.1.4" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.1.4.tgz#fd578278312613eddcf3aee26910100509941b63" + integrity sha512-SSST/dBymecllZxcqTCcSTCu5o1NKk9I+xcvhn/O9nH6GWjgvGgGkNqLbCarCa0jJ1ukvlBA138FagyrmZ/4rQ== -"@next/swc-linux-arm-gnueabihf@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.1.0.tgz#9ec6380a27938a5799aaa6035c205b3c478468a7" - integrity sha512-njUd9hpl6o6A5d08dC0cKAgXKCzm5fFtgGe6i0eko8IAdtAPbtHxtpre3VeSxdZvuGFh+hb0REySQP9T1ttkog== +"@next/swc-darwin-x64@12.1.4": + version "12.1.4" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.1.4.tgz#ace5f80d8c8348efe194f6d7074c6213c52b3944" + integrity sha512-p1lwdX0TVjaoDXQVuAkjtxVBbCL/urgxiMCBwuPDO7TikpXtSRivi+mIzBj5q7ypgICFmIAOW3TyupXeoPRAnA== -"@next/swc-linux-arm64-gnu@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.1.0.tgz#7f4196dff1049cea479607c75b81033ae2dbd093" - integrity sha512-OqangJLkRxVxMhDtcb7Qn1xjzFA3s50EIxY7mljbSCLybU+sByPaWAHY4px97ieOlr2y4S0xdPKkQ3BCAwyo6Q== +"@next/swc-linux-arm-gnueabihf@12.1.4": + version "12.1.4" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.1.4.tgz#2bf2c83863635f19c71c226a2df936e001cce29c" + integrity sha512-67PZlgkCn3TDxacdVft0xqDCL7Io1/C4xbAs0+oSQ0xzp6OzN2RNpuKjHJrJgKd0DsE1XZ9sCP27Qv0591yfyg== -"@next/swc-linux-arm64-musl@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.1.0.tgz#b445f767569cdc2dddee785ca495e1a88c025566" - integrity sha512-hB8cLSt4GdmOpcwRe2UzI5UWn6HHO/vLkr5OTuNvCJ5xGDwpPXelVkYW/0+C3g5axbDW2Tym4S+MQCkkH9QfWA== +"@next/swc-linux-arm64-gnu@12.1.4": + version "12.1.4" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.1.4.tgz#d577190f641c9b4b463719dd6b8953b6ba9be8d9" + integrity sha512-OnOWixhhw7aU22TQdQLYrgpgFq0oA1wGgnjAiHJ+St7MLj82KTDyM9UcymAMbGYy6nG/TFOOHdTmRMtCRNOw0g== -"@next/swc-linux-x64-gnu@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.0.tgz#67610e9be4fbc987de7535f1bcb17e45fe12f90e" - integrity sha512-OKO4R/digvrVuweSw/uBM4nSdyzsBV5EwkUeeG4KVpkIZEe64ZwRpnFB65bC6hGwxIBnTv5NMSnJ+0K/WmG78A== +"@next/swc-linux-arm64-musl@12.1.4": + version "12.1.4" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.1.4.tgz#e70ffe70393d8f9242deecdb282ce5a8fd588b14" + integrity sha512-UoRMzPZnsAavdWtVylYxH8DNC7Uy0i6RrvNwT4PyQVdfANBn2omsUkcH5lgS2O7oaz0nAYLk1vqyZDO7+tJotA== -"@next/swc-linux-x64-musl@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.0.tgz#ea19a23db08a9f2e34ac30401f774cf7d1669d31" - integrity sha512-JohhgAHZvOD3rQY7tlp7NlmvtvYHBYgY0x5ZCecUT6eCCcl9lv6iV3nfu82ErkxNk1H893fqH0FUpznZ/H3pSw== +"@next/swc-linux-x64-gnu@12.1.4": + version "12.1.4" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.4.tgz#91498a130387fb1961902f2bee55863f8e910cff" + integrity sha512-nM+MA/frxlTLUKLJKorctdI20/ugfHRjVEEkcLp/58LGG7slNaP1E5d5dRA1yX6ISjPcQAkywas5VlGCg+uTvA== -"@next/swc-win32-arm64-msvc@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.1.0.tgz#eadf054fc412085659b98e145435bbba200b5283" - integrity sha512-T/3gIE6QEfKIJ4dmJk75v9hhNiYZhQYAoYm4iVo1TgcsuaKLFa+zMPh4056AHiG6n9tn2UQ1CFE8EoybEsqsSw== +"@next/swc-linux-x64-musl@12.1.4": + version "12.1.4" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.4.tgz#78057b03c148c121553d41521ad38f6c732762ff" + integrity sha512-GoRHxkuW4u4yKw734B9SzxJwVdyEJosaZ62P7ifOwcujTxhgBt3y76V2nNUrsSuopcKI2ZTDjaa+2wd5zyeXbA== -"@next/swc-win32-ia32-msvc@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.1.0.tgz#68faeae10c89f698bf9d28759172b74c9c21bda1" - integrity sha512-iwnKgHJdqhIW19H9PRPM9j55V6RdcOo6rX+5imx832BCWzkDbyomWnlzBfr6ByUYfhohb8QuH4hSGEikpPqI0Q== +"@next/swc-win32-arm64-msvc@12.1.4": + version "12.1.4" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.1.4.tgz#05bbaabacac23b8edf6caa99eb86b17550a09051" + integrity sha512-6TQkQze0ievXwHJcVUrIULwCYVe3ccX6T0JgZ1SiMeXpHxISN7VJF/O8uSCw1JvXZYZ6ud0CJ7nfC5HXivgfPg== -"@next/swc-win32-x64-msvc@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.0.tgz#d27e7e76c87a460a4da99c5bfdb1618dcd6cd064" - integrity sha512-aBvcbMwuanDH4EMrL2TthNJy+4nP59Bimn8egqv6GHMVj0a44cU6Au4PjOhLNqEh9l+IpRGBqMTzec94UdC5xg== +"@next/swc-win32-ia32-msvc@12.1.4": + version "12.1.4" + resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.1.4.tgz#8fd2fb48f04a2802e51fc320878bf6b411c1c866" + integrity sha512-CsbX/IXuZ5VSmWCpSetG2HD6VO5FTsO39WNp2IR2Ut/uom9XtLDJAZqjQEnbUTLGHuwDKFjrIO3LkhtROXLE/g== + +"@next/swc-win32-x64-msvc@12.1.4": + version "12.1.4" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.4.tgz#a72ed44c9b1f850986a30fe36c59e01f8a79b5f3" + integrity sha512-JtYuWzKXKLDMgE/xTcFtCm1MiCIRaAc5XYZfYX3n/ZWSI1SJS/GMm+Su0SAHJgRFavJh6U/p998YwO/iGTIgqQ== "@nodelib/fs.scandir@2.1.3": version "2.1.3" @@ -5887,6 +5924,14 @@ dependencies: defer-to-connect "^1.0.1" +"@testing-library/cypress@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@testing-library/cypress/-/cypress-8.0.2.tgz#b13f0ff2424dec4368b6670dfbfb7e43af8eefc9" + integrity sha512-KVdm7n37sg/A4e3wKMD4zUl0NpzzVhx06V9Tf0hZHZ7nrZ4yFva6Zwg2EFF1VzHkEfN/ahUzRtT1qiW+vuWnJw== + dependencies: + "@babel/runtime" "^7.14.6" + "@testing-library/dom" "^8.1.0" + "@testing-library/dom@^8.0.0": version "8.1.0" resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.1.0.tgz#f8358b1883844ea569ba76b7e94582168df5370d" @@ -5901,6 +5946,20 @@ lz-string "^1.4.4" pretty-format "^27.0.2" +"@testing-library/dom@^8.1.0": + version "8.12.0" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.12.0.tgz#fef5e545533fb084175dda6509ee71d7d2f72e23" + integrity sha512-rBrJk5WjI02X1edtiUcZhgyhgBhiut96r5Jp8J5qktKdcvLcZpKDW8i2hkGMMItxrghjXuQ5AM6aE0imnFawaw== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/runtime" "^7.12.5" + "@types/aria-query" "^4.2.0" + aria-query "^5.0.0" + chalk "^4.1.0" + dom-accessibility-api "^0.5.9" + lz-string "^1.4.4" + pretty-format "^27.0.2" + "@testing-library/jest-dom@^5.16.1": version "5.16.2" resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.2.tgz#f329b36b44aa6149cd6ced9adf567f8b6aa1c959" @@ -6417,6 +6476,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.32.tgz#2ca61c9ef8c77f6fa1733be9e623ceb0d372ad96" integrity sha512-JcII3D5/OapPGx+eJ+Ik1SQGyt6WvuqdRfh9jUwL6/iHGjmyOriBDciBUu7lEIBTL2ijxwrR70WUnw5AEDmFvQ== +"@types/node@^14.14.31": + version "14.18.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.12.tgz#0d4557fd3b94497d793efd4e7d92df2f83b4ef24" + integrity sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A== + "@types/nodemailer@^6.4.4": version "6.4.4" resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.4.tgz#c265f7e7a51df587597b3a49a023acaf0c741f4b" @@ -6567,6 +6631,16 @@ "@types/mime" "^1" "@types/node" "*" +"@types/sinonjs__fake-timers@8.1.1": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz#b49c2c70150141a15e0fa7e79cf1f92a72934ce3" + integrity sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g== + +"@types/sizzle@^2.3.2": + version "2.3.3" + resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.3.tgz#ff5e2f1902969d305225a047c8a0fd5c915cebef" + integrity sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ== + "@types/sockjs@^0.3.33": version "0.3.33" resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" @@ -7216,6 +7290,13 @@ ansi-escapes@^4.2.1, ansi-escapes@^4.3.1: dependencies: type-fest "^0.11.0" +ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + ansi-html-community@^0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" @@ -7417,6 +7498,11 @@ aproba@^2.0.0: resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== +arch@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" + integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== + archy@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" @@ -7614,6 +7700,11 @@ ast-types-flow@^0.0.7: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + async-retry@^1.2.1, async-retry@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280" @@ -7628,7 +7719,7 @@ async@^2.6.2: dependencies: lodash "^4.17.14" -async@^3.2.3: +async@^3.2.0, async@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/async/-/async-3.2.3.tgz#ac53dafd3f4720ee9e8a160628f18ea91df196c9" integrity sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g== @@ -7928,6 +8019,16 @@ bl@^4.0.3, bl@^4.1.0: inherits "^2.0.4" readable-stream "^3.4.0" +blob-util@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb" + integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ== + +bluebird@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + body-parser@1.19.0: version "1.19.0" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" @@ -8092,7 +8193,7 @@ buffer-writer@2.0.0: resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== -buffer@^5.2.1, buffer@^5.5.0, buffer@^5.7.0: +buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0, buffer@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -8199,6 +8300,11 @@ cacheable-request@^6.0.0: normalize-url "^4.1.0" responselike "^1.0.2" +cachedir@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8" + integrity sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw== + caching-transform@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-4.0.0.tgz#00d297a4206d71e2163c39eaffa8157ac0651f0f" @@ -8257,12 +8363,7 @@ 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.30001251, caniuse-lite@^1.0.30001283, caniuse-lite@^1.0.30001286: - version "1.0.30001311" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001311.tgz#682ef3f4e617f1a177ad943de59775ed3032e511" - integrity sha512-mleTFtFKfykEeW34EyfhGIFjGCqzhh38Y0LhdQ9aWF+HorZTtdgKV/1hEE0NlFkG2ubvisPV6l400tlbPys98A== - -caniuse-lite@^1.0.30001317: +caniuse-lite@^1.0.30001251, caniuse-lite@^1.0.30001283, caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001317: version "1.0.30001319" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001319.tgz#eb4da4eb3ecdd409f7ba1907820061d56096e88f" integrity sha512-xjlIAFHucBRSMUo1kb5D4LYgcN1M45qdKP++lhqowDpwJwGkpIRTt5qQqnhxjj1vHcI7nrJxWhCC1ATrCEBTcw== @@ -8420,6 +8521,11 @@ check-error@^1.0.2: resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= +check-more-types@^2.24.0: + version "2.24.0" + resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" + integrity sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA= + chokidar@3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" @@ -8563,6 +8669,15 @@ cli-spinners@^2.5.0: resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d" integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== +cli-table3@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.1.tgz#36ce9b7af4847f288d3cdd081fbd09bf7bd237b8" + integrity sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA== + dependencies: + string-width "^4.2.0" + optionalDependencies: + colors "1.4.0" + cli-truncate@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" @@ -8571,6 +8686,14 @@ cli-truncate@^0.2.1: slice-ansi "0.0.4" string-width "^1.0.1" +cli-truncate@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" + integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== + dependencies: + slice-ansi "^3.0.0" + string-width "^4.2.0" + cli-width@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" @@ -8704,11 +8827,16 @@ colorette@^1.3.0: resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.3.0.tgz#ff45d2f0edb244069d3b772adeb04fed38d0a0af" integrity sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w== -colorette@^2.0.10, colorette@^2.0.14: +colorette@^2.0.10, colorette@^2.0.14, colorette@^2.0.16: version "2.0.16" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== +colors@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + colorspace@1.1.x: version "1.1.2" resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.2.tgz#e0128950d082b86a2168580796a0aa5d6c68d8c5" @@ -9200,6 +9328,54 @@ csv-parser@^3.0.0: dependencies: minimist "^1.2.0" +cypress@^9.5.3: + version "9.5.3" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-9.5.3.tgz#7c56b50fc1f1aa69ef10b271d895aeb4a1d7999e" + integrity sha512-ItelIVmqMTnKYbo1JrErhsGgQGjWOxCpHT1TfMvwnIXKXN/OSlPjEK7rbCLYDZhejQL99PmUqul7XORI24Ik0A== + dependencies: + "@cypress/request" "^2.88.10" + "@cypress/xvfb" "^1.2.4" + "@types/node" "^14.14.31" + "@types/sinonjs__fake-timers" "8.1.1" + "@types/sizzle" "^2.3.2" + arch "^2.2.0" + blob-util "^2.0.2" + bluebird "^3.7.2" + buffer "^5.6.0" + cachedir "^2.3.0" + chalk "^4.1.0" + check-more-types "^2.24.0" + cli-cursor "^3.1.0" + cli-table3 "~0.6.1" + commander "^5.1.0" + common-tags "^1.8.0" + dayjs "^1.10.4" + debug "^4.3.2" + enquirer "^2.3.6" + eventemitter2 "^6.4.3" + execa "4.1.0" + executable "^4.1.1" + extract-zip "2.0.1" + figures "^3.2.0" + fs-extra "^9.1.0" + getos "^3.2.1" + is-ci "^3.0.0" + is-installed-globally "~0.4.0" + lazy-ass "^1.6.0" + listr2 "^3.8.3" + lodash "^4.17.21" + log-symbols "^4.0.0" + minimist "^1.2.6" + ospath "^1.2.2" + pretty-bytes "^5.6.0" + proxy-from-env "1.0.0" + request-progress "^3.0.0" + semver "^7.3.2" + supports-color "^8.1.1" + tmp "~0.2.1" + untildify "^4.0.0" + yauzl "^2.10.0" + damerau-levenshtein@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz#64368003512a1a6992593741a09a9d31a836f55d" @@ -9260,6 +9436,11 @@ dateformat@^3.0.0: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== +dayjs@^1.10.4: + version "1.11.0" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.0.tgz#009bf7ef2e2ea2d5db2e6583d2d39a4b5061e805" + integrity sha512-JLC809s6Y948/FuCZPm5IX8rRhQwOiyMb2TfVVQEixG7P8Lm/gt5S7yoQZmC8x1UehI9Pb7sksEt4xx14m+7Ug== + debounce@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.0.tgz#44a540abc0ea9943018dc0eaa95cce87f65cd131" @@ -9293,7 +9474,7 @@ debug@4.3.1: dependencies: ms "2.1.2" -debug@^3.1.1, debug@^3.2.7: +debug@^3.1.0, debug@^3.1.1, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -9647,6 +9828,11 @@ dom-accessibility-api@^0.5.6: resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.7.tgz#8c2aa6325968f2933160a0b7dbb380893ddf3e7d" integrity sha512-ml3lJIq9YjUfM9TUnEPvEYWFSwivwIGBPKpewX7tii7fwCazA8yCioGdqQcNsItPpfFvSJ3VIdMQPj60LJhcQA== +dom-accessibility-api@^0.5.9: + version "0.5.13" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.13.tgz#102ee5f25eacce09bdf1cfa5a298f86da473be4b" + integrity sha512-R305kwb5CcMDIpSHUnLyIAp7SrSPBx6F0VfQFB3M75xVMHhXJJIdePYgbPPh1o57vCHNu5QztokWUPsLjWzFqw== + dom-serializer@^1.0.1: version "1.3.2" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" @@ -9890,7 +10076,7 @@ enhanced-resolve@^5.9.2: graceful-fs "^4.2.4" tapable "^2.2.0" -enquirer@^2.3.5: +enquirer@^2.3.5, enquirer@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== @@ -10326,6 +10512,11 @@ event-target-shim@^5.0.0: resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== +eventemitter2@^6.4.3: + version "6.4.5" + resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.5.tgz#97380f758ae24ac15df8353e0cc27f8b95644655" + integrity sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw== + eventemitter3@^3.1.0: version "3.1.2" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" @@ -10348,6 +10539,21 @@ events@^3.2.0: resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== +execa@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" + integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -10363,6 +10569,13 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" +executable@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" + integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg== + dependencies: + pify "^2.2.0" + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -10643,7 +10856,7 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" -figures@^3.0.0: +figures@^3.0.0, figures@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== @@ -11079,7 +11292,7 @@ get-stream@^4.1.0: dependencies: pump "^3.0.0" -get-stream@^5.1.0: +get-stream@^5.0.0, get-stream@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== @@ -11109,6 +11322,13 @@ getopts@2.2.5: resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.2.5.tgz#67a0fe471cacb9c687d817cab6450b96dde8313b" integrity sha512-9jb7AW5p3in+IiJWhQiZmmwkpLaR/ccTWdWQCtZM66HJcHHLegowh4q4tSD7gouUyeNvFWRavfK9GXosQHDpFA== +getos@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/getos/-/getos-3.2.1.tgz#0134d1f4e00eb46144c5a9c0ac4dc087cbb27dc5" + integrity sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q== + dependencies: + async "^3.2.0" + getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -11890,6 +12110,15 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" +http-signature@~1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.3.6.tgz#cb6fbfdf86d1c974f343be94e87f7fc128662cf9" + integrity sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw== + dependencies: + assert-plus "^1.0.0" + jsprim "^2.0.2" + sshpk "^1.14.1" + https-proxy-agent@5.0.0, https-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" @@ -11898,6 +12127,11 @@ https-proxy-agent@5.0.0, https-proxy-agent@^5.0.0: agent-base "6" debug "4" +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -12261,6 +12495,13 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" +is-ci@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867" + integrity sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ== + dependencies: + ci-info "^3.2.0" + is-core-module@^2.2.0, is-core-module@^2.5.0: version "2.6.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.6.0.tgz#d7553b2526fe59b92ba3e40c8df757ec8a709e19" @@ -12391,7 +12632,7 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" -is-installed-globally@^0.4.0: +is-installed-globally@^0.4.0, is-installed-globally@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ== @@ -13394,6 +13635,11 @@ json-schema@0.2.3: resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" @@ -13478,6 +13724,16 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +jsprim@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-2.0.2.tgz#77ca23dbcd4135cd364800d22ff82c2185803d4d" + integrity sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + "jsx-ast-utils@^2.4.1 || ^3.0.0": version "3.2.0" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz#41108d2cec408c3453c1bbe8a4aae9e1e2bd8f82" @@ -13652,6 +13908,11 @@ latest-version@5.1.0, latest-version@^5.1.0: dependencies: package-json "^6.3.0" +lazy-ass@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" + integrity sha1-eZllXoZGwX8In90YfRUNMyTVRRM= + lerna@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/lerna/-/lerna-4.0.0.tgz#b139d685d50ea0ca1be87713a7c2f44a5b678e9e" @@ -13792,6 +14053,20 @@ listr-verbose-renderer@^0.5.0: date-fns "^1.27.2" figures "^2.0.0" +listr2@^3.8.3: + version "3.14.0" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.14.0.tgz#23101cc62e1375fd5836b248276d1d2b51fdbe9e" + integrity sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g== + dependencies: + cli-truncate "^2.1.0" + colorette "^2.0.16" + log-update "^4.0.0" + p-map "^4.0.0" + rfdc "^1.3.0" + rxjs "^7.5.1" + through "^2.3.8" + wrap-ansi "^7.0.0" + listr@^0.14.3: version "0.14.3" resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586" @@ -13988,7 +14263,7 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash.once@^4.0.0: +lodash.once@^4.0.0, lodash.once@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= @@ -14071,6 +14346,16 @@ log-update@^2.3.0: cli-cursor "^2.0.0" wrap-ansi "^3.0.1" +log-update@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" + integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== + dependencies: + ansi-escapes "^4.3.0" + cli-cursor "^3.1.0" + slice-ansi "^4.0.0" + wrap-ansi "^6.2.0" + logform@^2.3.2, logform@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/logform/-/logform-2.4.0.tgz#131651715a17d50f09c2a2c1a524ff1a4164bcfe" @@ -14188,10 +14473,10 @@ lru_map@^0.3.3: resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" integrity sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0= -luxon@^1.25.0, luxon@^1.26.0: - version "1.28.0" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.28.0.tgz#e7f96daad3938c06a62de0fb027115d251251fbf" - integrity sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ== +luxon@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-2.3.1.tgz#f276b1b53fd9a740a60e666a541a7f6dbed4155a" + integrity sha512-I8vnjOmhXsMSlNMZlMkSOvgrxKJl0uOsEzdGgGNZuZPaS9KlefpE9KV95QFftlJSC+1UyCC9/I69R02cz/zcCA== lz-string@^1.4.4: version "1.4.4" @@ -14527,7 +14812,7 @@ minimist-options@4.1.0: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.5: +minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: version "1.2.6" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== @@ -14853,27 +15138,27 @@ newline@0.0.3: integrity sha1-D2p0STIj26BP59v7bNyAS/fkbdA= next@^12.1.0: - version "12.1.0" - resolved "https://registry.yarnpkg.com/next/-/next-12.1.0.tgz#c33d753b644be92fc58e06e5a214f143da61dd5d" - integrity sha512-s885kWvnIlxsUFHq9UGyIyLiuD0G3BUC/xrH0CEnH5lHEWkwQcHOORgbDF0hbrW9vr/7am4ETfX4A7M6DjrE7Q== + version "12.1.4" + resolved "https://registry.yarnpkg.com/next/-/next-12.1.4.tgz#597a9bdec7aec778b442c4f6d41afd2c64a54b23" + integrity sha512-DA4g97BM4Z0nKtDvCTm58RxdvoQyYzeg0AeVbh0N4Y/D8ELrNu47lQeEgRGF8hV4eQ+Sal90zxrJQQG/mPQ8CQ== dependencies: - "@next/env" "12.1.0" + "@next/env" "12.1.4" caniuse-lite "^1.0.30001283" postcss "8.4.5" - styled-jsx "5.0.0" - use-subscription "1.5.1" + styled-jsx "5.0.1" optionalDependencies: - "@next/swc-android-arm64" "12.1.0" - "@next/swc-darwin-arm64" "12.1.0" - "@next/swc-darwin-x64" "12.1.0" - "@next/swc-linux-arm-gnueabihf" "12.1.0" - "@next/swc-linux-arm64-gnu" "12.1.0" - "@next/swc-linux-arm64-musl" "12.1.0" - "@next/swc-linux-x64-gnu" "12.1.0" - "@next/swc-linux-x64-musl" "12.1.0" - "@next/swc-win32-arm64-msvc" "12.1.0" - "@next/swc-win32-ia32-msvc" "12.1.0" - "@next/swc-win32-x64-msvc" "12.1.0" + "@next/swc-android-arm-eabi" "12.1.4" + "@next/swc-android-arm64" "12.1.4" + "@next/swc-darwin-arm64" "12.1.4" + "@next/swc-darwin-x64" "12.1.4" + "@next/swc-linux-arm-gnueabihf" "12.1.4" + "@next/swc-linux-arm64-gnu" "12.1.4" + "@next/swc-linux-arm64-musl" "12.1.4" + "@next/swc-linux-x64-gnu" "12.1.4" + "@next/swc-linux-x64-musl" "12.1.4" + "@next/swc-win32-arm64-msvc" "12.1.4" + "@next/swc-win32-ia32-msvc" "12.1.4" + "@next/swc-win32-x64-msvc" "12.1.4" nise@^1.5.2: version "1.5.3" @@ -15203,7 +15488,7 @@ npm-registry-fetch@^9.0.0: minizlib "^2.0.0" npm-package-arg "^8.0.0" -npm-run-path@^4.0.1: +npm-run-path@^4.0.0, npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== @@ -15556,6 +15841,11 @@ osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" +ospath@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b" + integrity sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs= + p-cancelable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" @@ -16061,7 +16351,7 @@ picomatch@^2.2.3: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== -pify@^2.3.0: +pify@^2.2.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= @@ -16181,7 +16471,7 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@8.4.5, postcss@^8.0.2: +postcss@8.4.5: version "8.4.5" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95" integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg== @@ -16190,7 +16480,7 @@ postcss@8.4.5, postcss@^8.0.2: picocolors "^1.0.0" source-map-js "^1.0.1" -postcss@^8.4.7: +postcss@^8.0.2, postcss@^8.4.7: version "8.4.12" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.12.tgz#1e7de78733b28970fa4743f7da6f3763648b1905" integrity sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg== @@ -16256,6 +16546,11 @@ prettier@^2.5.1: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a" integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg== +pretty-bytes@^5.6.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" + integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== + pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.0.6: version "27.0.6" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.0.6.tgz#ab770c47b2c6f893a21aefc57b75da63ef49a11f" @@ -16410,6 +16705,11 @@ proxy-addr@~2.0.5: forwarded "0.2.0" ipaddr.js "1.9.1" +proxy-from-env@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" + integrity sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4= + proxy-from-env@1.1.0, proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" @@ -17029,6 +17329,13 @@ replaceall@^0.1.6: resolved "https://registry.yarnpkg.com/replaceall/-/replaceall-0.1.6.tgz#81d81ac7aeb72d7f5c4942adf2697a3220688d8e" integrity sha1-gdgax663LX9cSUKt8ml6MiBojY4= +request-progress@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-3.0.0.tgz#4ca754081c7fec63f505e4faa825aa06cd669dbe" + integrity sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4= + dependencies: + throttleit "^1.0.0" + request@^2.88.0, request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" @@ -17195,6 +17502,11 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== +rfdc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" + integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -17233,6 +17545,13 @@ rxjs@^7.2.0: dependencies: tslib "^2.1.0" +rxjs@^7.5.1: + version "7.5.5" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.5.tgz#2ebad89af0f560f460ad5cc4213219e1f7dd4e9f" + integrity sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw== + dependencies: + tslib "^2.1.0" + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -17585,6 +17904,24 @@ slice-ansi@0.0.4: resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= +slice-ansi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" + integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + slide@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" @@ -17863,6 +18200,21 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= +sshpk@^1.14.1: + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + sshpk@^1.7.0: version "1.16.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" @@ -18153,10 +18505,10 @@ style-loader@^3.3.1: resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575" integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ== -styled-jsx@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.0.tgz#816b4b92e07b1786c6b7111821750e0ba4d26e77" - integrity sha512-qUqsWoBquEdERe10EW8vLp3jT25s/ssG1/qX5gZ4wu15OZpmSMFI2v+fWlRhLfykA5rFtlJ1ME8A8pm/peV4WA== +styled-jsx@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.1.tgz#78fecbbad2bf95ce6cd981a08918ce4696f5fc80" + integrity sha512-+PIZ/6Uk40mphiQJJI1202b+/dYeTVd9ZnMPR80pgiWbjIwvN2zIp4r9et0BgqBuShh48I0gttPlAXA7WVvBxw== subscriptions-transport-ws@^0.11.0: version "0.11.0" @@ -18194,7 +18546,7 @@ supertest@^6.2.2: methods "^1.1.2" superagent "^7.1.0" -supports-color@8.1.1, supports-color@^8.0.0, supports-color@^8.1.0: +supports-color@8.1.1, supports-color@^8.0.0, supports-color@^8.1.0, supports-color@^8.1.1: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== @@ -18450,6 +18802,11 @@ throat@^6.0.1: resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375" integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w== +throttleit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c" + integrity sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw= + through2@^2.0.0: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" @@ -18507,6 +18864,13 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" +tmp@~0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== + dependencies: + rimraf "^3.0.0" + tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" @@ -18807,6 +19171,11 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + type-fest@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.4.1.tgz#8bdf77743385d8a4f13ba95f610f5ccd68c728f8" @@ -19045,6 +19414,11 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" +untildify@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" + integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== + upath@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/upath/-/upath-2.0.1.tgz#50c73dea68d6f6b990f51d279ce6081665d61a8b" @@ -19138,13 +19512,6 @@ use-sidecar@^1.0.1: detect-node-es "^1.1.0" tslib "^1.9.3" -use-subscription@1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1" - integrity sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA== - dependencies: - object-assign "^4.1.1" - use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" From bb665a704b5ff7bad49313af5eec78d8b99a6722 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Tue, 12 Apr 2022 12:08:02 +0800 Subject: [PATCH 4/9] make label name <= 64 char length --- packages/api/src/schema.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/api/src/schema.ts b/packages/api/src/schema.ts index c31bf5838..109624af6 100755 --- a/packages/api/src/schema.ts +++ b/packages/api/src/schema.ts @@ -1272,9 +1272,9 @@ const schema = gql` union LabelsResult = LabelsSuccess | LabelsError input CreateLabelInput { - name: String! + name: String! @sanitize(maxLength: 64) color: String! - description: String + description: String @sanitize(maxLength: 100) } type CreateLabelSuccess { From 2ebdaba780a140f84dccd7eddd9f1566b9dd3090 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Tue, 12 Apr 2022 12:11:45 +0800 Subject: [PATCH 5/9] add generate api key api and test (#392) * add generate api key api and test * test if user can make api call with the api key --- packages/api/src/generated/graphql.ts | 47 +++++++++++++++++++ packages/api/src/generated/schema.graphql | 15 ++++++ packages/api/src/resolvers/api_key/index.ts | 40 ++++++++++++++++ .../api/src/resolvers/function_resolvers.ts | 3 ++ packages/api/src/resolvers/types.ts | 1 + packages/api/src/schema.ts | 15 ++++++ packages/api/src/utils/auth.ts | 7 +++ packages/api/test/resolvers/api_key.test.ts | 47 +++++++++++++++++++ 8 files changed, 175 insertions(+) create mode 100644 packages/api/src/resolvers/api_key/index.ts create mode 100644 packages/api/test/resolvers/api_key.test.ts diff --git a/packages/api/src/generated/graphql.ts b/packages/api/src/generated/graphql.ts index 435d1e2ab..3d392ec03 100644 --- a/packages/api/src/generated/graphql.ts +++ b/packages/api/src/generated/graphql.ts @@ -521,6 +521,22 @@ export type FeedArticlesSuccess = { pageInfo: PageInfo; }; +export type GenerateApiKeyError = { + __typename?: 'GenerateApiKeyError'; + errorCodes: Array; +}; + +export enum GenerateApiKeyErrorCode { + BadRequest = 'BAD_REQUEST' +} + +export type GenerateApiKeyResult = GenerateApiKeyError | GenerateApiKeySuccess; + +export type GenerateApiKeySuccess = { + __typename?: 'GenerateApiKeySuccess'; + apiKey: Scalars['String']; +}; + export type GetFollowersError = { __typename?: 'GetFollowersError'; errorCodes: Array; @@ -771,6 +787,7 @@ export type Mutation = { deleteNewsletterEmail: DeleteNewsletterEmailResult; deleteReaction: DeleteReactionResult; deleteReminder: DeleteReminderResult; + generateApiKey: GenerateApiKeyResult; googleLogin: LoginResult; googleSignup: GoogleSignupResult; login: LoginResult; @@ -867,6 +884,11 @@ export type MutationDeleteReminderArgs = { }; +export type MutationGenerateApiKeyArgs = { + scope?: InputMaybe; +}; + + export type MutationGoogleLoginArgs = { input: GoogleLoginInput; }; @@ -1989,6 +2011,10 @@ export type ResolversTypes = { FeedArticlesResult: ResolversTypes['FeedArticlesError'] | ResolversTypes['FeedArticlesSuccess']; FeedArticlesSuccess: ResolverTypeWrapper; Float: ResolverTypeWrapper; + GenerateApiKeyError: ResolverTypeWrapper; + GenerateApiKeyErrorCode: GenerateApiKeyErrorCode; + GenerateApiKeyResult: ResolversTypes['GenerateApiKeyError'] | ResolversTypes['GenerateApiKeySuccess']; + GenerateApiKeySuccess: ResolverTypeWrapper; GetFollowersError: ResolverTypeWrapper; GetFollowersErrorCode: GetFollowersErrorCode; GetFollowersResult: ResolversTypes['GetFollowersError'] | ResolversTypes['GetFollowersSuccess']; @@ -2252,6 +2278,9 @@ export type ResolversParentTypes = { FeedArticlesResult: ResolversParentTypes['FeedArticlesError'] | ResolversParentTypes['FeedArticlesSuccess']; FeedArticlesSuccess: FeedArticlesSuccess; Float: Scalars['Float']; + GenerateApiKeyError: GenerateApiKeyError; + GenerateApiKeyResult: ResolversParentTypes['GenerateApiKeyError'] | ResolversParentTypes['GenerateApiKeySuccess']; + GenerateApiKeySuccess: GenerateApiKeySuccess; GetFollowersError: GetFollowersError; GetFollowersResult: ResolversParentTypes['GetFollowersError'] | ResolversParentTypes['GetFollowersSuccess']; GetFollowersSuccess: GetFollowersSuccess; @@ -2763,6 +2792,20 @@ export type FeedArticlesSuccessResolvers; }; +export type GenerateApiKeyErrorResolvers = { + errorCodes?: Resolver, ParentType, ContextType>; + __isTypeOf?: IsTypeOfResolverFn; +}; + +export type GenerateApiKeyResultResolvers = { + __resolveType: TypeResolveFn<'GenerateApiKeyError' | 'GenerateApiKeySuccess', ParentType, ContextType>; +}; + +export type GenerateApiKeySuccessResolvers = { + apiKey?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}; + export type GetFollowersErrorResolvers = { errorCodes?: Resolver, ParentType, ContextType>; __isTypeOf?: IsTypeOfResolverFn; @@ -2957,6 +3000,7 @@ export type MutationResolvers>; deleteReaction?: Resolver>; deleteReminder?: Resolver>; + generateApiKey?: Resolver>; googleLogin?: Resolver>; googleSignup?: Resolver>; login?: Resolver>; @@ -3521,6 +3565,9 @@ export type Resolvers = { FeedArticlesError?: FeedArticlesErrorResolvers; FeedArticlesResult?: FeedArticlesResultResolvers; FeedArticlesSuccess?: FeedArticlesSuccessResolvers; + GenerateApiKeyError?: GenerateApiKeyErrorResolvers; + GenerateApiKeyResult?: GenerateApiKeyResultResolvers; + GenerateApiKeySuccess?: GenerateApiKeySuccessResolvers; GetFollowersError?: GetFollowersErrorResolvers; GetFollowersResult?: GetFollowersResultResolvers; GetFollowersSuccess?: GetFollowersSuccessResolvers; diff --git a/packages/api/src/generated/schema.graphql b/packages/api/src/generated/schema.graphql index 20055efb9..74a59f9de 100644 --- a/packages/api/src/generated/schema.graphql +++ b/packages/api/src/generated/schema.graphql @@ -457,6 +457,20 @@ type FeedArticlesSuccess { pageInfo: PageInfo! } +type GenerateApiKeyError { + errorCodes: [GenerateApiKeyErrorCode!]! +} + +enum GenerateApiKeyErrorCode { + BAD_REQUEST +} + +union GenerateApiKeyResult = GenerateApiKeyError | GenerateApiKeySuccess + +type GenerateApiKeySuccess { + apiKey: String! +} + type GetFollowersError { errorCodes: [GetFollowersErrorCode!]! } @@ -684,6 +698,7 @@ type Mutation { deleteNewsletterEmail(newsletterEmailId: ID!): DeleteNewsletterEmailResult! deleteReaction(id: ID!): DeleteReactionResult! deleteReminder(id: ID!): DeleteReminderResult! + generateApiKey(scope: String): GenerateApiKeyResult! googleLogin(input: GoogleLoginInput!): LoginResult! googleSignup(input: GoogleSignupInput!): GoogleSignupResult! login(input: LoginInput!): LoginResult! diff --git a/packages/api/src/resolvers/api_key/index.ts b/packages/api/src/resolvers/api_key/index.ts new file mode 100644 index 000000000..9b70b59b6 --- /dev/null +++ b/packages/api/src/resolvers/api_key/index.ts @@ -0,0 +1,40 @@ +import { + GenerateApiKeyError, + GenerateApiKeyErrorCode, + GenerateApiKeySuccess, + MutationGenerateApiKeyArgs, +} from '../../generated/graphql' +import { generateApiKey } from '../../utils/auth' +import { analytics } from '../../utils/analytics' +import { env } from '../../env' +import { authorized } from '../../utils/helpers' + +export const generateApiKeyResolver = authorized< + GenerateApiKeySuccess, + GenerateApiKeyError, + MutationGenerateApiKeyArgs +>((_, { scope }, { claims }) => { + try { + console.log('generateApiKeyResolver', scope) + + analytics.track({ + userId: claims.uid, + event: 'generate_api_key', + properties: { + scope, + env: env.server.apiEnv, + }, + }) + + const apiKey = generateApiKey({ + iat: new Date().getTime(), + scope: scope || 'all', + uid: claims.uid, + }) + + return { apiKey } + } catch (error) { + console.error(error) + return { errorCodes: [GenerateApiKeyErrorCode.BadRequest] } + } +}) diff --git a/packages/api/src/resolvers/function_resolvers.ts b/packages/api/src/resolvers/function_resolvers.ts index 2186f701b..000ccf22e 100644 --- a/packages/api/src/resolvers/function_resolvers.ts +++ b/packages/api/src/resolvers/function_resolvers.ts @@ -79,6 +79,7 @@ import { generateUploadFilePathName, } from '../utils/uploads' import { getPageById, getPageByParam } from '../elastic' +import { generateApiKeyResolver } from './api_key' /* eslint-disable @typescript-eslint/naming-convention */ type ResultResolveType = { @@ -138,6 +139,7 @@ export const functionResolvers = { login: loginResolver, signup: signupResolver, setLabels: setLabelsResolver, + generateApiKey: generateApiKeyResolver, }, Query: { me: getMeUserResolver, @@ -529,4 +531,5 @@ export const functionResolvers = { ...resultResolveTypeResolver('Login'), ...resultResolveTypeResolver('Signup'), ...resultResolveTypeResolver('SetLabels'), + ...resultResolveTypeResolver('GenerateApiKey'), } diff --git a/packages/api/src/resolvers/types.ts b/packages/api/src/resolvers/types.ts index d9590f5fc..723346ff2 100644 --- a/packages/api/src/resolvers/types.ts +++ b/packages/api/src/resolvers/types.ts @@ -20,6 +20,7 @@ export interface Claims { uid: string iat: number userRole?: string + scope?: string // scope is used for api key like page:search } export type ClaimsToSet = { diff --git a/packages/api/src/schema.ts b/packages/api/src/schema.ts index c31bf5838..f18a3786b 100755 --- a/packages/api/src/schema.ts +++ b/packages/api/src/schema.ts @@ -1379,6 +1379,20 @@ const schema = gql` NOT_FOUND } + union GenerateApiKeyResult = GenerateApiKeySuccess | GenerateApiKeyError + + type GenerateApiKeySuccess { + apiKey: String! + } + + type GenerateApiKeyError { + errorCodes: [GenerateApiKeyErrorCode!]! + } + + enum GenerateApiKeyErrorCode { + BAD_REQUEST + } + # Mutations type Mutation { googleLogin(input: GoogleLoginInput!): LoginResult! @@ -1439,6 +1453,7 @@ const schema = gql` login(input: LoginInput!): LoginResult! signup(input: SignupInput!): SignupResult! setLabels(input: SetLabelsInput!): SetLabelsResult! + generateApiKey(scope: String): GenerateApiKeyResult! } # FIXME: remove sort from feedArticles after all cahced tabs are closed diff --git a/packages/api/src/utils/auth.ts b/packages/api/src/utils/auth.ts index d397f1685..e86eb80eb 100644 --- a/packages/api/src/utils/auth.ts +++ b/packages/api/src/utils/auth.ts @@ -1,4 +1,7 @@ import * as bcrypt from 'bcryptjs' +import * as jwt from 'jsonwebtoken' +import { env } from '../env' +import { Claims } from '../resolvers/types' export const hashPassword = (password: string) => { return bcrypt.hashSync(password, 10) @@ -7,3 +10,7 @@ export const hashPassword = (password: string) => { export const comparePassword = (password: string, hash: string) => { return bcrypt.compareSync(password, hash) } + +export const generateApiKey = (claims: Claims): string => { + return jwt.sign(claims, env.server.jwtSecret) +} diff --git a/packages/api/test/resolvers/api_key.test.ts b/packages/api/test/resolvers/api_key.test.ts new file mode 100644 index 000000000..8045b7ad7 --- /dev/null +++ b/packages/api/test/resolvers/api_key.test.ts @@ -0,0 +1,47 @@ +import { User } from '../../src/entity/user' +import { createTestUser, deleteTestUser } from '../db' +import { graphqlRequest, request } from '../util' +import { expect } from 'chai' + +describe('generate api key', () => { + const username = 'fake_user' + + let authToken: string + let user: User + + before(async () => { + // create test user and login + user = await createTestUser(username) + const res = await request + .post('/local/debug/fake-user-login') + .send({ fakeEmail: user.email }) + + authToken = res.body.authToken + }) + + after(async () => { + // clean up + await deleteTestUser(username) + }) + + it('should return api key which could be used to make api calls', async () => { + const query = ` + mutation { + generateApiKey { + ... on GenerateApiKeySuccess { + apiKey + } + ... on GenerateApiKeyError { + errorCodes + } + } + } + ` + const response = await graphqlRequest(query, authToken).expect(200) + + expect(response.body.data.generateApiKey.apiKey).to.be.a('string') + + const apiKey = response.body.data.generateApiKey.apiKey + return graphqlRequest(query, apiKey).expect(200) + }) +}) From ae0d1dd2eed85231c634697930ed121c8a0b36e1 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Tue, 12 Apr 2022 12:31:08 +0800 Subject: [PATCH 6/9] Feature/search highlights backend (#395) * add highlight mappings * return highlight in resolvers * temporarily skip highlight tests * add test for getting highlights * update merge highlight * separate elastic methods * roll back merge highlight test * add highlight to elastic script * update delete highlight in elastic * migrate highlight data from postgres to elastic * rescue not found exception when page is not found in the migration script * exclude highlights in searching pages results * search pages with highlights only with has:highlight query * add search endpoint to search pages or highlights * reduce code smell in search api * fix rebase error * fix tests * add test for search highlight * add test for new search endpoint * add labels to search results * update schema * update search query * fix update/share highlights * fix rebase error * fix tests * add highlight model in elastic * add savedAt and publishedAt date range in search query * add sort by updated and recently read * fix tests * close db connection when tests are done * test github action * revert github action test * fix rebase error * add docker-compose for api-test * remove unused env * remove highlights with no page attached to * allow get_articles resolver to search for query so we can merge it without web changes --- docker-compose-test.yml | 73 +++ packages/api/.env.example | 3 +- packages/api/.env.test | 2 +- packages/api/Dockerfile-test | 1 + packages/api/add_highlight_to_elastic.py | 188 +++++++ packages/api/elastic_migrate.py | 4 +- packages/api/index_settings.json | 24 + packages/api/package.json | 2 +- .../api/src/datalayer/links/share_info.ts | 2 +- packages/api/src/elastic/highlights.ts | 281 ++++++++++ packages/api/src/elastic/index.ts | 508 +----------------- packages/api/src/elastic/labels.ts | 81 +++ packages/api/src/elastic/pages.ts | 470 ++++++++++++++++ packages/api/src/elastic/types.ts | 78 ++- packages/api/src/generated/graphql.ts | 124 ++++- packages/api/src/generated/schema.graphql | 48 +- packages/api/src/resolvers/article/index.ts | 134 ++++- .../api/src/resolvers/function_resolvers.ts | 69 ++- packages/api/src/resolvers/highlight/index.ts | 159 +++--- packages/api/src/resolvers/labels/index.ts | 3 +- packages/api/src/resolvers/links/index.ts | 2 +- packages/api/src/routers/svc/content.ts | 2 +- .../api/src/routers/svc/pdf_attachments.ts | 2 +- packages/api/src/schema.ts | 53 +- .../src/services/create_page_save_request.ts | 2 +- packages/api/src/services/labels.ts | 2 +- packages/api/src/services/reports.ts | 2 +- packages/api/src/services/save_email.ts | 2 +- packages/api/src/services/save_file.ts | 2 +- packages/api/src/services/save_page.ts | 2 +- packages/api/src/utils/search.ts | 104 +++- packages/api/test/elastic/index.test.ts | 46 +- packages/api/test/global-setup.ts | 4 + packages/api/test/global-teardown.ts | 6 + packages/api/test/resolvers/article.test.ts | 211 ++++++-- packages/api/test/resolvers/highlight.test.ts | 2 +- packages/api/test/resolvers/labels.test.ts | 2 +- .../api/test/routers/pdf_attachments.test.ts | 2 +- packages/api/test/services/save_email.test.ts | 2 +- .../services/save_newsletter_email.test.ts | 2 +- packages/api/test/util.ts | 10 +- 41 files changed, 2024 insertions(+), 692 deletions(-) create mode 100644 docker-compose-test.yml create mode 100644 packages/api/add_highlight_to_elastic.py create mode 100644 packages/api/src/elastic/highlights.ts create mode 100644 packages/api/src/elastic/labels.ts create mode 100644 packages/api/src/elastic/pages.ts diff --git a/docker-compose-test.yml b/docker-compose-test.yml new file mode 100644 index 000000000..8772ffc50 --- /dev/null +++ b/docker-compose-test.yml @@ -0,0 +1,73 @@ +version: '3' +services: + postgres-test: + image: "postgres:12.8" + container_name: "omnivore-postgres-test" + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=omnivore_test + - PG_POOL_MAX=20 + healthcheck: + test: "exit 0" + interval: 2s + timeout: 12s + retries: 3 + expose: + - 5432 + + elastic-test: + image: docker.elastic.co/elasticsearch/elasticsearch:7.17.1 + container_name: "omnivore-elastic-test" + healthcheck: + test: curl 0.0.0.0:9201/_cat/health >/dev/null || exit 1 + interval: 2s + timeout: 2s + retries: 5 + environment: + - discovery.type=single-node + - http.cors.allow-origin=* + - http.cors.enabled=true + - http.cors.allow-headers=X-Requested-With,X-Auth-Token,Content-Type,Content-Length,Authorization + - http.cors.allow-credentials=true + - http.port=9201 + volumes: + - ./.docker/elastic-data:/usr/share/elasticsearch/data + ports: + - "9201:9201" + + api-test: + build: + context: . + dockerfile: ./packages/api/Dockerfile-test + container_name: "omnivore-api-test" + environment: + - API_ENV=local + - PG_HOST=postgres-test + - PG_USER=postgres + - PG_PASSWORD=postgres + - PG_DB=omnivore_test + - PG_PORT=5432 + - PG_POOL_MAX=20 + - ELASTIC_URL=http://elastic-test:9201 + - IMAGE_PROXY_URL=http://localhost:9999 + - IMAGE_PROXY_SECRET=some-secret + - JWT_SECRET=some_secret + - SSO_JWT_SECRET=some_sso_secret + - CLIENT_URL=http://localhost:3000 + - GATEWAY_URL=http://localhost:8080/api + - PUPPETEER_TASK_HANDLER_URL=http://localhost:9090/ + - REMINDER_TASK_HANDLER_URL=/svc/reminders/trigger + - BOOKMARKLET_JWT_SECRET=some_bookmarklet_secret + - BOOKMARKLET_VERSION=1.0.0 + - PREVIEW_IMAGE_WRAPPER_ID='selected_highlight_wrapper' + - GCP_PROJECT_ID=omnivore-local + - GAUTH_CLIENT_ID='notset' + - GAUTH_SECRET='notset' + - SEGMENT_WRITE_KEY='test' + - PUBSUB_VERIFICATION_TOKEN='123456' + depends_on: + postgres-test: + condition: service_healthy + elastic-test: + condition: service_healthy diff --git a/packages/api/.env.example b/packages/api/.env.example index 2590b876d..7c3204150 100644 --- a/packages/api/.env.example +++ b/packages/api/.env.example @@ -23,4 +23,5 @@ GCS_UPLOAD_BUCKET= GCS_UPLOAD_SA_KEY_FILE_PATH= TWITTER_BEARER_TOKEN= PREVIEW_IMAGE_WRAPPER_ID='selected_highlight_wrapper' -REMINDER_TASK_HANDLER_URL= \ No newline at end of file +REMINDER_TASK_HANDLER_URL= +ELASTIC_URL=http://localhost:9200 diff --git a/packages/api/.env.test b/packages/api/.env.test index d3b940a69..4d10b8316 100644 --- a/packages/api/.env.test +++ b/packages/api/.env.test @@ -28,4 +28,4 @@ SEGMENT_WRITE_KEY='test' REMINDER_TASK_HANDLER_URL=http://localhost:4000/svc/reminders/trigger PUBSUB_VERIFICATION_TOKEN='123456' PUPPETEER_TASK_HANDLER_URL=http://localhost:9090/ - +ELASTIC_URL=http://localhost:9200 diff --git a/packages/api/Dockerfile-test b/packages/api/Dockerfile-test index 262cb5a29..bdeb25b6d 100644 --- a/packages/api/Dockerfile-test +++ b/packages/api/Dockerfile-test @@ -18,6 +18,7 @@ ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true RUN yarn install +ADD /packages/db ./packages/db ADD /packages/readabilityjs ./packages/readabilityjs ADD /packages/api ./packages/api diff --git a/packages/api/add_highlight_to_elastic.py b/packages/api/add_highlight_to_elastic.py new file mode 100644 index 000000000..46d73ba8a --- /dev/null +++ b/packages/api/add_highlight_to_elastic.py @@ -0,0 +1,188 @@ +#!/usr/bin/python +import os +import json +import psycopg2 +from psycopg2.extras import RealDictCursor +from elasticsearch import Elasticsearch, NotFoundError + +PG_HOST = os.getenv('PG_HOST', 'localhost') +PG_PORT = os.getenv('PG_PORT', 5432) +PG_USER = os.getenv('PG_USER', 'app_user') +PG_PASSWORD = os.getenv('PG_PASSWORD', 'app_pass') +PG_DB = os.getenv('PG_DB', 'omnivore') +ES_URL = os.getenv('ES_URL', 'http://localhost:9200') +ES_USERNAME = os.getenv('ES_USERNAME', 'elastic') +ES_PASSWORD = os.getenv('ES_PASSWORD', 'password') +UPDATE_TIME = os.getenv('UPDATE_TIME', '2019-01-01 00:00:00') +INDEX_SETTINGS = os.getenv('INDEX_SETTINGS', 'index_settings.json') +DATETIME_FORMAT = 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"' + + +def update_mappings(client: Elasticsearch): + print('updating mappings') + try: + with open(INDEX_SETTINGS, 'r') as f: + settings = json.load(f) + client.indices.put_mapping( + index='pages_alias', + body=settings['mappings']) + print('mappings updated') + except Exception as err: + print('update mappings ERROR:', err) + exit(1) + + +def assertData(conn, client: Elasticsearch, pages): + # get all users from postgres + try: + success = 0 + failure = 0 + skip = 0 + cursor = conn.cursor(cursor_factory=RealDictCursor) + for page in pages: + pageId = page['pageId'] + cursor.execute( + f'''SELECT COUNT(*) FROM omnivore.highlight + WHERE elastic_page_id = \'{pageId}\' AND deleted = false''') + countInPostgres = cursor.fetchone()['count'] + try: + countInElastic = len(client.get( + index='pages_alias', + id=pageId, + _source=['highlights'])['_source']['highlights']) + except NotFoundError as err: + print('Elasticsearch get ERROR:', err) + # if page is not found in elasticsearch, skip testing + skip += 1 + continue + + if countInPostgres == countInElastic: + success += 1 + print(f'Page {pageId} OK') + else: + failure += 1 + print( + f'Page {pageId} ERROR: postgres: {countInPostgres}, elastic: {countInElastic}') + cursor.close() + print( + f'Asserted data, success: {success}, failure: {failure}, skip: {skip}') + except Exception as err: + print('Assert data ERROR:', err) + exit(1) + + +def ingest_highlights(conn, pages): + try: + import_count = 0 + cursor = conn.cursor(cursor_factory=RealDictCursor) + + for page in pages: + pageId = page['pageId'] + query = ''' + SELECT + id, + quote, + prefix, + to_char(created_at, '{DATETIME_FORMAT}') as "createdAt", + to_char(COALESCE(updated_at, current_timestamp), '{DATETIME_FORMAT}') as "updatedAt", + suffix, + patch, + annotation, + short_id as "shortId", + user_id as "userId", + to_char(shared_at, '{DATETIME_FORMAT}') as "sharedAt" + FROM omnivore.highlight + WHERE + elastic_page_id = \'{pageId}\' + AND deleted = false + AND created_at > '{UPDATE_TIME}' + '''.format(pageId=pageId, DATETIME_FORMAT=DATETIME_FORMAT, UPDATE_TIME=UPDATE_TIME) + + cursor.execute(query) + result = cursor.fetchall() + import_count += import_highlights_to_es(client, result, pageId) + + print(f'Imported total {import_count} highlights to es') + + cursor.close() + except Exception as err: + print('Export data to json ERROR:', err) + + +def import_highlights_to_es(client, highlights, pageId) -> int: + # import highlights to elasticsearch + print(f'Writing {len(highlights)} highlights to page {pageId}') + + if len(highlights) == 0: + print('No highlights to import') + return 0 + + try: + resp = client.update( + index='pages_alias', + id=pageId, + body={'doc': {'highlights': highlights}}) + + count = 0 + if resp['result'] == 'updated': + count = len(highlights) + + print(f'Added {count} highlights to page {pageId}') + + return count + except Exception as err: + print('Elasticsearch update ERROR:', err) + return 0 + + +def get_pages_with_highlights(conn): + try: + query = f''' + SELECT DISTINCT + elastic_page_id as "pageId" + FROM omnivore.highlight + WHERE + elastic_page_id IS NOT NULL + AND deleted = false + AND created_at > '{UPDATE_TIME}' + ''' + cursor = conn.cursor(cursor_factory=RealDictCursor) + cursor.execute(query) + result = cursor.fetchall() + cursor.close() + print('Found pages with highlights:', len(result)) + return result + except Exception as err: + print('Get pages with highlights ERROR:', err) + + +print('Starting migration') + +# test elastic client +client = Elasticsearch(ES_URL, http_auth=( + ES_USERNAME, ES_PASSWORD), retry_on_timeout=True) +try: + print('Elasticsearch client connected', client.info()) +except Exception as err: + print('Elasticsearch client ERROR:', err) + exit(1) + +# test postgres client +conn = psycopg2.connect( + f'host={PG_HOST} port={PG_PORT} dbname={PG_DB} user={PG_USER} \ + password={PG_PASSWORD}') +print('Postgres connection:', conn.info) + + +update_mappings(client) + +pages = get_pages_with_highlights(conn) + +ingest_highlights(conn, pages) + +assertData(conn, client, pages) + +client.close() +conn.close() + +print('Migration complete') diff --git a/packages/api/elastic_migrate.py b/packages/api/elastic_migrate.py index d0be65ede..3fd7003d5 100644 --- a/packages/api/elastic_migrate.py +++ b/packages/api/elastic_migrate.py @@ -89,7 +89,7 @@ def assertData(conn, client): f'SELECT COUNT(*) FROM omnivore.links WHERE user_id = \'{userId}\'''') countInPostgres = cursor.fetchone()['count'] countInElastic = client.count( - index='pages', body={'query': {'term': {'userId': userId}}})['count'] + index='pages_alias', body={'query': {'term': {'userId': userId}}})['count'] if countInPostgres == countInElastic: success += 1 @@ -197,7 +197,7 @@ def import_data_to_es(client, docs) -> int: doc['publishedAt'] = validated_date(doc['publishedAt']) # convert the string to a dict object dict_doc = { - '_index': 'pages', + '_index': 'pages_alias', '_id': doc['id'], '_source': doc } diff --git a/packages/api/index_settings.json b/packages/api/index_settings.json index c0c3aab57..2e540dcde 100644 --- a/packages/api/index_settings.json +++ b/packages/api/index_settings.json @@ -56,6 +56,30 @@ } } }, + "highlights": { + "type": "nested", + "properties": { + "id": { + "type": "keyword" + }, + "userId": { + "type": "keyword" + }, + "quote": { + "type": "text", + "analyzer": "strip_html_analyzer" + }, + "annotation": { + "type": "text" + }, + "createdAt": { + "type": "date" + }, + "updatedAt": { + "type": "date" + } + } + }, "readingProgressPercent": { "type": "float" }, diff --git a/packages/api/package.json b/packages/api/package.json index 80c7c523a..312f97c91 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -8,7 +8,7 @@ "start": "node dist/server.js", "lint": "eslint src --ext ts,js,tsx,jsx", "lint:fix": "eslint src --fix --ext ts,js,tsx,jsx", - "test": "nyc mocha -r ts-node/register --config mocha-config.json --exit --timeout 10000" + "test": "nyc mocha -r ts-node/register --config mocha-config.json --timeout 10000" }, "dependencies": { "@elastic/elasticsearch": "~7.12.0", diff --git a/packages/api/src/datalayer/links/share_info.ts b/packages/api/src/datalayer/links/share_info.ts index 4bc45acd3..2646cfc57 100644 --- a/packages/api/src/datalayer/links/share_info.ts +++ b/packages/api/src/datalayer/links/share_info.ts @@ -3,7 +3,7 @@ import Knex from 'knex' import { LinkShareInfo } from '../../generated/graphql' import { DataModels } from '../../resolvers/types' -import { getPageByParam } from '../../elastic' +import { getPageByParam } from '../../elastic/pages' // once we have links setup properly in the API we will remove this method // and have a getShareInfoForLink method diff --git a/packages/api/src/elastic/highlights.ts b/packages/api/src/elastic/highlights.ts new file mode 100644 index 000000000..5a499237e --- /dev/null +++ b/packages/api/src/elastic/highlights.ts @@ -0,0 +1,281 @@ +import { + Highlight, + Page, + PageContext, + SearchItem, + SearchResponse, +} from './types' +import { ResponseError } from '@elastic/elasticsearch/lib/errors' +import { client, INDEX_ALIAS } from './index' +import { SortBy, SortOrder, SortParams } from '../utils/search' + +export const addHighlightToPage = async ( + id: string, + highlight: Highlight, + ctx: PageContext +): Promise => { + try { + const { body } = await client.update({ + index: INDEX_ALIAS, + id, + body: { + script: { + source: `if (ctx._source.highlights == null) { + ctx._source.highlights = [params.highlight] + } else { + ctx._source.highlights.add(params.highlight) + }`, + lang: 'painless', + params: { + highlight: highlight, + }, + }, + }, + refresh: ctx.refresh, + retry_on_conflict: 3, + }) + + return body.result === 'updated' + } catch (e) { + if ( + e instanceof ResponseError && + e.message === 'document_missing_exception' + ) { + console.log('page has been deleted', id) + return false + } + console.error('failed to add highlight to a page in elastic', e) + return false + } +} + +export const getHighlightById = async ( + id: string +): Promise => { + try { + const { body } = await client.search({ + index: INDEX_ALIAS, + body: { + query: { + nested: { + path: 'highlights', + query: { + match: { + 'highlights.id': id, + }, + }, + inner_hits: {}, + }, + }, + _source: false, + }, + }) + + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (body.hits.total.value === 0) { + return undefined + } + + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-return + return body.hits.hits[0].inner_hits.highlights.hits.hits[0]._source + } catch (e) { + console.error('failed to get highlight from a page in elastic', e) + return undefined + } +} + +export const deleteHighlight = async ( + highlightId: string, + ctx: PageContext +): Promise => { + try { + const { body } = await client.updateByQuery({ + index: INDEX_ALIAS, + body: { + script: { + source: + 'ctx._source.highlights.removeIf(h -> h.id == params.highlightId)', + lang: 'painless', + params: { + highlightId: highlightId, + }, + }, + query: { + bool: { + filter: [ + { + term: { + userId: ctx.uid, + }, + }, + { + nested: { + path: 'highlights', + query: { + term: { + 'highlights.id': highlightId, + }, + }, + }, + }, + ], + }, + }, + }, + refresh: ctx.refresh, + }) + + return !!body.updated + } catch (e) { + console.error('failed to delete a highlight in elastic', e) + + return false + } +} + +export const searchHighlights = async ( + args: { + from?: number + size?: number + sort?: SortParams + query?: string + }, + userId: string +): Promise<[SearchItem[], number] | undefined> => { + try { + const { from = 0, size = 10, sort, query } = args + const sortOrder = sort?.order || SortOrder.DESCENDING + // default sort by updatedAt + const sortField = + sort?.by === SortBy.SCORE ? SortBy.SCORE : 'highlights.updatedAt' + + const searchBody = { + query: { + nested: { + path: 'highlights', + query: { + bool: { + filter: [ + { + term: { + 'highlights.userId': userId, + }, + }, + ], + should: [ + { + multi_match: { + query: query || '', + fields: ['highlights.quote', 'highlights.annotation'], + operator: 'and', + type: 'cross_fields', + }, + }, + ], + minimum_should_match: query ? 1 : 0, + }, + }, + inner_hits: {}, + }, + }, + sort: [ + { + [sortField]: { + order: sortOrder, + nested: { + path: 'highlights', + }, + }, + }, + ], + from, + size, + _source: ['title', 'slug', 'url', 'createdAt'], + } + + console.log('searching highlights in elastic', JSON.stringify(searchBody)) + + const response = await client.search>({ + index: INDEX_ALIAS, + body: searchBody, + }) + + if (response.body.hits.total.value === 0) { + return [[], 0] + } + + const results: SearchItem[] = [] + response.body.hits.hits.forEach((hit) => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access + hit.inner_hits.highlights.hits.hits.forEach( + (innerHit: { _source: Highlight }) => { + results.push({ + ...hit._source, + ...innerHit._source, + pageId: hit._id, + }) + } + ) + }) + + return [results, response.body.hits.total.value] + } catch (e) { + console.error('failed to search highlights in elastic', e) + return undefined + } +} + +export const updateHighlight = async ( + highlight: Highlight, + ctx: PageContext +): Promise => { + try { + const { body } = await client.updateByQuery({ + index: INDEX_ALIAS, + body: { + script: { + source: `ctx._source.highlights.removeIf(h -> h.id == params.highlight.id); + ctx._source.highlights.add(params.highlight)`, + lang: 'painless', + params: { + highlight: highlight, + }, + }, + query: { + bool: { + filter: [ + { + term: { + userId: ctx.uid, + }, + }, + { + nested: { + path: 'highlights', + query: { + term: { + 'highlights.id': highlight.id, + }, + }, + }, + }, + ], + }, + }, + }, + refresh: ctx.refresh, + }) + + return !!body.updated + } catch (e) { + if ( + e instanceof ResponseError && + e.message === 'document_missing_exception' + ) { + console.log('page has been deleted') + return false + } + console.error('failed to update highlight in elastic', e) + return false + } +} diff --git a/packages/api/src/elastic/index.ts b/packages/api/src/elastic/index.ts index 1108c1619..118132069 100644 --- a/packages/api/src/elastic/index.ts +++ b/packages/api/src/elastic/index.ts @@ -1,35 +1,11 @@ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -/* eslint-disable @typescript-eslint/no-unsafe-assignment */ -/* eslint-disable @typescript-eslint/no-unsafe-call */ import { env } from '../env' import { Client } from '@elastic/elasticsearch' -import { - Label, - PageType, - SortBy, - SortOrder, - SortParams, -} from '../generated/graphql' -import { - InFilter, - LabelFilter, - LabelFilterType, - ReadFilter, -} from '../utils/search' -import { - Page, - PageContext, - ParamSet, - SearchBody, - SearchResponse, -} from './types' import { readFileSync } from 'fs' import { join } from 'path' -import { ResponseError } from '@elastic/elasticsearch/lib/errors' -const INDEX_NAME = 'pages' -const INDEX_ALIAS = 'pages_alias' -const client = new Client({ +export const INDEX_NAME = 'pages' +export const INDEX_ALIAS = 'pages_alias' +export const client = new Client({ node: env.elastic.url, maxRetries: 3, requestTimeout: 50000, @@ -52,484 +28,6 @@ const ingest = async (): Promise => { }) } -const appendQuery = (body: SearchBody, query: string): void => { - body.query.bool.should.push({ - multi_match: { - query, - fields: ['title', 'content', 'author', 'description', 'siteName'], - operator: 'and', - type: 'cross_fields', - }, - }) - body.query.bool.minimum_should_match = 1 -} - -const appendTypeFilter = (body: SearchBody, filter: PageType): void => { - body.query.bool.filter.push({ - term: { - pageType: filter, - }, - }) -} - -const appendReadFilter = (body: SearchBody, filter: ReadFilter): void => { - switch (filter) { - case ReadFilter.UNREAD: - body.query.bool.filter.push({ - range: { - readingProgress: { - gte: 98, - }, - }, - }) - break - case ReadFilter.READ: - body.query.bool.filter.push({ - range: { - readingProgress: { - lt: 98, - }, - }, - }) - } -} - -const appendInFilter = (body: SearchBody, filter: InFilter): void => { - switch (filter) { - case InFilter.ARCHIVE: - body.query.bool.filter.push({ - exists: { - field: 'archivedAt', - }, - }) - break - case InFilter.INBOX: - body.query.bool.must_not.push({ - exists: { - field: 'archivedAt', - }, - }) - } -} - -const appendNotNullField = (body: SearchBody, field: string): void => { - body.query.bool.filter.push({ - exists: { - field, - }, - }) -} - -const appendExcludeLabelFilter = ( - body: SearchBody, - filters: LabelFilter[] -): void => { - body.query.bool.must_not.push({ - nested: { - path: 'labels', - query: filters.map((filter) => { - return { - terms: { - 'labels.name': filter.labels, - }, - } - }), - }, - }) -} - -const appendIncludeLabelFilter = ( - body: SearchBody, - filters: LabelFilter[] -): void => { - body.query.bool.filter.push({ - nested: { - path: 'labels', - query: { - bool: { - filter: filters.map((filter) => { - return { - terms: { - 'labels.name': filter.labels, - }, - } - }), - }, - }, - }, - }) -} - -export const createPage = async ( - page: Page, - ctx: PageContext -): Promise => { - try { - const { body } = await client.index({ - id: page.id || undefined, - index: INDEX_ALIAS, - body: { - ...page, - updatedAt: new Date(), - savedAt: new Date(), - }, - refresh: ctx.refresh, - }) - - await ctx.pubsub.pageCreated(page) - - return body._id as string - } catch (e) { - console.error('failed to create a page in elastic', e) - return undefined - } -} - -export const updatePage = async ( - id: string, - page: Partial, - ctx: PageContext -): Promise => { - try { - const { body } = await client.update({ - index: INDEX_ALIAS, - id, - body: { - doc: { - ...page, - updatedAt: new Date(), - }, - }, - refresh: ctx.refresh, - retry_on_conflict: 3, - }) - - if (body.result !== 'updated') return false - - await ctx.pubsub.pageUpdated({ ...page, id }, ctx.uid) - - return true - } catch (e) { - if ( - e instanceof ResponseError && - e.message === 'document_missing_exception' - ) { - console.info('page has been deleted', id) - return false - } - console.error('failed to update a page in elastic', e) - return false - } -} - -export const addLabelInPage = async ( - id: string, - label: Label, - ctx: PageContext -): Promise => { - try { - const { body } = await client.update({ - index: INDEX_ALIAS, - id, - body: { - script: { - source: `if (ctx._source.labels == null) { - ctx._source.labels = [params.label] - } else if (!ctx._source.labels.any(label -> label.name == params.label.name)) { - ctx._source.labels.add(params.label) - } else { ctx.op = 'none' }`, - lang: 'painless', - params: { - label: label, - }, - }, - }, - refresh: ctx.refresh, - retry_on_conflict: 3, - }) - - return body.result === 'updated' - } catch (e) { - console.error('failed to update a page in elastic', e) - return false - } -} - -export const deletePage = async ( - id: string, - ctx: PageContext -): Promise => { - try { - const { body } = await client.delete({ - index: INDEX_ALIAS, - id, - refresh: ctx.refresh, - }) - - if (body.deleted === 0) return false - - await ctx.pubsub.pageDeleted(id, ctx.uid) - - return true - } catch (e) { - console.error('failed to delete a page in elastic', e) - return false - } -} - -export const deleteLabelInPages = async ( - userId: string, - label: string, - ctx: PageContext -): Promise => { - try { - await client.updateByQuery({ - index: INDEX_ALIAS, - body: { - script: { - source: - 'ctx._source.labels.removeIf(label -> label.name == params.label)', - lang: 'painless', - params: { - label: label, - }, - }, - query: { - bool: { - filter: [ - { - term: { - userId, - }, - }, - { - nested: { - path: 'labels', - query: { - term: { - 'labels.name': label, - }, - }, - }, - }, - ], - }, - }, - }, - refresh: ctx.refresh, - }) - } catch (e) { - console.error('failed to delete a page in elastic', e) - } -} - -export const getPageByParam = async ( - param: Record -): Promise => { - try { - const params = { - query: { - bool: { - filter: Object.keys(param).map((key) => { - return { - term: { - [key]: param[key as K], - }, - } - }), - }, - }, - size: 1, - _source: { - excludes: ['originalHtml'], - }, - } - - const { body } = await client.search({ - index: INDEX_ALIAS, - body: params, - }) - - if (body.hits.total.value === 0) { - return undefined - } - - return { - ...body.hits.hits[0]._source, - id: body.hits.hits[0]._id, - } as Page - } catch (e) { - console.error('failed to search pages in elastic', e) - return undefined - } -} - -export const getPageById = async (id: string): Promise => { - try { - const { body } = await client.get({ - index: INDEX_ALIAS, - id, - }) - - return { - ...body._source, - id: body._id, - } as Page - } catch (e) { - console.error('failed to search pages in elastic', e) - return undefined - } -} - -export const searchPages = async ( - args: { - from?: number - size?: number - sort?: SortParams - query?: string - inFilter: InFilter - readFilter: ReadFilter - typeFilter?: PageType - labelFilters: LabelFilter[] - }, - userId: string, - notNullField: string | null = null -): Promise<[Page[], number] | undefined> => { - try { - const { - from = 0, - size = 10, - sort, - query, - readFilter, - typeFilter, - labelFilters, - inFilter, - } = args - const sortOrder = sort?.order === SortOrder.Ascending ? 'asc' : 'desc' - // default sort by saved_at - const sortField = sort?.by === SortBy.Score ? '_score' : 'savedAt' - const includeLabels = labelFilters.filter( - (filter) => filter.type === LabelFilterType.INCLUDE - ) - const excludeLabels = labelFilters.filter( - (filter) => filter.type === LabelFilterType.EXCLUDE - ) - - const body: SearchBody = { - query: { - bool: { - filter: [ - { - term: { - userId, - }, - }, - ], - should: [], - must_not: [], - }, - }, - sort: [ - { - [sortField]: { - order: sortOrder, - }, - }, - ], - from, - size, - _source: { - excludes: ['originalHtml', 'content'], - }, - } - - // append filters - if (query) { - appendQuery(body, query) - } - if (typeFilter) { - appendTypeFilter(body, typeFilter) - } - if (inFilter !== InFilter.ALL) { - appendInFilter(body, inFilter) - } - if (readFilter !== ReadFilter.ALL) { - appendReadFilter(body, readFilter) - } - if (notNullField) { - appendNotNullField(body, notNullField) - } - if (includeLabels.length > 0) { - appendIncludeLabelFilter(body, includeLabels) - } - if (excludeLabels.length > 0) { - appendExcludeLabelFilter(body, excludeLabels) - } - - console.log('searching pages in elastic', JSON.stringify(body)) - - const response = await client.search, SearchBody>({ - index: INDEX_ALIAS, - body, - }) - - if (response.body.hits.total.value === 0) { - return [[], 0] - } - - return [ - response.body.hits.hits.map((hit: { _source: Page; _id: string }) => ({ - ...hit._source, - content: '', - id: hit._id, - })), - response.body.hits.total.value, - ] - } catch (e) { - console.error('failed to search pages in elastic', e) - return undefined - } -} - -export const countByCreatedAt = async ( - userId: string, - from?: number, - to?: number -): Promise => { - try { - const { body } = await client.count({ - index: INDEX_ALIAS, - body: { - query: { - bool: { - filter: [ - { - term: { - userId, - }, - }, - { - range: { - createdAt: { - gte: from, - lte: to, - }, - }, - }, - ], - }, - }, - }, - }) - - return body.count as number - } catch (e) { - console.error('failed to count pages in elastic', e) - return 0 - } -} - export const initElasticsearch = async (): Promise => { try { const response = await client.info() diff --git a/packages/api/src/elastic/labels.ts b/packages/api/src/elastic/labels.ts new file mode 100644 index 000000000..ec1ac5188 --- /dev/null +++ b/packages/api/src/elastic/labels.ts @@ -0,0 +1,81 @@ +import { Label, PageContext } from './types' +import { client, INDEX_ALIAS } from './index' + +export const addLabelInPage = async ( + id: string, + label: Label, + ctx: PageContext +): Promise => { + try { + const { body } = await client.update({ + index: INDEX_ALIAS, + id, + body: { + script: { + source: `if (ctx._source.labels == null) { + ctx._source.labels = [params.label] + } else if (!ctx._source.labels.any(label -> label.name == params.label.name)) { + ctx._source.labels.add(params.label) + } else { ctx.op = 'none' }`, + lang: 'painless', + params: { + label: label, + }, + }, + }, + refresh: ctx.refresh, + retry_on_conflict: 3, + }) + + return body.result === 'updated' + } catch (e) { + console.error('failed to update a page in elastic', e) + return false + } +} + +export const deleteLabelInPages = async ( + userId: string, + label: string, + ctx: PageContext +): Promise => { + try { + await client.updateByQuery({ + index: INDEX_ALIAS, + body: { + script: { + source: + 'ctx._source.labels.removeIf(label -> label.name == params.label)', + lang: 'painless', + params: { + label: label, + }, + }, + query: { + bool: { + filter: [ + { + term: { + userId, + }, + }, + { + nested: { + path: 'labels', + query: { + term: { + 'labels.name': label, + }, + }, + }, + }, + ], + }, + }, + }, + refresh: ctx.refresh, + }) + } catch (e) { + console.error('failed to delete a page in elastic', e) + } +} diff --git a/packages/api/src/elastic/pages.ts b/packages/api/src/elastic/pages.ts new file mode 100644 index 000000000..96f1b5d4a --- /dev/null +++ b/packages/api/src/elastic/pages.ts @@ -0,0 +1,470 @@ +import { + Page, + PageContext, + PageType, + ParamSet, + SearchBody, + SearchResponse, +} from './types' +import { + DateRangeFilter, + HasFilter, + InFilter, + LabelFilter, + LabelFilterType, + ReadFilter, + SortBy, + SortOrder, + SortParams, +} from '../utils/search' +import { client, INDEX_ALIAS } from './index' + +const appendQuery = (body: SearchBody, query: string): void => { + body.query.bool.should.push({ + multi_match: { + query, + fields: ['title', 'content', 'author', 'description', 'siteName'], + operator: 'and', + type: 'cross_fields', + }, + }) + body.query.bool.minimum_should_match = 1 +} + +const appendTypeFilter = (body: SearchBody, filter: PageType): void => { + body.query.bool.filter.push({ + term: { + pageType: filter, + }, + }) +} + +const appendReadFilter = (body: SearchBody, filter: ReadFilter): void => { + switch (filter) { + case ReadFilter.UNREAD: + body.query.bool.filter.push({ + range: { + readingProgress: { + gte: 98, + }, + }, + }) + break + case ReadFilter.READ: + body.query.bool.filter.push({ + range: { + readingProgress: { + lt: 98, + }, + }, + }) + } +} + +const appendInFilter = (body: SearchBody, filter: InFilter): void => { + switch (filter) { + case InFilter.ARCHIVE: + body.query.bool.filter.push({ + exists: { + field: 'archivedAt', + }, + }) + break + case InFilter.INBOX: + body.query.bool.must_not.push({ + exists: { + field: 'archivedAt', + }, + }) + } +} + +const appendHasFilters = (body: SearchBody, filters: HasFilter[]): void => { + filters.forEach((filter) => { + switch (filter) { + case HasFilter.HIGHLIGHTS: + body.query.bool.filter.push({ + nested: { + path: 'highlights', + query: { + exists: { + field: 'highlights', + }, + }, + }, + }) + break + case HasFilter.SHARED_AT: + body.query.bool.filter.push({ + exists: { + field: 'sharedAt', + }, + }) + break + } + }) +} + +const appendExcludeLabelFilter = ( + body: SearchBody, + filters: LabelFilter[] +): void => { + body.query.bool.must_not.push({ + nested: { + path: 'labels', + query: filters.map((filter) => { + return { + terms: { + 'labels.name': filter.labels, + }, + } + }), + }, + }) +} + +const appendIncludeLabelFilter = ( + body: SearchBody, + filters: LabelFilter[] +): void => { + body.query.bool.filter.push({ + nested: { + path: 'labels', + query: { + bool: { + filter: filters.map((filter) => { + return { + terms: { + 'labels.name': filter.labels, + }, + } + }), + }, + }, + }, + }) +} + +const appendSavedDateFilter = ( + body: SearchBody, + filter: DateRangeFilter +): void => { + body.query.bool.filter.push({ + range: { + savedAt: { + gt: filter.startDate, + lt: filter.endDate, + }, + }, + }) +} + +const appendPublishedDateFilter = ( + body: SearchBody, + filter: DateRangeFilter +): void => { + body.query.bool.filter.push({ + range: { + publishedAt: { + gt: filter.startDate, + lt: filter.endDate, + }, + }, + }) +} + +export const createPage = async ( + page: Page, + ctx: PageContext +): Promise => { + try { + const { body } = await client.index({ + id: page.id || undefined, + index: INDEX_ALIAS, + body: { + ...page, + updatedAt: new Date(), + savedAt: new Date(), + }, + refresh: ctx.refresh, + }) + + await ctx.pubsub.pageCreated(page) + + return body._id as string + } catch (e) { + console.error('failed to create a page in elastic', e) + return undefined + } +} + +export const updatePage = async ( + id: string, + page: Partial, + ctx: PageContext +): Promise => { + try { + const { body } = await client.update({ + index: INDEX_ALIAS, + id, + body: { + doc: { + ...page, + updatedAt: new Date(), + }, + }, + refresh: ctx.refresh, + retry_on_conflict: 3, + }) + + if (body.result !== 'updated') return false + + await ctx.pubsub.pageUpdated({ ...page, id }, ctx.uid) + + return true + } catch (e) { + console.error('failed to update a page in elastic', e) + return false + } +} + +export const deletePage = async ( + id: string, + ctx: PageContext +): Promise => { + try { + const { body } = await client.delete({ + index: INDEX_ALIAS, + id, + refresh: ctx.refresh, + }) + + if (body.deleted === 0) return false + + await ctx.pubsub.pageDeleted(id, ctx.uid) + + return true + } catch (e) { + console.error('failed to delete a page in elastic', e) + return false + } +} + +export const getPageByParam = async ( + param: Record +): Promise => { + try { + const params = { + query: { + bool: { + filter: Object.keys(param).map((key) => { + return { + term: { + [key]: param[key as K], + }, + } + }), + }, + }, + size: 1, + _source: { + excludes: ['originalHtml'], + }, + } + + const { body } = await client.search>({ + index: INDEX_ALIAS, + body: params, + }) + + if (body.hits.total.value === 0) { + return undefined + } + + return { + ...body.hits.hits[0]._source, + id: body.hits.hits[0]._id, + } as Page + } catch (e) { + console.error('failed to search pages in elastic', e) + return undefined + } +} + +export const getPageById = async (id: string): Promise => { + try { + const { body } = await client.get({ + index: INDEX_ALIAS, + id, + }) + + return { + ...body._source, + id: body._id as string, + } as Page + } catch (e) { + console.error('failed to search pages in elastic', e) + return undefined + } +} + +export const searchPages = async ( + args: { + from?: number + size?: number + sort?: SortParams + query?: string + inFilter?: InFilter + readFilter?: ReadFilter + typeFilter?: PageType + labelFilters?: LabelFilter[] + hasFilters?: HasFilter[] + savedDateFilter?: DateRangeFilter + publishedDateFilter?: DateRangeFilter + }, + userId: string +): Promise<[Page[], number] | undefined> => { + try { + const { + from = 0, + size = 10, + sort, + query, + readFilter = ReadFilter.ALL, + typeFilter, + labelFilters = [], + inFilter = InFilter.ALL, + hasFilters = [], + savedDateFilter, + publishedDateFilter, + } = args + // default order is descending + const sortOrder = sort?.order || SortOrder.DESCENDING + // default sort by saved_at + const sortField = sort?.by || SortBy.SAVED + const includeLabels = labelFilters.filter( + (filter) => filter.type === LabelFilterType.INCLUDE + ) + const excludeLabels = labelFilters.filter( + (filter) => filter.type === LabelFilterType.EXCLUDE + ) + + const body: SearchBody = { + query: { + bool: { + filter: [ + { + term: { + userId, + }, + }, + ], + should: [], + must_not: [], + }, + }, + sort: [ + { + [sortField]: { + order: sortOrder, + }, + }, + ], + from, + size, + _source: { + excludes: ['originalHtml', 'content', 'highlights'], + }, + } + + // append filters + if (query) { + appendQuery(body, query) + } + if (typeFilter) { + appendTypeFilter(body, typeFilter) + } + if (inFilter !== InFilter.ALL) { + appendInFilter(body, inFilter) + } + if (readFilter !== ReadFilter.ALL) { + appendReadFilter(body, readFilter) + } + if (hasFilters.length > 0) { + appendHasFilters(body, hasFilters) + } + if (includeLabels.length > 0) { + appendIncludeLabelFilter(body, includeLabels) + } + if (excludeLabels.length > 0) { + appendExcludeLabelFilter(body, excludeLabels) + } + if (savedDateFilter) { + appendSavedDateFilter(body, savedDateFilter) + } + if (publishedDateFilter) { + appendPublishedDateFilter(body, publishedDateFilter) + } + + console.log('searching pages in elastic', JSON.stringify(body)) + + const response = await client.search, SearchBody>({ + index: INDEX_ALIAS, + body, + }) + + if (response.body.hits.total.value === 0) { + return [[], 0] + } + + return [ + response.body.hits.hits.map((hit: { _source: Page; _id: string }) => ({ + ...hit._source, + content: '', + id: hit._id, + })), + response.body.hits.total.value, + ] + } catch (e) { + console.error('failed to search pages in elastic', e) + return undefined + } +} + +export const countByCreatedAt = async ( + userId: string, + from?: number, + to?: number +): Promise => { + try { + const { body } = await client.count({ + index: INDEX_ALIAS, + body: { + query: { + bool: { + filter: [ + { + term: { + userId, + }, + }, + { + range: { + createdAt: { + gte: from, + lte: to, + }, + }, + }, + ], + }, + }, + }, + }) + + return body.count as number + } catch (e) { + console.error('failed to count pages in elastic', e) + return 0 + } +} diff --git a/packages/api/src/elastic/types.ts b/packages/api/src/elastic/types.ts index 0ec857678..9d9e5f74a 100644 --- a/packages/api/src/elastic/types.ts +++ b/packages/api/src/elastic/types.ts @@ -1,5 +1,4 @@ // Define the type of the body for the Search request -import { Label, PageType } from '../generated/graphql' import { PickTuple } from '../util' import { PubsubClient } from '../datalayer/pubsub' @@ -19,6 +18,16 @@ export interface SearchBody { readingProgress: { gte: number } | { lt: number } } } + | { + range: { + savedAt: { gt: Date | undefined } | { lt: Date | undefined } + } + } + | { + range: { + publishedAt: { gt: Date | undefined } | { lt: Date | undefined } + } + } | { nested: { path: 'labels' @@ -33,6 +42,16 @@ export interface SearchBody { } } } + | { + nested: { + path: 'highlights' + query: { + exists: { + field: 'highlights' + } + } + } + } )[] should: { multi_match: { @@ -109,7 +128,7 @@ export interface SearchResponse { _explanation?: Explanation fields?: never highlight?: never - inner_hits?: never + inner_hits?: any matched_queries?: string[] sort?: string[] }> @@ -117,6 +136,38 @@ export interface SearchResponse { aggregations?: never } +export enum PageType { + Article = 'ARTICLE', + Book = 'BOOK', + File = 'FILE', + Profile = 'PROFILE', + Unknown = 'UNKNOWN', + Website = 'WEBSITE', + Highlights = 'HIGHLIGHTS', +} + +export interface Label { + id: string + name: string + color: string + description?: string + createdAt?: Date +} + +export interface Highlight { + id: string + shortId: string + patch: string + quote: string + userId: string + createdAt: Date + prefix?: string | null + suffix?: string | null + annotation?: string | null + sharedAt?: Date | null + updatedAt?: Date | null +} + export interface Page { id: string userId: string @@ -143,6 +194,29 @@ export interface Page { siteName?: string _id?: string siteIcon?: string + highlights?: Highlight[] +} + +export interface SearchItem { + annotation?: string | null + author?: string | null + createdAt: Date + description?: string | null + id: string + image?: string | null + pageId?: string + pageType: PageType + publishedAt?: Date + quote?: string | null + shortId?: string | null + slug: string + title: string + uploadFileId?: string | null + url: string + archivedAt?: Date | null + readingProgressPercent?: number + readingProgressAnchorIndex?: number + userId: string } const keys = ['_id', 'url', 'slug', 'userId', 'uploadFileId'] as const diff --git a/packages/api/src/generated/graphql.ts b/packages/api/src/generated/graphql.ts index 3d392ec03..872991d7f 100644 --- a/packages/api/src/generated/graphql.ts +++ b/packages/api/src/generated/graphql.ts @@ -615,7 +615,6 @@ export type GoogleSignupSuccess = { export type Highlight = { __typename?: 'Highlight'; annotation?: Maybe; - article: Article; createdAt: Scalars['Date']; createdByMe: Scalars['Boolean']; id: Scalars['ID']; @@ -1087,6 +1086,7 @@ export enum PageType { Article = 'ARTICLE', Book = 'BOOK', File = 'FILE', + Highlights = 'HIGHLIGHTS', Profile = 'PROFILE', Unknown = 'UNKNOWN', Website = 'WEBSITE' @@ -1120,6 +1120,7 @@ export type Query = { me?: Maybe; newsletterEmails: NewsletterEmailsResult; reminder: ReminderResult; + search: SearchResult; sharedArticle: SharedArticleResult; user: UserResult; users: UsersResult; @@ -1170,6 +1171,13 @@ export type QueryReminderArgs = { }; +export type QuerySearchArgs = { + after?: InputMaybe; + first?: InputMaybe; + query?: InputMaybe; +}; + + export type QuerySharedArticleArgs = { selectedHighlightId?: InputMaybe; slug: Scalars['String']; @@ -1323,6 +1331,55 @@ export type SaveUrlInput = { url: Scalars['String']; }; +export type SearchError = { + __typename?: 'SearchError'; + errorCodes: Array; +}; + +export enum SearchErrorCode { + Unauthorized = 'UNAUTHORIZED' +} + +export type SearchItem = { + __typename?: 'SearchItem'; + annotation?: Maybe; + author?: Maybe; + contentReader: ContentReader; + createdAt: Scalars['Date']; + description?: Maybe; + id: Scalars['ID']; + image?: Maybe; + isArchived: Scalars['Boolean']; + labels?: Maybe>; + originalArticleUrl?: Maybe; + ownedByViewer?: Maybe; + pageId?: Maybe; + pageType: PageType; + publishedAt?: Maybe; + quote?: Maybe; + readingProgressAnchorIndex?: Maybe; + readingProgressPercent?: Maybe; + shortId?: Maybe; + slug: Scalars['String']; + title: Scalars['String']; + uploadFileId?: Maybe; + url: Scalars['String']; +}; + +export type SearchItemEdge = { + __typename?: 'SearchItemEdge'; + cursor: Scalars['String']; + node: SearchItem; +}; + +export type SearchResult = SearchError | SearchSuccess; + +export type SearchSuccess = { + __typename?: 'SearchSuccess'; + edges: Array; + pageInfo: PageInfo; +}; + export type SetBookmarkArticleError = { __typename?: 'SetBookmarkArticleError'; errorCodes: Array; @@ -2094,6 +2151,12 @@ export type ResolversTypes = { SaveResult: ResolversTypes['SaveError'] | ResolversTypes['SaveSuccess']; SaveSuccess: ResolverTypeWrapper; SaveUrlInput: SaveUrlInput; + SearchError: ResolverTypeWrapper; + SearchErrorCode: SearchErrorCode; + SearchItem: ResolverTypeWrapper; + SearchItemEdge: ResolverTypeWrapper; + SearchResult: ResolversTypes['SearchError'] | ResolversTypes['SearchSuccess']; + SearchSuccess: ResolverTypeWrapper; SetBookmarkArticleError: ResolverTypeWrapper; SetBookmarkArticleErrorCode: SetBookmarkArticleErrorCode; SetBookmarkArticleInput: SetBookmarkArticleInput; @@ -2346,6 +2409,11 @@ export type ResolversParentTypes = { SaveResult: ResolversParentTypes['SaveError'] | ResolversParentTypes['SaveSuccess']; SaveSuccess: SaveSuccess; SaveUrlInput: SaveUrlInput; + SearchError: SearchError; + SearchItem: SearchItem; + SearchItemEdge: SearchItemEdge; + SearchResult: ResolversParentTypes['SearchError'] | ResolversParentTypes['SearchSuccess']; + SearchSuccess: SearchSuccess; SetBookmarkArticleError: SetBookmarkArticleError; SetBookmarkArticleInput: SetBookmarkArticleInput; SetBookmarkArticleResult: ResolversParentTypes['SetBookmarkArticleError'] | ResolversParentTypes['SetBookmarkArticleSuccess']; @@ -2864,7 +2932,6 @@ export type GoogleSignupSuccessResolvers = { annotation?: Resolver, ParentType, ContextType>; - article?: Resolver; createdAt?: Resolver; createdByMe?: Resolver; id?: Resolver; @@ -3100,6 +3167,7 @@ export type QueryResolvers, ParentType, ContextType>; newsletterEmails?: Resolver; reminder?: Resolver>; + search?: Resolver>; sharedArticle?: Resolver>; user?: Resolver>; users?: Resolver; @@ -3180,6 +3248,53 @@ export type SaveSuccessResolvers; }; +export type SearchErrorResolvers = { + errorCodes?: Resolver, ParentType, ContextType>; + __isTypeOf?: IsTypeOfResolverFn; +}; + +export type SearchItemResolvers = { + annotation?: Resolver, ParentType, ContextType>; + author?: Resolver, ParentType, ContextType>; + contentReader?: Resolver; + createdAt?: Resolver; + description?: Resolver, ParentType, ContextType>; + id?: Resolver; + image?: Resolver, ParentType, ContextType>; + isArchived?: Resolver; + labels?: Resolver>, ParentType, ContextType>; + originalArticleUrl?: Resolver, ParentType, ContextType>; + ownedByViewer?: Resolver, ParentType, ContextType>; + pageId?: Resolver, ParentType, ContextType>; + pageType?: Resolver; + publishedAt?: Resolver, ParentType, ContextType>; + quote?: Resolver, ParentType, ContextType>; + readingProgressAnchorIndex?: Resolver, ParentType, ContextType>; + readingProgressPercent?: Resolver, ParentType, ContextType>; + shortId?: Resolver, ParentType, ContextType>; + slug?: Resolver; + title?: Resolver; + uploadFileId?: Resolver, ParentType, ContextType>; + url?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}; + +export type SearchItemEdgeResolvers = { + cursor?: Resolver; + node?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}; + +export type SearchResultResolvers = { + __resolveType: TypeResolveFn<'SearchError' | 'SearchSuccess', ParentType, ContextType>; +}; + +export type SearchSuccessResolvers = { + edges?: Resolver, ParentType, ContextType>; + pageInfo?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}; + export type SetBookmarkArticleErrorResolvers = { errorCodes?: Resolver, ParentType, ContextType>; __isTypeOf?: IsTypeOfResolverFn; @@ -3620,6 +3735,11 @@ export type Resolvers = { SaveError?: SaveErrorResolvers; SaveResult?: SaveResultResolvers; SaveSuccess?: SaveSuccessResolvers; + SearchError?: SearchErrorResolvers; + SearchItem?: SearchItemResolvers; + SearchItemEdge?: SearchItemEdgeResolvers; + SearchResult?: SearchResultResolvers; + SearchSuccess?: SearchSuccessResolvers; SetBookmarkArticleError?: SetBookmarkArticleErrorResolvers; SetBookmarkArticleResult?: SetBookmarkArticleResultResolvers; SetBookmarkArticleSuccess?: SetBookmarkArticleSuccessResolvers; diff --git a/packages/api/src/generated/schema.graphql b/packages/api/src/generated/schema.graphql index 74a59f9de..29d101a6c 100644 --- a/packages/api/src/generated/schema.graphql +++ b/packages/api/src/generated/schema.graphql @@ -540,7 +540,6 @@ type GoogleSignupSuccess { type Highlight { annotation: String - article: Article! createdAt: Date! createdByMe: Boolean! id: ID! @@ -788,6 +787,7 @@ enum PageType { ARTICLE BOOK FILE + HIGHLIGHTS PROFILE UNKNOWN WEBSITE @@ -819,6 +819,7 @@ type Query { me: User newsletterEmails: NewsletterEmailsResult! reminder(linkId: ID!): ReminderResult! + search(after: String, first: Int, query: String): SearchResult! sharedArticle(selectedHighlightId: String, slug: String!, username: String!): SharedArticleResult! user(userId: ID, username: String): UserResult! users: UsersResult! @@ -951,6 +952,51 @@ input SaveUrlInput { url: String! } +type SearchError { + errorCodes: [SearchErrorCode!]! +} + +enum SearchErrorCode { + UNAUTHORIZED +} + +type SearchItem { + annotation: String + author: String + contentReader: ContentReader! + createdAt: Date! + description: String + id: ID! + image: String + isArchived: Boolean! + labels: [Label!] + originalArticleUrl: String + ownedByViewer: Boolean + pageId: ID + pageType: PageType! + publishedAt: Date + quote: String + readingProgressAnchorIndex: Int + readingProgressPercent: Float + shortId: String + slug: String! + title: String! + uploadFileId: ID + url: String! +} + +type SearchItemEdge { + cursor: String! + node: SearchItem! +} + +union SearchResult = SearchError | SearchSuccess + +type SearchSuccess { + edges: [SearchItemEdge!]! + pageInfo: PageInfo! +} + type SetBookmarkArticleError { errorCodes: [SetBookmarkArticleErrorCode!]! } diff --git a/packages/api/src/resolvers/article/index.ts b/packages/api/src/resolvers/article/index.ts index b85ae7d05..aed133929 100644 --- a/packages/api/src/resolvers/article/index.ts +++ b/packages/api/src/resolvers/article/index.ts @@ -22,10 +22,14 @@ import { PageType, QueryArticleArgs, QueryArticlesArgs, + QuerySearchArgs, ResolverFn, SaveArticleReadingProgressError, SaveArticleReadingProgressErrorCode, SaveArticleReadingProgressSuccess, + SearchError, + SearchItem, + SearchSuccess, SetBookmarkArticleError, SetBookmarkArticleErrorCode, SetBookmarkArticleSuccess, @@ -67,6 +71,8 @@ import { createPageSaveRequest } from '../../services/create_page_save_request' import { createIntercomEvent } from '../../utils/intercom' import { analytics } from '../../utils/analytics' import { env } from '../../env' + +import { Page, SearchItem as SearchItemData } from '../../elastic/types' import { createPage, deletePage, @@ -74,8 +80,8 @@ import { getPageByParam, searchPages, updatePage, -} from '../../elastic' -import { Page } from '../../elastic/types' +} from '../../elastic/pages' +import { searchHighlights } from '../../elastic/highlights' export type PartialArticle = Omit< Article, @@ -438,44 +444,45 @@ export const getArticlesResolver = authorized< ArticlesError, QueryArticlesArgs >(async (_obj, params, { claims }) => { - const notNullField = params.sharedOnly ? 'sharedAt' : null const startCursor = params.after || '' const first = params.first || 10 - // Perform basic sanitization. Right now we just allow alphanumeric, space and quote - // so queries can contain phrases like "human race"; - // We can also split out terms like "label:unread". const searchQuery = parseSearchQuery(params.query || undefined) analytics.track({ userId: claims.uid, - event: 'search', + event: 'get_articles', properties: { + env: env.server.apiEnv, query: searchQuery.query, inFilter: searchQuery.inFilter, readFilter: searchQuery.readFilter, typeFilter: searchQuery.typeFilter, labelFilters: searchQuery.labelFilters, sortParams: searchQuery.sortParams, - env: env.server.apiEnv, + hasFilters: searchQuery.hasFilters, + savedDateFilter: searchQuery.savedDateFilter, + publishedDateFilter: searchQuery.publishedDateFilter, }, }) - await createIntercomEvent('search', claims.uid) + await createIntercomEvent('get_articles', claims.uid) const [pages, totalCount] = (await searchPages( { from: Number(startCursor), size: first + 1, // fetch one more item to get next cursor - sort: searchQuery.sortParams || params.sort || undefined, + sort: searchQuery.sortParams, query: searchQuery.query, inFilter: searchQuery.inFilter, readFilter: searchQuery.readFilter, typeFilter: searchQuery.typeFilter, labelFilters: searchQuery.labelFilters, + hasFilters: searchQuery.hasFilters, + savedDateFilter: searchQuery.savedDateFilter, + publishedDateFilter: searchQuery.publishedDateFilter, }, - claims.uid, - notNullField + claims.uid )) || [[], 0] const start = @@ -792,3 +799,106 @@ export const getReadingProgressAnchorIndexForArticleResolver: ResolverFn< return articleReadingProgressAnchorIndex || 0 } + +export const searchResolver = authorized< + SearchSuccess, + SearchError, + QuerySearchArgs +>(async (_obj, params, { claims }) => { + const startCursor = params.after || '' + const first = params.first || 10 + + const searchQuery = parseSearchQuery(params.query || undefined) + + analytics.track({ + userId: claims.uid, + event: 'search', + properties: { + query: searchQuery.query, + inFilter: searchQuery.inFilter, + readFilter: searchQuery.readFilter, + typeFilter: searchQuery.typeFilter, + labelFilters: searchQuery.labelFilters, + sortParams: searchQuery.sortParams, + hasFilters: searchQuery.hasFilters, + savedDateFilter: searchQuery.savedDateFilter, + publishedDateFilter: searchQuery.publishedDateFilter, + env: env.server.apiEnv, + }, + }) + + await createIntercomEvent('search', claims.uid) + + let results: (SearchItemData | Page)[] + let totalCount: number + + const searchType = searchQuery.typeFilter + // search highlights if type:highlights + if (searchType === PageType.Highlights) { + ;[results, totalCount] = (await searchHighlights( + { + from: Number(startCursor), + size: first + 1, // fetch one more item to get next cursor + sort: searchQuery.sortParams, + query: searchQuery.query, + }, + claims.uid + )) || [[], 0] + } else { + // otherwise, search pages + ;[results, totalCount] = (await searchPages( + { + from: Number(startCursor), + size: first + 1, // fetch one more item to get next cursor + sort: searchQuery.sortParams, + query: searchQuery.query, + inFilter: searchQuery.inFilter, + readFilter: searchQuery.readFilter, + typeFilter: searchQuery.typeFilter, + labelFilters: searchQuery.labelFilters, + hasFilters: searchQuery.hasFilters, + savedDateFilter: searchQuery.savedDateFilter, + publishedDateFilter: searchQuery.publishedDateFilter, + }, + claims.uid + )) || [[], 0] + } + + const start = + startCursor && !isNaN(Number(startCursor)) ? Number(startCursor) : 0 + const hasNextPage = results.length > first + const endCursor = String(start + results.length - (hasNextPage ? 1 : 0)) + + if (hasNextPage) { + // remove an extra if exists + results.pop() + } + + const edges = results.map((r) => { + return { + node: { + ...r, + image: r.image && createImageProxyUrl(r.image, 88, 88), + isArchived: !!r.archivedAt, + contentReader: + r.pageType === PageType.File ? ContentReader.Pdf : ContentReader.Web, + originalArticleUrl: r.url, + publishedAt: validatedDate(r.publishedAt), + ownedByViewer: r.userId === claims.uid, + pageType: r.pageType || PageType.Highlights, + } as SearchItem, + cursor: endCursor, + } + }) + + return { + edges, + pageInfo: { + hasPreviousPage: false, + startCursor, + hasNextPage: hasNextPage, + endCursor, + totalCount, + }, + } +}) diff --git a/packages/api/src/resolvers/function_resolvers.ts b/packages/api/src/resolvers/function_resolvers.ts index 000ccf22e..7a99e06c0 100644 --- a/packages/api/src/resolvers/function_resolvers.ts +++ b/packages/api/src/resolvers/function_resolvers.ts @@ -16,6 +16,7 @@ import { LinkShareInfo, PageType, Reaction, + SearchItem, User, } from './../generated/graphql' @@ -54,6 +55,7 @@ import { saveFileResolver, savePageResolver, saveUrlResolver, + searchResolver, setBookmarkArticleResolver, setDeviceTokenResolver, setFollowResolver, @@ -78,7 +80,7 @@ import { generateDownloadSignedUrl, generateUploadFilePathName, } from '../utils/uploads' -import { getPageById, getPageByParam } from '../elastic' +import { getPageByParam } from '../elastic/pages' import { generateApiKeyResolver } from './api_key' /* eslint-disable @typescript-eslint/naming-convention */ @@ -157,6 +159,7 @@ export const functionResolvers = { newsletterEmails: newsletterEmailsResolver, reminder: reminderResolver, labels: labelsResolver, + search: searchResolver, }, User: { async sharedArticles( @@ -394,32 +397,33 @@ export const functionResolvers = { : ContentReader.Web }, async highlights( - article: { id: string; userId?: string }, + article: { id: string; userId?: string; highlights?: Highlight[] }, _: { input: ArticleHighlightsInput }, ctx: WithDataSourcesContext ) { - const includeFriends = false - // TODO: this is a temporary solution until we figure out how collaborative approach would look like - // article has userId only if it's returned by getSharedArticle resolver - if (article.userId) { - const result = await ctx.models.highlight.getForUserArticle( - article.userId, - article.id - ) - return result - } - - const friendsIds = - ctx.claims?.uid && includeFriends - ? await ctx.models.userFriends.getFriends(ctx.claims?.uid) - : [] - - // FIXME: Move this filtering logic to the datalayer - return (await ctx.models.highlight.batchGet(article.id)).filter((h) => - [...(includeFriends ? friendsIds : []), ctx.claims?.uid || ''].some( - (u) => u === h.userId - ) - ) + // const includeFriends = false + // // TODO: this is a temporary solution until we figure out how collaborative approach would look like + // // article has userId only if it's returned by getSharedArticle resolver + // if (article.userId) { + // const result = await ctx.models.highlight.getForUserArticle( + // article.userId, + // article.id + // ) + // return result + // } + // + // const friendsIds = + // ctx.claims?.uid && includeFriends + // ? await ctx.models.userFriends.getFriends(ctx.claims?.uid) + // : [] + // + // // FIXME: Move this filtering logic to the datalayer + // return (await ctx.models.highlight.batchGet(article.id)).filter((h) => + // [...(includeFriends ? friendsIds : []), ctx.claims?.uid || ''].some( + // (u) => u === h.userId + // ) + // ) + return article.highlights || [] }, async shareInfo( article: { id: string; sharedBy?: User; shareInfo?: LinkShareInfo }, @@ -447,9 +451,6 @@ export const functionResolvers = { }, }, Highlight: { - async article(highlight: { articleId: string }, __: unknown) { - return getPageById(highlight.articleId) - }, async user( highlight: { userId: string }, __: unknown, @@ -484,6 +485,19 @@ export const functionResolvers = { return userDataToUser(await ctx.models.user.get(reaction.userId)) }, }, + SearchItem: { + async url(item: SearchItem, _: unknown, ctx: WithDataSourcesContext) { + if (item.pageType == PageType.File && ctx.claims && item.uploadFileId) { + const upload = await ctx.models.uploadFile.get(item.uploadFileId) + if (!upload || !upload.fileName) { + return undefined + } + const filePath = generateUploadFilePathName(upload.id, upload.fileName) + return generateDownloadSignedUrl(filePath) + } + return item.url + }, + }, ...resultResolveTypeResolver('Login'), ...resultResolveTypeResolver('LogOut'), ...resultResolveTypeResolver('GoogleSignup'), @@ -532,4 +546,5 @@ export const functionResolvers = { ...resultResolveTypeResolver('Signup'), ...resultResolveTypeResolver('SetLabels'), ...resultResolveTypeResolver('GenerateApiKey'), + ...resultResolveTypeResolver('Search'), } diff --git a/packages/api/src/resolvers/highlight/index.ts b/packages/api/src/resolvers/highlight/index.ts index 69163de53..d14419c03 100644 --- a/packages/api/src/resolvers/highlight/index.ts +++ b/packages/api/src/resolvers/highlight/index.ts @@ -3,7 +3,6 @@ /* eslint-disable @typescript-eslint/no-floating-promises */ import { authorized } from '../../utils/helpers' import { - Article, CreateHighlightError, CreateHighlightErrorCode, CreateHighlightSuccess, @@ -27,15 +26,20 @@ import { UpdateHighlightSuccess, User, } from '../../generated/graphql' -import { HighlightData } from '../../datalayer/highlight/model' import { env } from '../../env' import { analytics } from '../../utils/analytics' -import { getPageById } from '../../elastic' +import { Highlight as HighlightData } from '../../elastic/types' +import { getPageById, updatePage } from '../../elastic/pages' +import { + addHighlightToPage, + deleteHighlight, + getHighlightById, + updateHighlight, +} from '../../elastic/highlights' const highlightDataToHighlight = (highlight: HighlightData): Highlight => ({ ...highlight, user: highlight.userId as unknown as User, - article: highlight.articleId as unknown as Article, updatedAt: highlight.updatedAt || highlight.createdAt, replies: [], reactions: [], @@ -46,11 +50,10 @@ export const createHighlightResolver = authorized< CreateHighlightSuccess, CreateHighlightError, MutationCreateHighlightArgs ->(async (_, { input }, { models, claims, log }) => { - const { articleId } = input - const article = await getPageById(articleId) - - if (!article) { +>(async (_, { input }, { claims, log, pubsub }) => { + const { articleId: pageId } = input + const page = await getPageById(pageId) + if (!page) { return { errorCodes: [CreateHighlightErrorCode.NotFound], } @@ -60,7 +63,7 @@ export const createHighlightResolver = authorized< userId: claims.uid, event: 'highlight_created', properties: { - articleId: article.id, + pageId, env: env.server.apiEnv, }, }) @@ -72,12 +75,23 @@ export const createHighlightResolver = authorized< } try { - const highlight = await models.highlight.create({ - ...input, - articleId: undefined, + const highlight: HighlightData = { + updatedAt: new Date(), + createdAt: new Date(), userId: claims.uid, - elasticPageId: article.id, - }) + ...input, + } + + if ( + !(await addHighlightToPage(pageId, highlight, { + pubsub, + uid: claims.uid, + })) + ) { + return { + errorCodes: [CreateHighlightErrorCode.NotFound], + } + } log.info('Creating a new highlight', { highlight, @@ -101,22 +115,27 @@ export const mergeHighlightResolver = authorized< MergeHighlightSuccess, MergeHighlightError, MutationMergeHighlightArgs ->(async (_, { input }, { authTrx, models, claims, log }) => { - const { articleId } = input +>(async (_, { input }, { claims, log, pubsub }) => { + const { articleId: pageId } = input const { overlapHighlightIdList, ...newHighlightInput } = input - const articleHighlights = await models.highlight.batchGet(articleId) - - if (!articleHighlights.length) { + const page = await getPageById(pageId) + if (!page || !page.highlights) { return { errorCodes: [MergeHighlightErrorCode.NotFound], } } + const articleHighlights = page.highlights + /* Compute merged annotation form the order of highlights appearing on page */ const overlapAnnotations: { [id: string]: string } = {} - articleHighlights.forEach((highlight) => { - if (overlapHighlightIdList.includes(highlight.id) && highlight.annotation) { - overlapAnnotations[highlight.id] = highlight.annotation + articleHighlights.forEach((highlight, index) => { + if (overlapHighlightIdList.includes(highlight.id)) { + articleHighlights.splice(index, 1) + + if (highlight.annotation) { + overlapAnnotations[highlight.id] = highlight.annotation + } } }) const mergedAnnotation: string[] = [] @@ -127,17 +146,20 @@ export const mergeHighlightResolver = authorized< }) try { - const highlight = await authTrx(async (tx) => { - await models.highlight.deleteMany(overlapHighlightIdList, tx) - return await models.highlight.create({ - ...newHighlightInput, - articleId: undefined, - annotation: mergedAnnotation ? mergedAnnotation.join('\n') : null, - userId: claims.uid, - elasticPageId: newHighlightInput.articleId, - }) - }) - if (!highlight) { + const highlight: HighlightData = { + ...newHighlightInput, + updatedAt: new Date(), + createdAt: new Date(), + userId: claims.uid, + annotation: mergedAnnotation ? mergedAnnotation.join('\n') : null, + } + + const merged = await updatePage( + pageId, + { highlights: articleHighlights.concat(highlight) }, + { pubsub, uid: claims.uid } + ) + if (!merged) { throw new Error('Failed to create merged highlight') } @@ -147,7 +169,7 @@ export const mergeHighlightResolver = authorized< source: 'resolver', resolver: 'mergeHighlightResolver', uid: claims.uid, - articleId: articleId, + pageId, }, }) @@ -175,9 +197,9 @@ export const updateHighlightResolver = authorized< UpdateHighlightSuccess, UpdateHighlightError, MutationUpdateHighlightArgs ->(async (_, { input }, { authTrx, models, claims, log }) => { +>(async (_, { input }, { pubsub, claims, log }) => { const { highlightId } = input - const highlight = await models.highlight.get(highlightId) + const highlight = await getHighlightById(highlightId) if (!highlight?.id) { return { @@ -197,16 +219,11 @@ export const updateHighlightResolver = authorized< } } - const updatedHighlight = await authTrx((tx) => - models.highlight.update( - highlightId, - { - annotation: input.annotation, - sharedAt: input.sharedAt, - }, - tx - ) - ) + const updatedHighlight: HighlightData = { + ...highlight, + annotation: input.annotation, + updatedAt: new Date(), + } log.info('Updating a highlight', { updatedHighlight, @@ -217,6 +234,17 @@ export const updateHighlightResolver = authorized< }, }) + const updated = await updateHighlight(updatedHighlight, { + pubsub, + uid: claims.uid, + }) + + if (!updated) { + return { + errorCodes: [UpdateHighlightErrorCode.NotFound], + } + } + return { highlight: highlightDataToHighlight(updatedHighlight) } }) @@ -224,8 +252,8 @@ export const deleteHighlightResolver = authorized< DeleteHighlightSuccess, DeleteHighlightError, MutationDeleteHighlightArgs ->(async (_, { highlightId }, { authTrx, models, claims, log }) => { - const highlight = await models.highlight.get(highlightId) +>(async (_, { highlightId }, { claims, log, pubsub }) => { + const highlight = await getHighlightById(highlightId) if (!highlight?.id) { return { @@ -239,18 +267,19 @@ export const deleteHighlightResolver = authorized< } } - const deletedHighlight = await authTrx((tx) => - models.highlight.delete(highlightId, tx) - ) + const deleted = await deleteHighlight(highlightId, { + pubsub, + uid: claims.uid, + }) - if ('error' in deletedHighlight) { + if (!deleted) { return { errorCodes: [DeleteHighlightErrorCode.NotFound], } } log.info('Deleting a highlight', { - deletedHighlight, + highlight, labels: { source: 'resolver', resolver: 'deleteHighlightResolver', @@ -258,15 +287,15 @@ export const deleteHighlightResolver = authorized< }, }) - return { highlight: highlightDataToHighlight(deletedHighlight) } + return { highlight: highlightDataToHighlight(highlight) } }) export const setShareHighlightResolver = authorized< SetShareHighlightSuccess, SetShareHighlightError, MutationSetShareHighlightArgs ->(async (_, { input: { id, share } }, { authTrx, models, claims, log }) => { - const highlight = await models.highlight.get(id) +>(async (_, { input: { id, share } }, { pubsub, claims, log }) => { + const highlight = await getHighlightById(id) if (!highlight?.id) { return { @@ -287,16 +316,22 @@ export const setShareHighlightResolver = authorized< labels: { source: 'resolver', resolver: 'setShareHighlightResolver', - articleId: highlight.articleId, userId: highlight.userId, }, }) - const updatedHighlight = await authTrx((tx) => - models.highlight.update(id, { sharedAt }, tx) - ) + const updatedHighlight: HighlightData = { + ...highlight, + sharedAt, + updatedAt: new Date(), + } - if (!updatedHighlight || 'error' in updatedHighlight) { + const updated = await updateHighlight(updatedHighlight, { + pubsub, + uid: claims.uid, + }) + + if (!updated) { return { errorCodes: [SetShareHighlightErrorCode.NotFound], } diff --git a/packages/api/src/resolvers/labels/index.ts b/packages/api/src/resolvers/labels/index.ts index 3f428c8f2..e2813861e 100644 --- a/packages/api/src/resolvers/labels/index.ts +++ b/packages/api/src/resolvers/labels/index.ts @@ -26,9 +26,10 @@ import { User } from '../../entity/user' import { Label } from '../../entity/label' import { ILike, In } from 'typeorm' import { getRepository, setClaims } from '../../entity/utils' -import { deleteLabelInPages, getPageById, updatePage } from '../../elastic' import { createPubSubClient } from '../../datalayer/pubsub' import { AppDataSource } from '../../server' +import { getPageById, updatePage } from '../../elastic/pages' +import { deleteLabelInPages } from '../../elastic/labels' export const labelsResolver = authorized( async (_obj, _params, { claims: { uid }, log }) => { diff --git a/packages/api/src/resolvers/links/index.ts b/packages/api/src/resolvers/links/index.ts index 0f9705908..48554b69c 100644 --- a/packages/api/src/resolvers/links/index.ts +++ b/packages/api/src/resolvers/links/index.ts @@ -14,7 +14,7 @@ import { import { authorized } from '../../utils/helpers' import { analytics } from '../../utils/analytics' import { env } from '../../env' -import { updatePage } from '../../elastic' +import { updatePage } from '../../elastic/pages' export const updateLinkShareInfoResolver = authorized< UpdateLinkShareInfoSuccess, diff --git a/packages/api/src/routers/svc/content.ts b/packages/api/src/routers/svc/content.ts index ec89afb85..efde65410 100644 --- a/packages/api/src/routers/svc/content.ts +++ b/packages/api/src/routers/svc/content.ts @@ -6,8 +6,8 @@ import { createPubSubClient, readPushSubscription, } from '../../datalayer/pubsub' -import { getPageByParam, updatePage } from '../../elastic' import { Page } from '../../elastic/types' +import { getPageByParam, updatePage } from '../../elastic/pages' interface UpdateContentMessage { fileId: string diff --git a/packages/api/src/routers/svc/pdf_attachments.ts b/packages/api/src/routers/svc/pdf_attachments.ts index ba672a5b2..f2ff1a5cb 100644 --- a/packages/api/src/routers/svc/pdf_attachments.ts +++ b/packages/api/src/routers/svc/pdf_attachments.ts @@ -14,9 +14,9 @@ import { analytics } from '../../utils/analytics' import { getNewsletterEmail } from '../../services/newsletters' import { setClaims } from '../../datalayer/helpers' import { generateSlug } from '../../utils/helpers' -import { createPage } from '../../elastic' import { createPubSubClient } from '../../datalayer/pubsub' import { Page } from '../../elastic/types' +import { createPage } from '../../elastic/pages' export function pdfAttachmentsRouter() { const router = express.Router() diff --git a/packages/api/src/schema.ts b/packages/api/src/schema.ts index f18a3786b..2e4ecd4f3 100755 --- a/packages/api/src/schema.ts +++ b/packages/api/src/schema.ts @@ -286,6 +286,7 @@ const schema = gql` FILE PROFILE WEBSITE + HIGHLIGHTS UNKNOWN } @@ -569,7 +570,6 @@ const schema = gql` # used for simplified url format shortId: String! user: User! - article: Article! quote: String! # piece of content before the quote prefix: String @@ -1393,6 +1393,56 @@ const schema = gql` BAD_REQUEST } + # Query: search + union SearchResult = SearchSuccess | SearchError + + type SearchItem { + # used for pages + id: ID! + title: String! + slug: String! + # for uploaded file articles (PDFs), the URL here is the saved omnivore link in GCS + url: String! + pageType: PageType! + contentReader: ContentReader! + createdAt: Date! + isArchived: Boolean! + readingProgressPercent: Float + readingProgressAnchorIndex: Int + author: String + image: String + description: String + publishedAt: Date + ownedByViewer: Boolean + # for uploaded file articles (PDFs), we track the original article URL separately! + originalArticleUrl: String + uploadFileId: ID + # used for highlights + pageId: ID + shortId: String + quote: String + annotation: String + labels: [Label!] + } + + type SearchItemEdge { + cursor: String! + node: SearchItem! + } + + type SearchSuccess { + edges: [SearchItemEdge!]! + pageInfo: PageInfo! + } + + enum SearchErrorCode { + UNAUTHORIZED + } + + type SearchError { + errorCodes: [SearchErrorCode!]! + } + # Mutations type Mutation { googleLogin(input: GoogleLoginInput!): LoginResult! @@ -1490,6 +1540,7 @@ const schema = gql` newsletterEmails: NewsletterEmailsResult! reminder(linkId: ID!): ReminderResult! labels: LabelsResult! + search(after: String, first: Int, query: String): SearchResult! } ` diff --git a/packages/api/src/services/create_page_save_request.ts b/packages/api/src/services/create_page_save_request.ts index be4a81b16..60d82fc69 100644 --- a/packages/api/src/services/create_page_save_request.ts +++ b/packages/api/src/services/create_page_save_request.ts @@ -9,7 +9,7 @@ import { } from '../generated/graphql' import { articleSavingRequestDataToArticleSavingRequest } from '../utils/helpers' import * as privateIpLib from 'private-ip' -import { countByCreatedAt } from '../elastic' +import { countByCreatedAt } from '../elastic/pages' const isPrivateIP = privateIpLib.default diff --git a/packages/api/src/services/labels.ts b/packages/api/src/services/labels.ts index 5b3be6915..7b908dd7f 100644 --- a/packages/api/src/services/labels.ts +++ b/packages/api/src/services/labels.ts @@ -2,7 +2,7 @@ import { Label } from '../entity/label' import { ILike, In } from 'typeorm' import { PageContext } from '../elastic/types' import { User } from '../entity/user' -import { addLabelInPage } from '../elastic' +import { addLabelInPage } from '../elastic/labels' import { getRepository } from '../entity/utils' import { Link } from '../entity/link' import DataLoader from 'dataloader' diff --git a/packages/api/src/services/reports.ts b/packages/api/src/services/reports.ts index ed545b075..5f39b669d 100644 --- a/packages/api/src/services/reports.ts +++ b/packages/api/src/services/reports.ts @@ -1,7 +1,7 @@ import { ReportItemInput, ReportType } from '../generated/graphql' import { ContentDisplayReport } from '../entity/reports/content_display_report' import { AbuseReport } from '../entity/reports/abuse_report' -import { getPageById } from '../elastic' +import { getPageById } from '../elastic/pages' import { getRepository } from '../entity/utils' export const saveContentDisplayReport = async ( diff --git a/packages/api/src/services/save_email.ts b/packages/api/src/services/save_email.ts index a733f84be..6f04b5d6c 100644 --- a/packages/api/src/services/save_email.ts +++ b/packages/api/src/services/save_email.ts @@ -7,7 +7,7 @@ import { import normalizeUrl from 'normalize-url' import { PubsubClient } from '../datalayer/pubsub' import { Page } from '../elastic/types' -import { createPage, getPageByParam, updatePage } from '../elastic' +import { createPage, getPageByParam, updatePage } from '../elastic/pages' export type SaveContext = { pubsub: PubsubClient diff --git a/packages/api/src/services/save_file.ts b/packages/api/src/services/save_file.ts index 592cdd064..dabf5f09a 100644 --- a/packages/api/src/services/save_file.ts +++ b/packages/api/src/services/save_file.ts @@ -13,7 +13,7 @@ import { DataModels } from '../resolvers/types' import { generateSlug } from '../utils/helpers' import { getStorageFileDetails, makeStorageFilePublic } from '../utils/uploads' import { createSavingRequest } from './save_page' -import { createPage, getPageByParam, updatePage } from '../elastic' +import { createPage, getPageByParam, updatePage } from '../elastic/pages' type SaveContext = { pubsub: PubsubClient diff --git a/packages/api/src/services/save_page.ts b/packages/api/src/services/save_page.ts index fb97d0fd6..9feecffc4 100644 --- a/packages/api/src/services/save_page.ts +++ b/packages/api/src/services/save_page.ts @@ -14,8 +14,8 @@ import normalizeUrl from 'normalize-url' import { createPageSaveRequest } from './create_page_save_request' import { kx } from '../datalayer/knex_config' import { setClaims } from '../datalayer/helpers' -import { createPage, getPageByParam, updatePage } from '../elastic' import { Page } from '../elastic/types' +import { createPage, getPageByParam, updatePage } from '../elastic/pages' type SaveContext = { pubsub: PubsubClient diff --git a/packages/api/src/utils/search.ts b/packages/api/src/utils/search.ts index b0f914607..5ffbc44b8 100644 --- a/packages/api/src/utils/search.ts +++ b/packages/api/src/utils/search.ts @@ -9,7 +9,7 @@ import { SearchParserKeyWordOffset, SearchParserTextOffset, } from 'search-query-parser' -import { PageType, SortBy, SortOrder, SortParams } from '../generated/graphql' +import { PageType } from '../generated/graphql' export enum ReadFilter { ALL, @@ -27,9 +27,12 @@ export type SearchFilter = { query: string | undefined inFilter: InFilter readFilter: ReadFilter - typeFilter?: PageType | undefined + typeFilter?: PageType labelFilters: LabelFilter[] sortParams?: SortParams + hasFilters: HasFilter[] + savedDateFilter?: DateRangeFilter + publishedDateFilter?: DateRangeFilter } export enum LabelFilterType { @@ -42,6 +45,32 @@ export type LabelFilter = { labels: string[] } +export enum HasFilter { + HIGHLIGHTS, + SHARED_AT, +} + +export type DateRangeFilter = { + startDate?: Date + endDate?: Date +} + +export enum SortBy { + SAVED = 'savedAt', + UPDATED = 'updatedAt', + SCORE = '_score', +} + +export enum SortOrder { + ASCENDING = 'asc', + DESCENDING = 'desc', +} + +export type SortParams = { + by: SortBy + order?: SortOrder +} + const parseIsFilter = (str: string | undefined): ReadFilter => { switch (str?.toUpperCase()) { case 'READ': @@ -72,7 +101,7 @@ const parseTypeFilter = (str: string | undefined): PageType | undefined => { return undefined } - switch (str) { + switch (str.toLowerCase()) { case 'article': return PageType.Article case 'book': @@ -86,6 +115,8 @@ const parseTypeFilter = (str: string | undefined): PageType | undefined => { return PageType.Website case 'unknown': return PageType.Unknown + case 'highlights': + return PageType.Highlights } return undefined } @@ -115,25 +146,55 @@ const parseSortParams = (str?: string): SortParams | undefined => { return undefined } - const [sort, order] = str.split(':') + const [sort, order] = str.split('-') const sortOrder = - order?.toUpperCase() === 'ASC' ? SortOrder.Ascending : SortOrder.Descending + order?.toUpperCase() === 'ASC' ? SortOrder.ASCENDING : SortOrder.DESCENDING switch (sort.toUpperCase()) { - case 'UPDATED_TIME': - case 'SAVED_AT': + case 'UPDATED': return { - by: SortBy.SavedAt, + by: SortBy.UPDATED, + order: sortOrder, + } + case 'SAVED': + return { + by: SortBy.SAVED, order: sortOrder, } case 'SCORE': // sort by score does not need an order return { - by: SortBy.Score, + by: SortBy.SCORE, } } } +const parseHasFilter = (str?: string): HasFilter | undefined => { + if (str === undefined) { + return undefined + } + + switch (str.toUpperCase()) { + case 'HIGHLIGHTS': + return HasFilter.HIGHLIGHTS + } +} + +const parseDateRangeFilter = (str?: string): DateRangeFilter | undefined => { + if (str === undefined) { + return undefined + } + + const [start, end] = str.split('..') + const startDate = start && start !== '*' ? new Date(start) : undefined + const endDate = end && end !== '*' ? new Date(end) : undefined + + return { + startDate, + endDate, + } +} + export const parseSearchQuery = (query: string | undefined): SearchFilter => { const searchQuery = query ? query.replace(/\W\s":/g, '') : undefined const result: SearchFilter = { @@ -141,6 +202,7 @@ export const parseSearchQuery = (query: string | undefined): SearchFilter => { readFilter: ReadFilter.ALL, inFilter: searchQuery ? InFilter.ALL : InFilter.INBOX, labelFilters: [], + hasFilters: [], } if (!searchQuery) { @@ -149,11 +211,21 @@ export const parseSearchQuery = (query: string | undefined): SearchFilter => { inFilter: InFilter.INBOX, readFilter: ReadFilter.ALL, labelFilters: [], + hasFilters: [], } } const parsed = parse(searchQuery, { - keywords: ['in', 'is', 'type', 'label', 'sort'], + keywords: [ + 'in', + 'is', + 'type', + 'label', + 'sort', + 'has', + 'saved', + 'published', + ], tokenize: true, }) if (parsed.offsets) { @@ -197,10 +269,20 @@ export const parseSearchQuery = (query: string | undefined): SearchFilter => { labelFilter && result.labelFilters.push(labelFilter) break } - case 'sort': { + case 'sort': result.sortParams = parseSortParams(keyword.value) break + case 'has': { + const hasFilter = parseHasFilter(keyword.value) + hasFilter !== undefined && result.hasFilters.push(hasFilter) + break } + case 'saved': + result.savedDateFilter = parseDateRangeFilter(keyword.value) + break + case 'published': + result.publishedDateFilter = parseDateRangeFilter(keyword.value) + break } } } diff --git a/packages/api/test/elastic/index.test.ts b/packages/api/test/elastic/index.test.ts index 29e86d07d..d3d6e73eb 100644 --- a/packages/api/test/elastic/index.test.ts +++ b/packages/api/test/elastic/index.test.ts @@ -1,6 +1,9 @@ import 'mocha' +import { expect } from 'chai' +import { InFilter, ReadFilter } from '../../src/utils/search' +import { Highlight, Page, PageContext, PageType } from '../../src/elastic/types' +import { createPubSubClient } from '../../src/datalayer/pubsub' import { - addLabelInPage, countByCreatedAt, createPage, deletePage, @@ -8,12 +11,12 @@ import { getPageByParam, searchPages, updatePage, -} from '../../src/elastic' -import { PageType } from '../../src/generated/graphql' -import { expect } from 'chai' -import { InFilter, ReadFilter } from '../../src/utils/search' -import { Page, PageContext } from '../../src/elastic/types' -import { createPubSubClient } from '../../src/datalayer/pubsub' +} from '../../src/elastic/pages' +import { addLabelInPage } from '../../src/elastic/labels' +import { + addHighlightToPage, + searchHighlights, +} from '../../src/elastic/highlights' describe('elastic api', () => { const userId = 'userId' @@ -204,4 +207,33 @@ describe('elastic api', () => { expect(count).to.eq(1) }) }) + + describe('searchHighlights', () => { + const highlightId = 'highlightId' + + before(async () => { + const highlightData: Highlight = { + patch: 'test patch', + quote: 'test content', + shortId: 'test shortId', + id: highlightId, + userId: page.userId, + createdAt: new Date(), + } + + await addHighlightToPage(page.id, highlightData, ctx) + }) + + it('searches highlights', async () => { + const [searchResults, count] = (await searchHighlights( + { + query: 'test', + }, + page.userId + )) || [[], 0] + + expect(count).to.eq(1) + expect(searchResults[0].id).to.eq(highlightId) + }) + }) }) diff --git a/packages/api/test/global-setup.ts b/packages/api/test/global-setup.ts index f96afabb6..2025c97f7 100644 --- a/packages/api/test/global-setup.ts +++ b/packages/api/test/global-setup.ts @@ -1,5 +1,6 @@ import { createTestConnection } from './db' import { initElasticsearch } from '../src/elastic' +import { startApolloServer } from './util' export const mochaGlobalSetup = async () => { await createTestConnection() @@ -7,4 +8,7 @@ export const mochaGlobalSetup = async () => { await initElasticsearch() console.log('elasticsearch initialized') + + await startApolloServer() + console.log('apollo server started') } diff --git a/packages/api/test/global-teardown.ts b/packages/api/test/global-teardown.ts index 259f354a6..ff2b9e6a0 100644 --- a/packages/api/test/global-teardown.ts +++ b/packages/api/test/global-teardown.ts @@ -1,6 +1,12 @@ import { AppDataSource } from '../src/server' +import { stopApolloServer } from './util' +import { kx } from '../src/datalayer/knex_config' export const mochaGlobalTeardown = async () => { await AppDataSource.destroy() + await kx.destroy() console.log('db connection closed') + + await stopApolloServer() + console.log('apollo server stopped') } diff --git a/packages/api/test/resolvers/article.test.ts b/packages/api/test/resolvers/article.test.ts index 3f0e1a6b5..901329bbe 100644 --- a/packages/api/test/resolvers/article.test.ts +++ b/packages/api/test/resolvers/article.test.ts @@ -11,17 +11,18 @@ import 'mocha' import { User } from '../../src/entity/user' import chaiString from 'chai-string' import { Label } from '../../src/entity/label' +import { UploadFileStatus } from '../../src/generated/graphql' +import { Highlight, Page, PageContext, PageType } from '../../src/elastic/types' +import { UploadFile } from '../../src/entity/upload_file' +import { createPubSubClient } from '../../src/datalayer/pubsub' +import { getRepository } from '../../src/entity/utils' import { createPage, deletePage, getPageById, updatePage, -} from '../../src/elastic' -import { PageType, UploadFileStatus } from '../../src/generated/graphql' -import { Page, PageContext } from '../../src/elastic/types' -import { UploadFile } from '../../src/entity/upload_file' -import { createPubSubClient } from '../../src/datalayer/pubsub' -import { getRepository } from '../../src/entity/utils' +} from '../../src/elastic/pages' +import { addHighlightToPage } from '../../src/elastic/highlights' chai.use(chaiString) @@ -85,15 +86,11 @@ const createArticleQuery = ( ` } -const articlesQuery = (after = '', order = 'ASCENDING') => { +const articlesQuery = (after = '') => { return ` query { articles( sharedOnly: ${false} - sort: { - order: ${order} - by: UPDATED_TIME - } after: "${after}" first: 5 query: "") { @@ -136,6 +133,17 @@ const getArticleQuery = (slug: string) => { article { id slug + highlights { + id + shortId + quote + prefix + suffix + patch + annotation + sharedAt + createdAt + } } } ... on ArticleError { @@ -146,6 +154,37 @@ const getArticleQuery = (slug: string) => { ` } +const searchQuery = (keyword = '') => { + return ` + query { + search( + after: "" + first: 5 + query: "${keyword}") { + ... on SearchSuccess { + edges { + cursor + node { + id + url + } + } + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + totalCount + } + } + ... on SearchError { + errorCodes + } + } + } + ` +} + const savePageQuery = (url: string, title: string, originalContent: string) => { return ` mutation { @@ -302,6 +341,7 @@ describe('Article API', () => { describe('GetArticle', () => { const realSlug = 'testing-is-really-fun-with-omnivore' + let query = '' let slug = '' let pageId: string | undefined @@ -321,6 +361,15 @@ describe('Article API', () => { readingProgressAnchorIndex: 0, url: 'https://blog.omnivore.app/test-with-omnivore', savedAt: new Date(), + highlights: [ + { + id: 'test id', + shortId: 'test short id', + createdAt: new Date(), + patch: 'test patch', + quote: 'test quote', + }, + ], } as Page pageId = await createPage(page, ctx) }) @@ -335,19 +384,25 @@ describe('Article API', () => { query = getArticleQuery(slug) }) - context('when article exists', () => { + context('when page exists', () => { before(() => { slug = realSlug }) - it('should return the article', async () => { + it('should return the page', async () => { const res = await graphqlRequest(query, authToken).expect(200) expect(res.body.data.article.article.slug).to.eql(slug) }) + + it('should return highlights', async () => { + const res = await graphqlRequest(query, authToken).expect(200) + + expect(res.body.data.article.article.highlights).to.length(1) + }) }) - context('when article does not exist', () => { + context('when page does not exist', () => { before(() => { slug = 'not-a-real-slug' }) @@ -418,11 +473,6 @@ describe('Article API', () => { }) context('when there are pages with labels', () => { - before(() => { - // get the last page - after = '14' - }) - it('should return labels', async () => { const res = await graphqlRequest(query, authToken).expect(200) @@ -437,15 +487,15 @@ describe('Article API', () => { after = '' }) - it('should return the first five items', async () => { + it('should return the first five items in desc order', async () => { const res = await graphqlRequest(query, authToken).expect(200) expect(res.body.data.articles.edges.length).to.eql(5) - expect(res.body.data.articles.edges[0].node.id).to.eql(pages[0].id) - expect(res.body.data.articles.edges[1].node.id).to.eql(pages[1].id) - expect(res.body.data.articles.edges[2].node.id).to.eql(pages[2].id) - expect(res.body.data.articles.edges[3].node.id).to.eql(pages[3].id) - expect(res.body.data.articles.edges[4].node.id).to.eql(pages[4].id) + expect(res.body.data.articles.edges[0].node.id).to.eql(pages[14].id) + expect(res.body.data.articles.edges[1].node.id).to.eql(pages[13].id) + expect(res.body.data.articles.edges[2].node.id).to.eql(pages[12].id) + expect(res.body.data.articles.edges[3].node.id).to.eql(pages[11].id) + expect(res.body.data.articles.edges[4].node.id).to.eql(pages[10].id) }) it('should set the pageInfo', async () => { @@ -471,11 +521,11 @@ describe('Article API', () => { const res = await graphqlRequest(query, authToken).expect(200) expect(res.body.data.articles.edges.length).to.eql(5) - expect(res.body.data.articles.edges[0].node.id).to.eql(pages[5].id) - expect(res.body.data.articles.edges[1].node.id).to.eql(pages[6].id) + expect(res.body.data.articles.edges[0].node.id).to.eql(pages[9].id) + expect(res.body.data.articles.edges[1].node.id).to.eql(pages[8].id) expect(res.body.data.articles.edges[2].node.id).to.eql(pages[7].id) - expect(res.body.data.articles.edges[3].node.id).to.eql(pages[8].id) - expect(res.body.data.articles.edges[4].node.id).to.eql(pages[9].id) + expect(res.body.data.articles.edges[3].node.id).to.eql(pages[6].id) + expect(res.body.data.articles.edges[4].node.id).to.eql(pages[5].id) }) it('should set the pageInfo', async () => { @@ -532,7 +582,7 @@ describe('Article API', () => { // set a slight delay to make sure the page is updated setTimeout(async () => { let allLinks = await graphqlRequest( - articlesQuery('', 'DESCENDING'), + articlesQuery(''), authToken ).expect(200) const justSavedId = allLinks.body.data.articles.edges[0].node.id @@ -541,10 +591,9 @@ describe('Article API', () => { // test the negative case, ensuring the archive link wasn't returned setTimeout(async () => { - allLinks = await graphqlRequest( - articlesQuery('', 'DESCENDING'), - authToken - ).expect(200) + allLinks = await graphqlRequest(articlesQuery(''), authToken).expect( + 200 + ) expect(allLinks.body.data.articles.edges[0].node.url).to.not.eq(url) }, 100) @@ -555,10 +604,9 @@ describe('Article API', () => { ).expect(200) setTimeout(async () => { - allLinks = await graphqlRequest( - articlesQuery('', 'DESCENDING'), - authToken - ).expect(200) + allLinks = await graphqlRequest(articlesQuery(''), authToken).expect( + 200 + ) expect(allLinks.body.data.articles.edges[0].node.url).to.eq(url) }, 100) }) @@ -729,4 +777,91 @@ describe('Article API', () => { }) }) }) + + describe('Search API', () => { + const url = 'https://blog.omnivore.app/p/getting-started-with-omnivore' + const pages: Page[] = [] + const highlights: Highlight[] = [] + + let query = '' + let keyword = '' + + before(async () => { + // Create some test pages + for (let i = 0; i < 5; i++) { + const page: Page = { + id: '', + hash: 'test hash', + userId: user.id, + pageType: PageType.Article, + title: 'test title', + content: '

search page

', + slug: 'test slug', + createdAt: new Date(), + updatedAt: new Date(), + readingProgressPercent: 0, + readingProgressAnchorIndex: 0, + url: url, + savedAt: new Date(), + } + const pageId = await createPage(page, ctx) + if (!pageId) { + expect.fail('Failed to create page') + } + page.id = pageId + pages.push(page) + + // Create some test highlights + const highlight: Highlight = { + id: `highlight-${i}`, + patch: 'test patch', + shortId: 'test shortId', + userId: user.id, + quote: '

search highlight

', + createdAt: new Date(), + updatedAt: new Date(), + } + await addHighlightToPage(pageId, highlight, ctx) + highlights.push(highlight) + } + }) + + beforeEach(async () => { + query = searchQuery(keyword) + }) + + context('when type:highlights is not in the query', () => { + before(() => { + keyword = 'search' + }) + + it('should return pages in descending order', async () => { + const res = await graphqlRequest(query, authToken).expect(200) + + expect(res.body.data.search.edges.length).to.eql(5) + expect(res.body.data.search.edges[0].node.id).to.eq(pages[4].id) + expect(res.body.data.search.edges[1].node.id).to.eq(pages[3].id) + expect(res.body.data.search.edges[2].node.id).to.eq(pages[2].id) + expect(res.body.data.search.edges[3].node.id).to.eq(pages[1].id) + expect(res.body.data.search.edges[4].node.id).to.eq(pages[0].id) + }) + }) + + context('when type:highlights is in the query', () => { + before(() => { + keyword = 'search type:highlights' + }) + + it('should return highlights in descending order', async () => { + const res = await graphqlRequest(query, authToken).expect(200) + + expect(res.body.data.search.edges.length).to.eq(5) + expect(res.body.data.search.edges[0].node.id).to.eq(highlights[4].id) + expect(res.body.data.search.edges[1].node.id).to.eq(highlights[3].id) + expect(res.body.data.search.edges[2].node.id).to.eq(highlights[2].id) + expect(res.body.data.search.edges[3].node.id).to.eq(highlights[1].id) + expect(res.body.data.search.edges[4].node.id).to.eq(highlights[0].id) + }) + }) + }) }) diff --git a/packages/api/test/resolvers/highlight.test.ts b/packages/api/test/resolvers/highlight.test.ts index f76898897..fbd3158e5 100644 --- a/packages/api/test/resolvers/highlight.test.ts +++ b/packages/api/test/resolvers/highlight.test.ts @@ -10,9 +10,9 @@ import { expect } from 'chai' import 'mocha' import { User } from '../../src/entity/user' import chaiString from 'chai-string' -import { deletePage } from '../../src/elastic' import { createPubSubClient } from '../../src/datalayer/pubsub' import { PageContext } from '../../src/elastic/types' +import { deletePage } from '../../src/elastic/pages' chai.use(chaiString) diff --git a/packages/api/test/resolvers/labels.test.ts b/packages/api/test/resolvers/labels.test.ts index 9ef4fb7d7..e8f4594a0 100644 --- a/packages/api/test/resolvers/labels.test.ts +++ b/packages/api/test/resolvers/labels.test.ts @@ -10,8 +10,8 @@ import { expect } from 'chai' import 'mocha' import { User } from '../../src/entity/user' import { Page } from '../../src/elastic/types' -import { getPageById } from '../../src/elastic' import { getRepository } from '../../src/entity/utils' +import { getPageById } from '../../src/elastic/pages' describe('Labels API', () => { const username = 'fakeUser' diff --git a/packages/api/test/routers/pdf_attachments.test.ts b/packages/api/test/routers/pdf_attachments.test.ts index 9e0648fe0..36e606b81 100644 --- a/packages/api/test/routers/pdf_attachments.test.ts +++ b/packages/api/test/routers/pdf_attachments.test.ts @@ -8,7 +8,7 @@ import { User } from '../../src/entity/user' import 'mocha' import * as jwt from 'jsonwebtoken' import { expect } from 'chai' -import { getPageById } from '../../src/elastic' +import { getPageById } from '../../src/elastic/pages' describe('PDF attachments Router', () => { const username = 'fakeUser' diff --git a/packages/api/test/services/save_email.test.ts b/packages/api/test/services/save_email.test.ts index cd4724636..fb06c4f95 100644 --- a/packages/api/test/services/save_email.test.ts +++ b/packages/api/test/services/save_email.test.ts @@ -4,7 +4,7 @@ import 'chai/register-should' import { createTestUser, deleteTestUser } from '../db' import { SaveContext, saveEmail } from '../../src/services/save_email' import { createPubSubClient } from '../../src/datalayer/pubsub' -import { getPageByParam } from '../../src/elastic' +import { getPageByParam } from '../../src/elastic/pages' describe('saveEmail', () => { const username = 'fakeUser' diff --git a/packages/api/test/services/save_newsletter_email.test.ts b/packages/api/test/services/save_newsletter_email.test.ts index 5fda82add..46d09daa6 100644 --- a/packages/api/test/services/save_newsletter_email.test.ts +++ b/packages/api/test/services/save_newsletter_email.test.ts @@ -4,11 +4,11 @@ import 'chai/register-should' import { createTestUser, deleteTestUser } from '../db' import { createNewsletterEmail } from '../../src/services/newsletters' import { saveNewsletterEmail } from '../../src/services/save_newsletter_email' -import { getPageByParam } from '../../src/elastic' import { User } from '../../src/entity/user' import { NewsletterEmail } from '../../src/entity/newsletter_email' import { SaveContext } from '../../src/services/save_email' import { createPubSubClient } from '../../src/datalayer/pubsub' +import { getPageByParam } from '../../src/elastic/pages' describe('saveNewsletterEmail', () => { const username = 'fakeUser' diff --git a/packages/api/test/util.ts b/packages/api/test/util.ts index b53342fde..1d09d798c 100644 --- a/packages/api/test/util.ts +++ b/packages/api/test/util.ts @@ -4,18 +4,22 @@ import { v4 } from 'uuid' import { corsConfig } from '../src/utils/corsConfig' import { Page } from '../src/elastic/types' import { PageType } from '../src/generated/graphql' -import { createPage, getPageById } from '../src/elastic' import { User } from '../src/entity/user' import { Label } from '../src/entity/label' import { createPubSubClient } from '../src/datalayer/pubsub' +import { createPage, getPageById } from '../src/elastic/pages' const { app, apollo } = createApp() export const request = supertest(app) -before(async () => { +export const startApolloServer = async () => { await apollo.start() apollo.applyMiddleware({ app, path: '/api/graphql', cors: corsConfig }) -}) +} + +export const stopApolloServer = async () => { + await apollo.stop() +} export const graphqlRequest = ( query: string, From 250239e11059bc80da6dccdf44c08e679b73b39d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Apr 2022 15:49:48 +0000 Subject: [PATCH 7/9] Bump swr from 1.2.2 to 1.3.0 Bumps [swr](https://github.com/vercel/swr) from 1.2.2 to 1.3.0. - [Release notes](https://github.com/vercel/swr/releases) - [Commits](https://github.com/vercel/swr/compare/1.2.2...1.3.0) --- updated-dependencies: - dependency-name: swr dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- yarn.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/yarn.lock b/yarn.lock index 72a06fd77..4597fa5c4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18520,9 +18520,9 @@ swap-case@^2.0.2: tslib "^2.0.3" swr@^1.0.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/swr/-/swr-1.2.2.tgz#6cae09928d30593a7980d80f85823e57468fac5d" - integrity sha512-ky0BskS/V47GpW8d6RU7CPsr6J8cr7mQD6+do5eky3bM0IyJaoi3vO8UhvrzJaObuTlGhPl2szodeB2dUd76Xw== + version "1.3.0" + resolved "https://registry.yarnpkg.com/swr/-/swr-1.3.0.tgz#c6531866a35b4db37b38b72c45a63171faf9f4e8" + integrity sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw== symbol-observable@^1.0.4, symbol-observable@^1.1.0: version "1.2.0" @@ -18552,16 +18552,6 @@ tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -tar-fs@*, tar-fs@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" - integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== - dependencies: - chownr "^1.1.1" - mkdirp-classic "^0.5.2" - pump "^3.0.0" - tar-stream "^2.1.4" - tar-fs@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.0.tgz#677700fc0c8b337a78bee3623fdc235f21d7afad" @@ -18572,6 +18562,16 @@ tar-fs@2.0.0: pump "^3.0.0" tar-stream "^2.0.0" +tar-fs@^2.0.0, tar-fs@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" + integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + tar-stream@^2.0.0, tar-stream@^2.1.4: version "2.2.0" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" From 73ef8fef09e77bb788f5d96f0bbc65a7813cff6b Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Tue, 12 Apr 2022 12:46:32 -0700 Subject: [PATCH 8/9] Rename linkId to pageId in SetLabelsInput --- packages/api/src/generated/graphql.ts | 2 +- packages/api/src/generated/schema.graphql | 2 +- packages/api/src/resolvers/labels/index.ts | 2 +- packages/api/src/schema.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/api/src/generated/graphql.ts b/packages/api/src/generated/graphql.ts index 872991d7f..d14428b39 100644 --- a/packages/api/src/generated/graphql.ts +++ b/packages/api/src/generated/graphql.ts @@ -1460,7 +1460,7 @@ export enum SetLabelsErrorCode { export type SetLabelsInput = { labelIds: Array; - linkId: Scalars['ID']; + pageId: Scalars['ID']; }; export type SetLabelsResult = SetLabelsError | SetLabelsSuccess; diff --git a/packages/api/src/generated/schema.graphql b/packages/api/src/generated/schema.graphql index 29d101a6c..e3c5630a8 100644 --- a/packages/api/src/generated/schema.graphql +++ b/packages/api/src/generated/schema.graphql @@ -1070,7 +1070,7 @@ enum SetLabelsErrorCode { input SetLabelsInput { labelIds: [ID!]! - linkId: ID! + pageId: ID! } union SetLabelsResult = SetLabelsError | SetLabelsSuccess diff --git a/packages/api/src/resolvers/labels/index.ts b/packages/api/src/resolvers/labels/index.ts index e2813861e..a8b8b83b2 100644 --- a/packages/api/src/resolvers/labels/index.ts +++ b/packages/api/src/resolvers/labels/index.ts @@ -203,7 +203,7 @@ export const setLabelsResolver = authorized< >(async (_, { input }, { claims: { uid }, log, pubsub }) => { log.info('setLabelsResolver') - const { linkId: pageId, labelIds } = input + const { pageId, labelIds } = input try { const user = await getRepository(User).findOneBy({ id: uid }) diff --git a/packages/api/src/schema.ts b/packages/api/src/schema.ts index cd4b5f399..43fa75719 100755 --- a/packages/api/src/schema.ts +++ b/packages/api/src/schema.ts @@ -1359,7 +1359,7 @@ const schema = gql` union SignupResult = SignupSuccess | SignupError input SetLabelsInput { - linkId: ID! + pageId: ID! labelIds: [ID!]! } From 782781639d8436344db11475c3110f9c3575c075 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Tue, 12 Apr 2022 12:53:08 -0700 Subject: [PATCH 9/9] Update API in test --- packages/api/test/resolvers/labels.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/api/test/resolvers/labels.test.ts b/packages/api/test/resolvers/labels.test.ts index e8f4594a0..83640a32b 100644 --- a/packages/api/test/resolvers/labels.test.ts +++ b/packages/api/test/resolvers/labels.test.ts @@ -247,7 +247,7 @@ describe('Labels API', () => { mutation { setLabels( input: { - linkId: "${pageId}", + pageId: "${pageId}", labelIds: [ "${labelIds[0]}", "${labelIds[1]}"