From b8367f4b6cd24825fcdaaa57c5b85945c77bf21e Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Fri, 23 Feb 2024 14:50:32 +1030 Subject: [PATCH 01/31] initial commit --- notes.md | 0 package-lock.json | 4283 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 4283 insertions(+) create mode 100644 notes.md create mode 100644 package-lock.json diff --git a/notes.md b/notes.md new file mode 100644 index 0000000..e69de29 diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..c05a13c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4283 @@ +{ + "name": "@bobaboard/ao3.js", + "version": "0.14.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "dev": true + }, + "@babel/core": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", + "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.9", + "@babel/parser": "^7.23.9", + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + } + }, + "@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "dev": true, + "requires": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.15" + } + }, + "@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true + }, + "@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", + "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", + "dev": true, + "requires": { + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9" + } + }, + "@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", + "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", + "dev": true + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", + "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", + "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", + "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + } + }, + "@babel/template": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", + "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9" + } + }, + "@babel/traverse": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", + "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", + "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "@bundled-es-modules/cookie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.0.tgz", + "integrity": "sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw==", + "dev": true, + "requires": { + "cookie": "^0.5.0" + } + }, + "@bundled-es-modules/statuses": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz", + "integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==", + "dev": true, + "requires": { + "statuses": "^2.0.1" + } + }, + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + } + } + }, + "@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "dev": true, + "optional": true + }, + "@inquirer/confirm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.0.0.tgz", + "integrity": "sha512-LHeuYP1D8NmQra1eR4UqvZMXwxEdDXyElJmmZfU44xdNLL6+GcQBS0uE16vyfZVjH8c22p9e+DStROfE/hyHrg==", + "dev": true, + "requires": { + "@inquirer/core": "^7.0.0", + "@inquirer/type": "^1.2.0" + } + }, + "@inquirer/core": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-7.0.0.tgz", + "integrity": "sha512-g13W5yEt9r1sEVVriffJqQ8GWy94OnfxLCreNSOTw0HPVcszmc/If1KIf7YBmlwtX4klmvwpZHnQpl3N7VX2xA==", + "dev": true, + "requires": { + "@inquirer/type": "^1.2.0", + "@types/mute-stream": "^0.0.4", + "@types/node": "^20.11.16", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "figures": "^3.2.0", + "mute-stream": "^1.0.0", + "run-async": "^3.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, + "@inquirer/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.2.0.tgz", + "integrity": "sha512-/vvkUkYhrjbm+RolU7V1aUFDydZVKNKqKHR5TsE+j5DXgXFwrsOPcoGUJ02K0O7q7O53CU2DOTMYCHeGZ25WHA==", + "dev": true + }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true + }, + "@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + } + }, + "@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "requires": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "requires": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + } + }, + "@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "requires": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + } + }, + "@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "requires": { + "jest-get-type": "^29.6.3" + } + }, + "@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + } + }, + "@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + } + }, + "@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "requires": { + "@sinclair/typebox": "^0.27.8" + } + }, + "@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + } + }, + "@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "requires": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "requires": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + } + }, + "@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + } + }, + "@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "requires": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", + "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@mswjs/cookies": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@mswjs/cookies/-/cookies-1.1.0.tgz", + "integrity": "sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw==", + "dev": true + }, + "@mswjs/interceptors": { + "version": "0.25.16", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.25.16.tgz", + "integrity": "sha512-8QC8JyKztvoGAdPgyZy49c9vSHHAZjHagwl4RY9E8carULk8ym3iTaiawrT1YoLF/qb449h48f71XDPgkUSOUg==", + "dev": true, + "requires": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.2.1", + "strict-event-emitter": "^0.5.1" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true + }, + "@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "requires": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true + }, + "@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^3.0.0" + } + }, + "@tsconfig/node-lts": { + "version": "18.12.5", + "resolved": "https://registry.npmjs.org/@tsconfig/node-lts/-/node-lts-18.12.5.tgz", + "integrity": "sha512-KJZX0kQ5FBv77WDVzmQ9y1dUjaJCNXAAz3LSsg5cMwH0AUijVdDQtII+IVprEXdb13U9GjVOBxBzyRvr/ozPxw==", + "dev": true + }, + "@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "dev": true, + "requires": { + "@babel/types": "^7.20.7" + } + }, + "@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "dev": true + }, + "@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "dev": true, + "requires": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "@types/mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "20.11.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.20.tgz", + "integrity": "sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==", + "dev": true, + "requires": { + "undici-types": "~5.26.4" + } + }, + "@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, + "@types/statuses": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.4.tgz", + "integrity": "sha512-eqNDvZsCNY49OAXB0Firg/Sc2BgoWsntsLUdybGFOhAfCD6QJ2n9HXUIHGqt5qjrxmMv4wS8WLAw43ZkKcJ8Pw==", + "dev": true + }, + "@types/wrap-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", + "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==", + "dev": true + }, + "@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true + }, + "acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "requires": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "dependencies": { + "istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + } + } + } + }, + "babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + } + }, + "babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + } + }, + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "2.x" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "bundle-require": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-4.0.2.tgz", + "integrity": "sha512-jwzPOChofl67PSTW2SGubV9HBQAhhR2i6nskiOThauo9dzwDUgOWQScFVaJkjEfYX+UXiD+LEx8EblQMc2wIag==", + "dev": true, + "requires": { + "load-tsconfig": "^0.2.3" + } + }, + "cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001589", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001589.tgz", + "integrity": "sha512-vNQWS6kI+q6sBlHbh71IIeC+sRwK2N3EDySc/updIGhIee2x5z00J4c1242/5/d6EpEMdOnk/m+6tuk4/tcsqg==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true + }, + "cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "requires": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + } + }, + "cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "requires": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + } + }, + "chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true + }, + "cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true + }, + "cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true + }, + "collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "command-line-args": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", + "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", + "dev": true, + "requires": { + "array-back": "^3.1.0", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + } + }, + "command-line-usage": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz", + "integrity": "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==", + "dev": true, + "requires": { + "array-back": "^4.0.2", + "chalk": "^2.4.2", + "table-layout": "^1.0.2", + "typical": "^5.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true + } + } + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "dev": true + }, + "create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + } + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "directory-tree": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/directory-tree/-/directory-tree-3.5.1.tgz", + "integrity": "sha512-HqjZ49fDzUnKYUhHxVw9eKBqbQ+lL0v4kSBInlDlaktmLtGoV9tC54a6A0ZfYeIrkMHWTE6MwwmUXP477+UEKQ==", + "dev": true, + "requires": { + "command-line-args": "^5.2.0", + "command-line-usage": "^6.1.1" + } + }, + "dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "requires": { + "domelementtype": "^2.3.0" + } + }, + "domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "requires": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + } + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.4.680", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.680.tgz", + "integrity": "sha512-4nToZ5jlPO14W82NkF32wyjhYqQByVaDmLy4J2/tYcAbJfgO2TKJC780Az1V13gzq4l73CJ0yuyalpXvxXXD9A==", + "dev": true + }, + "emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, + "escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true + }, + "expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "requires": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "requires": { + "bser": "2.1.1" + } + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "filename-reserved-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-3.0.0.tgz", + "integrity": "sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw==", + "dev": true + }, + "filenamify": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-6.0.0.tgz", + "integrity": "sha512-vqIlNogKeyD3yzrm0yhRMQg8hOVwYcYRfjEoODd49iCprMn4HL85gK3HcykQE53EPIpX3HcAbGA5ELQv216dAQ==", + "dev": true, + "requires": { + "filename-reserved-regex": "^3.0.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "dev": true, + "requires": { + "array-back": "^3.0.1" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "graphql": { + "version": "16.8.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz", + "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "hasown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + } + }, + "headers-polyfill": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.2.tgz", + "integrity": "sha512-EWGTfnTqAO2L/j5HZgoM/3z82L7necsJ0pO9Tp0X1wil3PDLrkypTBRgVO2ExehEEvUycejZD3FuRaXpZZc3kw==", + "dev": true + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true + }, + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "requires": { + "hasown": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", + "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", + "dev": true, + "requires": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + } + }, + "istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, + "jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "requires": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "dependencies": { + "jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "requires": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + } + } + } + }, + "jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "requires": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "dependencies": { + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + } + } + }, + "jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "dependencies": { + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + } + } + }, + "jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + } + }, + "jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "requires": { + "detect-newline": "^3.0.0" + } + }, + "jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + } + }, + "jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "jest-esm-transformer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jest-esm-transformer/-/jest-esm-transformer-1.0.0.tgz", + "integrity": "sha512-FoPgeMMwy1/CEsc8tBI41i83CEO3x85RJuZi5iAMmWoARXhfgk6Jd7y+4d+z+HCkTKNVDvSWKGRhwjzU9PUbrw==", + "dev": true, + "requires": { + "@babel/core": "^7.4.4", + "@babel/plugin-transform-modules-commonjs": "^7.4.4" + } + }, + "jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true + }, + "jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + } + }, + "jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "requires": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true + }, + "jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true + }, + "jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + } + }, + "jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "requires": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + } + }, + "jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "requires": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "dependencies": { + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + } + } + }, + "jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + } + }, + "jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + } + } + }, + "jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "requires": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + } + }, + "jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "requires": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "lilconfig": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", + "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", + "dev": true + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "load-tsconfig": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", + "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "requires": { + "semver": "^7.5.3" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "requires": { + "tmpl": "1.0.5" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "msw": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.2.1.tgz", + "integrity": "sha512-DCsZAQwan+2onEcpD86fiEnCKW4IvYzqcwDq/2TIoeNrmBqNp/mJW4wHQyxcoYrRPwgujin7wDFflqiSO1iT/w==", + "dev": true, + "requires": { + "@bundled-es-modules/cookie": "^2.0.0", + "@bundled-es-modules/statuses": "^1.0.1", + "@inquirer/confirm": "^3.0.0", + "@mswjs/cookies": "^1.1.0", + "@mswjs/interceptors": "^0.25.16", + "@open-draft/until": "^2.1.0", + "@types/cookie": "^0.6.0", + "@types/statuses": "^2.0.4", + "chalk": "^4.1.2", + "graphql": "^16.8.1", + "headers-polyfill": "^4.0.2", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.2", + "path-to-regexp": "^6.2.0", + "strict-event-emitter": "^0.5.1", + "type-fest": "^4.9.0", + "yargs": "^17.7.2" + }, + "dependencies": { + "type-fest": { + "version": "4.10.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.10.3.tgz", + "integrity": "sha512-JLXyjizi072smKGGcZiAJDCNweT8J+AuRxmPZ1aG7TERg4ijx9REl8CNhbr36RV4qXqL1gO1FF9HL8OkVmmrsA==", + "dev": true + } + } + }, + "mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true + }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "requires": { + "boolbase": "^1.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "outvariant": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.2.tgz", + "integrity": "sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "requires": { + "entities": "^4.4.0" + } + }, + "parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "requires": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "requires": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true + } + } + }, + "path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "requires": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + } + }, + "pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true + }, + "pure-rand": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "reduce-flatten": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", + "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rollup": { + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "dev": true + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + } + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true + }, + "strict-event-emitter": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==", + "dev": true + }, + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "table-layout": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", + "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", + "dev": true, + "requires": { + "array-back": "^4.0.1", + "deep-extend": "~0.6.0", + "typical": "^5.2.0", + "wordwrapjs": "^4.0.0" + }, + "dependencies": { + "array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true + }, + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true + } + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true + }, + "ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, + "ts-jest": { + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", + "integrity": "sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==", + "dev": true, + "requires": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + } + }, + "tsup": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-7.2.0.tgz", + "integrity": "sha512-vDHlczXbgUvY3rWvqFEbSqmC1L7woozbzngMqTtL2PGBODTtWlRwGDDawhvWzr5c1QjKe4OAKqJGfE1xeXUvtQ==", + "dev": true, + "requires": { + "bundle-require": "^4.0.0", + "cac": "^6.7.12", + "chokidar": "^3.5.1", + "debug": "^4.3.1", + "esbuild": "^0.18.2", + "execa": "^5.0.0", + "globby": "^11.0.3", + "joycon": "^3.0.1", + "postcss-load-config": "^4.0.1", + "resolve-from": "^5.0.0", + "rollup": "^3.2.5", + "source-map": "0.8.0-beta.0", + "sucrase": "^3.20.3", + "tree-kill": "^1.2.2" + }, + "dependencies": { + "source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "requires": { + "whatwg-url": "^7.0.0" + } + } + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + }, + "typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true + }, + "typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "dev": true + }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "v8-to-istanbul": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + } + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "requires": { + "makeerror": "1.0.12" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wordwrapjs": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", + "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", + "dev": true, + "requires": { + "reduce-flatten": "^2.0.0", + "typical": "^5.2.0" + }, + "dependencies": { + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true + } + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "yaml": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "dev": true + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} From 003a9926543623da6158e6358fc8b6cfbee11830 Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Fri, 23 Feb 2024 14:51:44 +1030 Subject: [PATCH 02/31] added Prompt interface type --- types/entities.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/types/entities.ts b/types/entities.ts index 4948501..103448a 100644 --- a/types/entities.ts +++ b/types/entities.ts @@ -159,6 +159,8 @@ export interface WorkSummary { locked: false; } + + export interface LockedWorkSummary { locked: true; } @@ -171,3 +173,27 @@ export interface Chapter { publishedAt: string; url: string; } + + +export interface Prompt { + id: string; + title: string; + fandoms: string[]; + //pseuds don't seem to have a noticable effect on the interface + prompter: "Anonymous" | string; + rating: WorkRatings; + tags: { + warnings: WorkWarnings[]; + characters: string[]; + relationships: string[]; + additional: string[]; + }; + fulfilled: boolean; + //there's a HTML option? + summary: string; + //Which of these applies to prompts? + //TODO currently doing test at https://archiveofourown.org/collections/test_prompt_meme_2024/requests + publishedAt: string; + updatedAt: string | null; + +} \ No newline at end of file From e2139f8edf9441e62b448ca7abb2ffe38579039e Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Fri, 23 Feb 2024 14:59:08 +1030 Subject: [PATCH 03/31] fixed link-breaking typo in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bd4e056..855116f 100644 --- a/README.md +++ b/README.md @@ -201,7 +201,7 @@ To identify what we're missing (and tour the codebase as a bonus): 1. Take a look at our [TypeScript types](./types/entities.ts). If the data you seek is not there, we most likely can't scrape it (yet). 2. See if there's already [an open issue](https://github.com/essential-randomness/ao3.js/issues/) for the type of data you seek. -3. See if we're aready [scraping the page](./src/pages-loaders.ts) the data resides in. +3. See if we're aready [scraping the page](./src/page-loaders.ts) the data resides in. Congratulations, you now have your first contribution carved for you! From f6df2955fab52581ad083c32152dead7bc2318fe Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Fri, 23 Feb 2024 15:02:13 +1030 Subject: [PATCH 04/31] added reminder to notes --- notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/notes.md b/notes.md index e69de29..1cbd8d6 100644 --- a/notes.md +++ b/notes.md @@ -0,0 +1 @@ +TODO: delete this file (eventually) \ No newline at end of file From ee7f8be7dc5730bceb5e1b39e95f0886cc2a0c92 Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Fri, 23 Feb 2024 15:10:34 +1030 Subject: [PATCH 05/31] added cross-env to include NODE=ENV compatibility on my windows machine --- package-lock.json | 20 +++++++++++--------- package.json | 5 +++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index c05a13c..64d5e63 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1868,11 +1868,18 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, + "cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "requires": { + "cross-spawn": "^7.0.1" + } + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2474,8 +2481,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "istanbul-lib-coverage": { "version": "3.2.2", @@ -3454,8 +3460,7 @@ "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, "path-parse": { "version": "1.0.7", @@ -3676,7 +3681,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "requires": { "shebang-regex": "^3.0.0" } @@ -3684,8 +3688,7 @@ "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "signal-exit": { "version": "3.0.7", @@ -4167,7 +4170,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "requires": { "isexe": "^2.0.0" } diff --git a/package.json b/package.json index 5b7ae53..17437a9 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ ], "scripts": { "build": "rm -rf dist/ && tsup src/index.ts src/urls.ts --format esm,cjs --dts", - "test": "NODE_OPTIONS=--experimental-vm-modules jest --no-cache .test.ts$ --verbose=true", + "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --no-cache .test.ts$ --verbose=true", "encode-mock-files": "ts-node-esm tests/mocks/scripts/encode-mock-files.mts" }, "repository": "https://github.com/essential-randomness/AO3.js.git", @@ -54,6 +54,7 @@ "typescript": "^5.1.6" }, "dependencies": { - "cheerio": "^1.0.0-rc.10" + "cheerio": "^1.0.0-rc.10", + "cross-env": "^7.0.3" } } From 0936f4ce1d6865ba97ffdd2d735c453ff618c0e6 Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Fri, 23 Feb 2024 15:28:01 +1030 Subject: [PATCH 06/31] duplicated works into new prompts folder --- src/prompts/index.ts | 120 ++++++++++++++++++++ src/prompts/work-getters.ts | 211 ++++++++++++++++++++++++++++++++++++ 2 files changed, 331 insertions(+) create mode 100644 src/prompts/index.ts create mode 100644 src/prompts/work-getters.ts diff --git a/src/prompts/index.ts b/src/prompts/index.ts new file mode 100644 index 0000000..da683cf --- /dev/null +++ b/src/prompts/index.ts @@ -0,0 +1,120 @@ +import { + Author, + Chapter, + LockedWorkSummary, + WorkSummary, +} from "types/entities"; +import { + getChapterIndex, + getChapterName, + getChapterSummary, + getWorkAdditionalTags, + getWorkAuthors, + getWorkBookmarkCount, + getWorkCategory, + getWorkCharacters, + getWorkCommentCount, + getWorkFandoms, + getWorkHits, + getWorkKudosCount, + getWorkLanguage, + getWorkLocked, + getWorkPublishDate, + getWorkPublishedChapters, + getWorkRating, + getWorkRelationships, + getWorkSeries, + getWorkSummary, + getWorkTitle, + getWorkTotalChapters, + getWorkUpdateDate, + getWorkWarnings, + getWorkWordCount, +} from "./work-getters"; +import { loadChaptersIndexPage, loadWorkPage } from "../page-loaders"; + +export const getWork = async ({ + workId, + chapterId, +}: { + workId: string; + chapterId?: string; +}): Promise => { + const workPage = await loadWorkPage({ workId, chapterId }); + + if (getWorkLocked(workPage)) { + return { + locked: true, + }; + } + + const totalChapters = getWorkTotalChapters(workPage); + const publishedChapters = getWorkPublishedChapters(workPage); + const chapterIndex = getChapterIndex(workPage); + + return { + id: workId, + authors: getWorkAuthors(workPage), + title: getWorkTitle(workPage), + words: getWorkWordCount(workPage), + language: getWorkLanguage(workPage), + rating: getWorkRating(workPage), + category: getWorkCategory(workPage), + // TODO: figure out how to get this + adult: false, + fandoms: getWorkFandoms(workPage), + tags: { + warnings: getWorkWarnings(workPage), + characters: getWorkCharacters(workPage), + relationships: getWorkRelationships(workPage), + additional: getWorkAdditionalTags(workPage), + }, + publishedAt: getWorkPublishDate(workPage), + updatedAt: getWorkUpdateDate(workPage), + chapters: { + published: publishedChapters, + total: totalChapters, + }, + chapterInfo: chapterId + ? { + id: chapterId, + index: chapterIndex, + name: getChapterName(workPage), + summary: getChapterSummary(workPage), + } + : null, + complete: totalChapters !== null && totalChapters === publishedChapters, + series: getWorkSeries(workPage), + summary: + chapterIndex === 1 || totalChapters === 1 + ? getWorkSummary(workPage) + : null, + stats: { + bookmarks: getWorkBookmarkCount(workPage), + comments: getWorkCommentCount(workPage), + hits: getWorkHits(workPage), + kudos: getWorkKudosCount(workPage), + }, + locked: false, + }; +}; + +export const getWorkWithChapters = async ({ + workId, +}: { + workId: string; +}): Promise<{ + title: string; + authors: "Anonymous" | Author[]; + workId: string; + chapters: Chapter[]; +}> => { + const page = await loadChaptersIndexPage({ workId }); + + return { + title: getWorkTitleFromChaptersIndex(page), + authors: getWorkAuthorsFromChaptersIndex(page), + workId, + chapters: getChaptersList(page), + }; +}; diff --git a/src/prompts/work-getters.ts b/src/prompts/work-getters.ts new file mode 100644 index 0000000..dcc5162 --- /dev/null +++ b/src/prompts/work-getters.ts @@ -0,0 +1,211 @@ +import { + Author, + BasicSeries, + WorkCategory, + WorkRatings, + WorkSummary, + WorkWarnings, +} from "types/entities"; + +import { WorkPage } from "../page-loaders"; + +export const getWorkAuthors = ($workPage: WorkPage): "Anonymous" | Author[] => { + const authorLinks = $workPage("h3.byline a[rel='author']"); + const authors: Author[] = []; + + if ($workPage("h3.byline").text().trim() === "Anonymous") { + return "Anonymous"; + } + + if (authorLinks.length !== 0) { + authorLinks.each((i, element) => { + const url = element.attribs.href; + const [, username, pseud] = url.match(/users\/(.+)\/pseuds\/(.+)/)!; + + authors.push({ username: username, pseud: decodeURI(pseud) }); + }); + } + + return authors; +}; + +export const getWorkTitle = ($workPage: WorkPage): string => { + return $workPage("h2.title").text().trim(); +}; + +export const getWorkWordCount = ($workPage: WorkPage): number => { + return parseInt($workPage("dd.words").text().replaceAll(",", "").trim()); +}; + +export const getWorkLanguage = ($workPage: WorkPage): string => { + return $workPage("dd.language").text().trim(); +}; + +export const getWorkRating = ($workPage: WorkPage): WorkRatings => { + const rating = $workPage("dd.rating a.tag").text().trim(); + if (!Object.values(WorkRatings).includes(rating as WorkRatings)) { + throw new Error("An unknown rating was found on the page"); + } + return rating as WorkRatings; +}; + +export const getWorkCategory = ($workPage: WorkPage): WorkCategory[] | null => { + if ($workPage("dd.category a.tag").length === 0) { + return null; + } else { + const categories: WorkCategory[] = []; + + $workPage("dd.category a.tag").each(function (i, element) { + const category = $workPage(element).text().trim(); + if (!Object.values(WorkCategory).includes(category as WorkCategory)) { + throw new Error("An unknown category was found on the page"); + } + + categories[i] = category as WorkCategory; + }); + return categories; + } +}; + +export const getWorkFandoms = ($workPage: WorkPage): string[] => { + const fandoms: string[] = []; + + $workPage("dd.fandom a.tag").each(function (i, element) { + fandoms[i] = $workPage(element).text().trim(); + }); + return fandoms; +}; + +export const getWorkWarnings = ($workPage: WorkPage): WorkWarnings[] => { + const warnings: WorkWarnings[] = []; + + $workPage("dd.warning a.tag").each(function (i, element) { + const warning = $workPage(element).text().trim(); + + if (!Object.values(WorkWarnings).includes(warning as WorkWarnings)) { + throw new Error("An unknown warning was found on the page"); + } + + warnings[i] = warning as WorkWarnings; + }); + return warnings; +}; + +export const getWorkCharacters = ($workPage: WorkPage): string[] => { + const characters: string[] = []; + + $workPage("dd.character a.tag").each(function (i, character) { + characters[i] = $workPage(character).text().trim(); + }); + return characters; +}; + +export const getWorkRelationships = ($workPage: WorkPage): string[] => { + const ships: string[] = []; + + $workPage("dd.relationship a.tag").each(function (i, ship) { + ships[i] = $workPage(ship).text().trim(); + }); + return ships; +}; + +export const getWorkAdditionalTags = ($workPage: WorkPage): string[] => { + const freeform: string[] = []; + $workPage("dd.freeform ul.commas li").each(function (i) { + freeform[i] = $workPage(this).text().trim(); + }); + return freeform; +}; + +export const getWorkUpdateDate = ($workPage: WorkPage): string | null => { + const updated = $workPage("dd.status").text().trim(); + + return updated ? updated : null; +}; + +export const getWorkPublishDate = ($workPage: WorkPage): string => { + return $workPage("dd.published").text().trim(); +}; + +export const getWorkPublishedChapters = ($workPage: WorkPage): number => { + return parseInt($workPage("dd.chapters").text().trim().split("/")[0]); +}; + +export const getWorkTotalChapters = ($workPage: WorkPage): number | null => { + const totalChapters = $workPage("dd.chapters").text().trim().split("/")[1]; + + return totalChapters === "?" ? null : parseInt(totalChapters); +}; + +export const getWorkSummary = ($workPage: WorkPage): string | null => { + const summary = $workPage(".preface .summary blockquote.userstuff").html(); + return summary ? summary.trim() : null; +}; + +export const getWorkSeries = ($workPage: WorkPage): BasicSeries[] => { + const series: BasicSeries[] = []; + + const selector = "dd.series span.series"; + $workPage(selector).each((index) => { + const seriesHtml = $workPage(`${selector}:nth-of-type(${index + 1})`); + const matches = seriesHtml.text().trim().match(/\d+/); + const link = seriesHtml.find("a:not(.next, .previous)"); + + series[index] = { + id: link.attr("href")!.replace("/series/", ""), + name: link.text().trim(), + index: matches!.length > 0 ? parseInt(matches![0]) : -1, + }; + }); + + return series; +}; + +export const getWorkCommentCount = ($workPage: WorkPage): number => { + const comments = $workPage("dd.comments").text().trim(); + + return comments ? parseInt(comments) : 0; +}; + +export const getWorkKudosCount = ($workPage: WorkPage) => { + const kudos = $workPage("dd.kudos").text().trim(); + + return kudos ? parseInt(kudos) : 0; +}; + +export const getWorkBookmarkCount = ($workPage: WorkPage) => { + const bookmarks = $workPage("dd.bookmarks a").text().trim(); + + return bookmarks ? parseInt(bookmarks) : 0; +}; + +export const getWorkHits = ($workPage: WorkPage) => { + return parseInt($workPage("dd.hits").text().trim()); +}; + +export const getWorkLocked = ($workPage: WorkPage) => { + return !!$workPage("#signin > .heading").text(); +}; + +// Chapter-specific (must be multi-chapter fic) +export const getChapterIndex = ( + $workPage: WorkPage +): NonNullable["index"] => { + const index = $workPage("#chapters h3.title a").text(); + return index ? parseInt(index.trim().replace("Chapter ", "")) : -1; +}; + +export const getChapterName = ( + $workPage: WorkPage +): NonNullable["name"] => { + const title = $workPage("#chapters h3.title").text().trim(); + // 2 characters is the length of query string + return title && title.includes(":") + ? title.slice(title.indexOf(": ") + 2) + : null; +}; + +export const getChapterSummary = ($workPage: WorkPage): string | null => { + const summary = $workPage(".chapter .summary blockquote.userstuff").html(); + return summary ? summary.trim() : null; +}; From 23e81cd4833ace6dac05578d9d03bbf0ab62246d Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Fri, 23 Feb 2024 17:40:40 +1030 Subject: [PATCH 07/31] created prompt test file. implemented get Prompt Id from url --- src/prompts/index.ts | 120 ------------------- src/prompts/prompt-getters.ts | 0 src/prompts/work-getters.ts | 211 ---------------------------------- src/urls.ts | 38 ++++++ tests/prompts.test.ts | 16 +++ 5 files changed, 54 insertions(+), 331 deletions(-) create mode 100644 src/prompts/prompt-getters.ts delete mode 100644 src/prompts/work-getters.ts create mode 100644 tests/prompts.test.ts diff --git a/src/prompts/index.ts b/src/prompts/index.ts index da683cf..e69de29 100644 --- a/src/prompts/index.ts +++ b/src/prompts/index.ts @@ -1,120 +0,0 @@ -import { - Author, - Chapter, - LockedWorkSummary, - WorkSummary, -} from "types/entities"; -import { - getChapterIndex, - getChapterName, - getChapterSummary, - getWorkAdditionalTags, - getWorkAuthors, - getWorkBookmarkCount, - getWorkCategory, - getWorkCharacters, - getWorkCommentCount, - getWorkFandoms, - getWorkHits, - getWorkKudosCount, - getWorkLanguage, - getWorkLocked, - getWorkPublishDate, - getWorkPublishedChapters, - getWorkRating, - getWorkRelationships, - getWorkSeries, - getWorkSummary, - getWorkTitle, - getWorkTotalChapters, - getWorkUpdateDate, - getWorkWarnings, - getWorkWordCount, -} from "./work-getters"; -import { loadChaptersIndexPage, loadWorkPage } from "../page-loaders"; - -export const getWork = async ({ - workId, - chapterId, -}: { - workId: string; - chapterId?: string; -}): Promise => { - const workPage = await loadWorkPage({ workId, chapterId }); - - if (getWorkLocked(workPage)) { - return { - locked: true, - }; - } - - const totalChapters = getWorkTotalChapters(workPage); - const publishedChapters = getWorkPublishedChapters(workPage); - const chapterIndex = getChapterIndex(workPage); - - return { - id: workId, - authors: getWorkAuthors(workPage), - title: getWorkTitle(workPage), - words: getWorkWordCount(workPage), - language: getWorkLanguage(workPage), - rating: getWorkRating(workPage), - category: getWorkCategory(workPage), - // TODO: figure out how to get this - adult: false, - fandoms: getWorkFandoms(workPage), - tags: { - warnings: getWorkWarnings(workPage), - characters: getWorkCharacters(workPage), - relationships: getWorkRelationships(workPage), - additional: getWorkAdditionalTags(workPage), - }, - publishedAt: getWorkPublishDate(workPage), - updatedAt: getWorkUpdateDate(workPage), - chapters: { - published: publishedChapters, - total: totalChapters, - }, - chapterInfo: chapterId - ? { - id: chapterId, - index: chapterIndex, - name: getChapterName(workPage), - summary: getChapterSummary(workPage), - } - : null, - complete: totalChapters !== null && totalChapters === publishedChapters, - series: getWorkSeries(workPage), - summary: - chapterIndex === 1 || totalChapters === 1 - ? getWorkSummary(workPage) - : null, - stats: { - bookmarks: getWorkBookmarkCount(workPage), - comments: getWorkCommentCount(workPage), - hits: getWorkHits(workPage), - kudos: getWorkKudosCount(workPage), - }, - locked: false, - }; -}; - -export const getWorkWithChapters = async ({ - workId, -}: { - workId: string; -}): Promise<{ - title: string; - authors: "Anonymous" | Author[]; - workId: string; - chapters: Chapter[]; -}> => { - const page = await loadChaptersIndexPage({ workId }); - - return { - title: getWorkTitleFromChaptersIndex(page), - authors: getWorkAuthorsFromChaptersIndex(page), - workId, - chapters: getChaptersList(page), - }; -}; diff --git a/src/prompts/prompt-getters.ts b/src/prompts/prompt-getters.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/prompts/work-getters.ts b/src/prompts/work-getters.ts deleted file mode 100644 index dcc5162..0000000 --- a/src/prompts/work-getters.ts +++ /dev/null @@ -1,211 +0,0 @@ -import { - Author, - BasicSeries, - WorkCategory, - WorkRatings, - WorkSummary, - WorkWarnings, -} from "types/entities"; - -import { WorkPage } from "../page-loaders"; - -export const getWorkAuthors = ($workPage: WorkPage): "Anonymous" | Author[] => { - const authorLinks = $workPage("h3.byline a[rel='author']"); - const authors: Author[] = []; - - if ($workPage("h3.byline").text().trim() === "Anonymous") { - return "Anonymous"; - } - - if (authorLinks.length !== 0) { - authorLinks.each((i, element) => { - const url = element.attribs.href; - const [, username, pseud] = url.match(/users\/(.+)\/pseuds\/(.+)/)!; - - authors.push({ username: username, pseud: decodeURI(pseud) }); - }); - } - - return authors; -}; - -export const getWorkTitle = ($workPage: WorkPage): string => { - return $workPage("h2.title").text().trim(); -}; - -export const getWorkWordCount = ($workPage: WorkPage): number => { - return parseInt($workPage("dd.words").text().replaceAll(",", "").trim()); -}; - -export const getWorkLanguage = ($workPage: WorkPage): string => { - return $workPage("dd.language").text().trim(); -}; - -export const getWorkRating = ($workPage: WorkPage): WorkRatings => { - const rating = $workPage("dd.rating a.tag").text().trim(); - if (!Object.values(WorkRatings).includes(rating as WorkRatings)) { - throw new Error("An unknown rating was found on the page"); - } - return rating as WorkRatings; -}; - -export const getWorkCategory = ($workPage: WorkPage): WorkCategory[] | null => { - if ($workPage("dd.category a.tag").length === 0) { - return null; - } else { - const categories: WorkCategory[] = []; - - $workPage("dd.category a.tag").each(function (i, element) { - const category = $workPage(element).text().trim(); - if (!Object.values(WorkCategory).includes(category as WorkCategory)) { - throw new Error("An unknown category was found on the page"); - } - - categories[i] = category as WorkCategory; - }); - return categories; - } -}; - -export const getWorkFandoms = ($workPage: WorkPage): string[] => { - const fandoms: string[] = []; - - $workPage("dd.fandom a.tag").each(function (i, element) { - fandoms[i] = $workPage(element).text().trim(); - }); - return fandoms; -}; - -export const getWorkWarnings = ($workPage: WorkPage): WorkWarnings[] => { - const warnings: WorkWarnings[] = []; - - $workPage("dd.warning a.tag").each(function (i, element) { - const warning = $workPage(element).text().trim(); - - if (!Object.values(WorkWarnings).includes(warning as WorkWarnings)) { - throw new Error("An unknown warning was found on the page"); - } - - warnings[i] = warning as WorkWarnings; - }); - return warnings; -}; - -export const getWorkCharacters = ($workPage: WorkPage): string[] => { - const characters: string[] = []; - - $workPage("dd.character a.tag").each(function (i, character) { - characters[i] = $workPage(character).text().trim(); - }); - return characters; -}; - -export const getWorkRelationships = ($workPage: WorkPage): string[] => { - const ships: string[] = []; - - $workPage("dd.relationship a.tag").each(function (i, ship) { - ships[i] = $workPage(ship).text().trim(); - }); - return ships; -}; - -export const getWorkAdditionalTags = ($workPage: WorkPage): string[] => { - const freeform: string[] = []; - $workPage("dd.freeform ul.commas li").each(function (i) { - freeform[i] = $workPage(this).text().trim(); - }); - return freeform; -}; - -export const getWorkUpdateDate = ($workPage: WorkPage): string | null => { - const updated = $workPage("dd.status").text().trim(); - - return updated ? updated : null; -}; - -export const getWorkPublishDate = ($workPage: WorkPage): string => { - return $workPage("dd.published").text().trim(); -}; - -export const getWorkPublishedChapters = ($workPage: WorkPage): number => { - return parseInt($workPage("dd.chapters").text().trim().split("/")[0]); -}; - -export const getWorkTotalChapters = ($workPage: WorkPage): number | null => { - const totalChapters = $workPage("dd.chapters").text().trim().split("/")[1]; - - return totalChapters === "?" ? null : parseInt(totalChapters); -}; - -export const getWorkSummary = ($workPage: WorkPage): string | null => { - const summary = $workPage(".preface .summary blockquote.userstuff").html(); - return summary ? summary.trim() : null; -}; - -export const getWorkSeries = ($workPage: WorkPage): BasicSeries[] => { - const series: BasicSeries[] = []; - - const selector = "dd.series span.series"; - $workPage(selector).each((index) => { - const seriesHtml = $workPage(`${selector}:nth-of-type(${index + 1})`); - const matches = seriesHtml.text().trim().match(/\d+/); - const link = seriesHtml.find("a:not(.next, .previous)"); - - series[index] = { - id: link.attr("href")!.replace("/series/", ""), - name: link.text().trim(), - index: matches!.length > 0 ? parseInt(matches![0]) : -1, - }; - }); - - return series; -}; - -export const getWorkCommentCount = ($workPage: WorkPage): number => { - const comments = $workPage("dd.comments").text().trim(); - - return comments ? parseInt(comments) : 0; -}; - -export const getWorkKudosCount = ($workPage: WorkPage) => { - const kudos = $workPage("dd.kudos").text().trim(); - - return kudos ? parseInt(kudos) : 0; -}; - -export const getWorkBookmarkCount = ($workPage: WorkPage) => { - const bookmarks = $workPage("dd.bookmarks a").text().trim(); - - return bookmarks ? parseInt(bookmarks) : 0; -}; - -export const getWorkHits = ($workPage: WorkPage) => { - return parseInt($workPage("dd.hits").text().trim()); -}; - -export const getWorkLocked = ($workPage: WorkPage) => { - return !!$workPage("#signin > .heading").text(); -}; - -// Chapter-specific (must be multi-chapter fic) -export const getChapterIndex = ( - $workPage: WorkPage -): NonNullable["index"] => { - const index = $workPage("#chapters h3.title a").text(); - return index ? parseInt(index.trim().replace("Chapter ", "")) : -1; -}; - -export const getChapterName = ( - $workPage: WorkPage -): NonNullable["name"] => { - const title = $workPage("#chapters h3.title").text().trim(); - // 2 characters is the length of query string - return title && title.includes(":") - ? title.slice(title.indexOf(": ") + 2) - : null; -}; - -export const getChapterSummary = ($workPage: WorkPage): string | null => { - const summary = $workPage(".chapter .summary blockquote.userstuff").html(); - return summary ? summary.trim() : null; -}; diff --git a/src/urls.ts b/src/urls.ts index 8a9b140..93c8294 100644 --- a/src/urls.ts +++ b/src/urls.ts @@ -57,3 +57,41 @@ export const getWorkDetailsFromUrl = ({ collectionName: url.match(/collections\/(\w+)/)?.[1], }; }; + +//defining the form of the arguments and the output +export const TODODelete = ({url,}: {url: string;}): { + workId: string; + chapterId?: string; + collectionName?: string; +} => { + const workUrlMatch = url.match(/works\/(\d+)/); + if (!workUrlMatch) { + throw new Error("Invalid work URL"); + } + + return { + workId: workUrlMatch[1], + chapterId: url.match(/chapters\/(\d+)/)?.[1], + collectionName: url.match(/collections\/(\w+)/)?.[1], + }; +}; + + +export const getPromptDetailsFromUrl = ({ + // defining the input structure, eg. + // url: "https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428" + url, +}: { + url: string; +}): { + //defining the form of the return value/output + promptId: string; +} => {//TODO will fail? + const promptUrlMatch = url.match(/prompts\/(\d+)/); + if (!promptUrlMatch) { + throw new Error("Invalid prompt URL"); + } + return { + promptId: promptUrlMatch[1], + }; +}; diff --git a/tests/prompts.test.ts b/tests/prompts.test.ts new file mode 100644 index 0000000..700bf5f --- /dev/null +++ b/tests/prompts.test.ts @@ -0,0 +1,16 @@ +import { getPromptDetailsFromUrl } from "src/urls"; + +describe("Fetches data from url", () => { + test("Fetches prompt id from url", async () => { + const promptData = await getPromptDetailsFromUrl({ + // getWorkDetailsFromUrl > getPromptDetailsFrom Url + url: "https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428", + }); + //wordId > promptId + expect(promptData).toMatchObject({ + promptId: "2644428", + }); + }); +}); + +// Ensure that it says the right things first: \ No newline at end of file From e387772d4c7d58f6d4cb4cda2c8ad9cde9f9f828 Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Fri, 23 Feb 2024 17:58:35 +1030 Subject: [PATCH 08/31] get Prompt Details gets collection name (not display title) from url --- src/urls.ts | 9 +++++++++ tests/prompts.test.ts | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/urls.ts b/src/urls.ts index 93c8294..6a7e623 100644 --- a/src/urls.ts +++ b/src/urls.ts @@ -85,13 +85,22 @@ export const getPromptDetailsFromUrl = ({ url: string; }): { //defining the form of the return value/output + //collection name is the url name, not the Display Title promptId: string; + collectionName: string } => {//TODO will fail? const promptUrlMatch = url.match(/prompts\/(\d+)/); if (!promptUrlMatch) { throw new Error("Invalid prompt URL"); } + + const collectionMatch = url.match(/collections\/(\w+)/); + if (!collectionMatch) { + throw new Error("Invalid prompt URL"); + } + return { promptId: promptUrlMatch[1], + collectionName: collectionMatch[1] }; }; diff --git a/tests/prompts.test.ts b/tests/prompts.test.ts index 700bf5f..7b9abe8 100644 --- a/tests/prompts.test.ts +++ b/tests/prompts.test.ts @@ -11,6 +11,18 @@ describe("Fetches data from url", () => { promptId: "2644428", }); }); + + test("Fetches collection name from url", async () => { + const workData = await getPromptDetailsFromUrl({ + url: "https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428", + }); + + expect(workData).toMatchObject({ + promptId: "2644428", + collectionName: "mo_dao_zu_shi_kink_meme_2020", + }); + }); + }); // Ensure that it says the right things first: \ No newline at end of file From 0d62c256e5dae359d47964b0d4346122cc849a7c Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Fri, 23 Feb 2024 18:21:34 +1030 Subject: [PATCH 09/31] Prompt gets url from collection name, prompt id --- src/urls.ts | 15 ++++++++++++++- tests/prompts.test.ts | 21 ++++++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/urls.ts b/src/urls.ts index 6a7e623..d971dba 100644 --- a/src/urls.ts +++ b/src/urls.ts @@ -98,9 +98,22 @@ export const getPromptDetailsFromUrl = ({ if (!collectionMatch) { throw new Error("Invalid prompt URL"); } - + return { promptId: promptUrlMatch[1], collectionName: collectionMatch[1] }; }; + +export const getPromptUrl = ({ + promptId, + collectionName +}:{ + promptId: string, + collectionName:string +})=>{ + let workUrl = `https://archiveofourown.org`; + workUrl += `/collections/${collectionName}`; + workUrl += `/prompts/${promptId}`; + return workUrl; +} \ No newline at end of file diff --git a/tests/prompts.test.ts b/tests/prompts.test.ts index 7b9abe8..6c0029b 100644 --- a/tests/prompts.test.ts +++ b/tests/prompts.test.ts @@ -1,18 +1,16 @@ -import { getPromptDetailsFromUrl } from "src/urls"; +import { getPromptDetailsFromUrl, getPromptUrl } from "src/urls"; describe("Fetches data from url", () => { test("Fetches prompt id from url", async () => { const promptData = await getPromptDetailsFromUrl({ - // getWorkDetailsFromUrl > getPromptDetailsFrom Url url: "https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428", }); - //wordId > promptId expect(promptData).toMatchObject({ promptId: "2644428", }); }); - test("Fetches collection name from url", async () => { + test("Fetches collection nameg from url", async () => { const workData = await getPromptDetailsFromUrl({ url: "https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428", }); @@ -25,4 +23,17 @@ describe("Fetches data from url", () => { }); -// Ensure that it says the right things first: \ No newline at end of file +describe("Gets url from data", () => { + + test("Gets url with collection name and prompt id", async () => { + const workUrl = await getPromptUrl({ + promptId: "2644428", + collectionName: "mo_dao_zu_shi_kink_meme_2020", + }); + + expect(workUrl).toBe( + "https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428" + ); + }); + +}); \ No newline at end of file From c1ffadc56092e305bc4af27f879ea8280386ec86 Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Fri, 23 Feb 2024 18:23:35 +1030 Subject: [PATCH 10/31] deleted extraneous examples and comments --- src/urls.ts | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/urls.ts b/src/urls.ts index d971dba..fa3af83 100644 --- a/src/urls.ts +++ b/src/urls.ts @@ -58,24 +58,6 @@ export const getWorkDetailsFromUrl = ({ }; }; -//defining the form of the arguments and the output -export const TODODelete = ({url,}: {url: string;}): { - workId: string; - chapterId?: string; - collectionName?: string; -} => { - const workUrlMatch = url.match(/works\/(\d+)/); - if (!workUrlMatch) { - throw new Error("Invalid work URL"); - } - - return { - workId: workUrlMatch[1], - chapterId: url.match(/chapters\/(\d+)/)?.[1], - collectionName: url.match(/collections\/(\w+)/)?.[1], - }; -}; - export const getPromptDetailsFromUrl = ({ // defining the input structure, eg. @@ -88,7 +70,7 @@ export const getPromptDetailsFromUrl = ({ //collection name is the url name, not the Display Title promptId: string; collectionName: string -} => {//TODO will fail? +} => { const promptUrlMatch = url.match(/prompts\/(\d+)/); if (!promptUrlMatch) { throw new Error("Invalid prompt URL"); From 1ef926a74ebc73c454f3775bcc5ce35d371dccdc Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Fri, 23 Feb 2024 20:04:07 +1030 Subject: [PATCH 11/31] untested: created scraper that returns the updated date of a prompt --- src/index.ts | 1 + src/page-loaders.ts | 13 +++++ src/prompts/index.ts | 26 +++++++++ src/prompts/prompt-getters.ts | 8 +++ tests/prompts.test.ts | 99 +++++++++++++++++++++++++++++++++-- types/entities.ts | 6 +++ 6 files changed, 150 insertions(+), 3 deletions(-) diff --git a/src/index.ts b/src/index.ts index c87d046..cc1afb3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,5 +2,6 @@ export * from "./users"; export * from "./tags"; export * from "./works"; export * from "./series"; +export * from "./prompts"; export { setFetcher } from "./fetcher"; diff --git a/src/page-loaders.ts b/src/page-loaders.ts index 89584e3..74ad0ed 100644 --- a/src/page-loaders.ts +++ b/src/page-loaders.ts @@ -4,6 +4,7 @@ import { getTagWorksFeedUrl, getUserProfileUrl, getWorkUrl, + getPromptUrl } from "./urls"; import { CheerioAPI } from "cheerio"; @@ -14,6 +15,18 @@ import { getFetcher } from "./fetcher"; // correct type of page is passed to each method that extracts data. // Other than this, all pages are instances of CheerioAPI and can be used interchangeably. +// A page showing a single, specified prompt from a particular collection +// Sample: https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428 +export interface PromptPage extends CheerioAPI { + kind: "PromptPage"; +} +export const loadPromptPage = async ({ id, collectionName }: { id: string, collectionName: string }) => { + return load( + await (await getFetcher()(getPromptUrl({promptId: id, collectionName: collectionName}))).text() + ) as PromptPage; +}; + + // A page showing the most recent works featuring a tag. // Sample: https://archiveofourown.org/tags/Git%20(The%20Fujoshi%20Guide%20to%20Web%20Development)/works export interface TagWorksFeed extends CheerioAPI { diff --git a/src/prompts/index.ts b/src/prompts/index.ts index e69de29..ff8a78c 100644 --- a/src/prompts/index.ts +++ b/src/prompts/index.ts @@ -0,0 +1,26 @@ +import { + Prompt +} from "types/entities" + +import { + getUpdatedAt +} from "./prompt-getters" + +import {loadPromptPage} from "../page-loaders" + +export const getPrompt = async ({ + promptId, + collectionName, +}: { + promptId: string; + collectionName: string; +}): Promise => { + console.log("Get Prompt!!") + + const promptPage = await loadPromptPage({id: promptId, collectionName: collectionName});//TODO + + return { + updatedAt: getUpdatedAt(promptPage) + } + +} \ No newline at end of file diff --git a/src/prompts/prompt-getters.ts b/src/prompts/prompt-getters.ts index e69de29..d3237aa 100644 --- a/src/prompts/prompt-getters.ts +++ b/src/prompts/prompt-getters.ts @@ -0,0 +1,8 @@ +import { PromptPage } from "../page-loaders"; + +export const getUpdatedAt = ($promptPage : PromptPage): string => { + const dateElement = $promptPage("p.datetime"); + const date = dateElement.text(); + + return date; +} \ No newline at end of file diff --git a/tests/prompts.test.ts b/tests/prompts.test.ts index 6c0029b..e053734 100644 --- a/tests/prompts.test.ts +++ b/tests/prompts.test.ts @@ -1,5 +1,7 @@ import { getPromptDetailsFromUrl, getPromptUrl } from "src/urls"; +import { getPrompt } from "src/index"; + describe("Fetches data from url", () => { test("Fetches prompt id from url", async () => { const promptData = await getPromptDetailsFromUrl({ @@ -10,7 +12,7 @@ describe("Fetches data from url", () => { }); }); - test("Fetches collection nameg from url", async () => { + test("Fetches collection name from url", async () => { const workData = await getPromptDetailsFromUrl({ url: "https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428", }); @@ -20,7 +22,6 @@ describe("Fetches data from url", () => { collectionName: "mo_dao_zu_shi_kink_meme_2020", }); }); - }); describe("Gets url from data", () => { @@ -36,4 +37,96 @@ describe("Gets url from data", () => { ); }); -}); \ No newline at end of file +}); + + + describe("Fetches prompt information", () => { + console.log("Describe??") + test("Fetches prompt updated date", async () => { + console.log("test???") + //getWork > getPrompt + //work > prompt + //calls the prompt ard recieves object below: + const prompt = await getPrompt({ + promptId: "2644428", + collectionName: "mo_dao_zu_shi_kink_meme_2020" + }); + + //work > prompt + expect(prompt).toMatchObject({ + //changed id to example prompt id + //added collectionName + updatedAt: "23 May 2022" + }); + }) +/* + authors: [{ username: "KBstories", pseud: "KBstories" }], + title: "waiting//wishing", + words: 36352, + language: "English", + rating: "Mature", + category: ["Gen", "F/M"], + fandoms: [ + "僕のヒーローアカデミア | Boku no Hero Academia | My Hero Academia", + ], + tags: { + warnings: ["Graphic Depictions Of Violence"], + characters: [ + "Kaminari Denki", + "Bakugou Katsuki", + "Kirishima Eijirou", + "Jirou Kyouka", + "Sero Hanta", + "Ashido Mina", + "Yamada Hizashi | Present Mic", + "Class 1-A (My Hero Academia)", + ], + relationships: [ + "Bakugou Katsuki/Kirishima Eijirou", + "Jirou Kyouka/Kaminari Denki", + "Bakugou Katsuki & Kaminari Denki", + "Ashido Mina & Bakugou Katsuki & Jirou Kyouka & Kaminari Denki & Kirishima Eijirou & Sero Hanta", + ], + additional: [ + "Post-Paranormal Liberation War Arc (My Hero Academia)", + "Developing Friendships", + "Character Study", + "Injury Recovery", + "Protective Bakusquad (My Hero Academia)", + "Queerplatonic Relationships", + "POV Kaminari Denki", + "the romance is There but it's not the point (the point is found family)", + "Medical Inaccuracies", + "Some Fluff", + "Asexual Bakugou Katsuki", + "Post-Traumatic Stress Disorder - PTSD", + "@ U.A. give these kids proper therapy or die by my sword", + "Hurt/Comfort", + "Angst with a Happy Ending", + "Bakusquad-centric (My Hero Academia)", + "Hospitals", + "Anxiety", + "POV Bakugou Katsuki", + "(epilogue only)", + "Canon compliant up to CH306", + "Hurt Bakugou Katsuki", + ], + }, + publishedAt: "2021-01-28", + updatedAt: "2021-03-03", + chapters: { + published: 7, + total: 7, + }, + summary: + "

Bakugou will know what to do. Top of the class, always quick on his feet and possessing the strongest nerves in all of 1-A – all of U.A., possibly. They’re at their most invincible with Bakugou there to hone their focus, to push them forward with that unique kind of teeth-bared tenacity Kaminari has come to rely on in the past year. When Kaminari looks, he sees–

Iida, helmet off, severe face twisted with agitation as he argues with the medics on the scene. Blood, so much blood, staining the gleaming chrome of his armor up to his neck in wet, intersecting streaks of crimson.

And in his arms, mask torn and body limp, is Bakugou Katsuki.”

In which disaster strikes, the Bakusquad comes together as a family once more, and Kaminari Denki is the MVP all the way through.

", + stats: { + bookmarks: 173, + comments: 110, + hits: 10903, + kudos: 664, + }, + }); + */ + }); + diff --git a/types/entities.ts b/types/entities.ts index 103448a..259ed2c 100644 --- a/types/entities.ts +++ b/types/entities.ts @@ -176,7 +176,12 @@ export interface Chapter { export interface Prompt { + updatedAt: string; + /* id: string; + collection: string; + + title: string; fandoms: string[]; //pseuds don't seem to have a noticable effect on the interface @@ -195,5 +200,6 @@ export interface Prompt { //TODO currently doing test at https://archiveofourown.org/collections/test_prompt_meme_2024/requests publishedAt: string; updatedAt: string | null; + */ } \ No newline at end of file From 81fba93af9212ccf18eb83bd393702dff7418d42 Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Sat, 24 Feb 2024 16:14:33 +1030 Subject: [PATCH 12/31] tested: prompt scraper returns updated date of a prompt --- package.json | 1 + .../prompts/2644428.html | 349 ++++++++++++++++++ tests/mocks/handlers.ts | 3 + tests/mocks/handlers/collections/prompt.ts | 31 ++ 4 files changed, 384 insertions(+) create mode 100644 tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428.html create mode 100644 tests/mocks/handlers/collections/prompt.ts diff --git a/package.json b/package.json index 17437a9..1b722c8 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "scripts": { "build": "rm -rf dist/ && tsup src/index.ts src/urls.ts --format esm,cjs --dts", "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --no-cache .test.ts$ --verbose=true", + "test-1": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --no-cache prompts.test.ts$ --verbose=true", "encode-mock-files": "ts-node-esm tests/mocks/scripts/encode-mock-files.mts" }, "repository": "https://github.com/essential-randomness/AO3.js.git", diff --git a/tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428.html b/tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428.html new file mode 100644 index 0000000..5124cf8 --- /dev/null +++ b/tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428.html @@ -0,0 +1,349 @@ + + + + + + + + + + + + + + + Show + Prompt + | + Archive of Our Own + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + +
+ +
+

Dashboard

+ + +

Prompt Meme

+ +

Contents

+ +
+ + +
+
+ +

Request by merelydovely

+ + + + + + +
+
+ +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/mocks/handlers.ts b/tests/mocks/handlers.ts index 527d45b..cc006be 100644 --- a/tests/mocks/handlers.ts +++ b/tests/mocks/handlers.ts @@ -10,6 +10,8 @@ import worksHandlers from "./handlers/works"; import worksNavigateHandlers from "./handlers/works/navigate"; import worksChapterHandlers from "./handlers/works/chapter"; +import promptHandlers from "./handlers/collections/prompt" + export default [ profileHandlers, feedHandlers, @@ -20,5 +22,6 @@ export default [ worksNavigateHandlers, worksChapterHandlers, seriesHandlers, + promptHandlers, allHandlers, ]; diff --git a/tests/mocks/handlers/collections/prompt.ts b/tests/mocks/handlers/collections/prompt.ts new file mode 100644 index 0000000..ae6444b --- /dev/null +++ b/tests/mocks/handlers/collections/prompt.ts @@ -0,0 +1,31 @@ +import { fileURLToPath } from "url"; +import filenamify from "filenamify"; +import fs from "fs"; +import path from "path"; +import { http, HttpResponse } from "msw"; + +const COLLECTIONS_DATA_DIR = path.resolve( + fileURLToPath(import.meta.url), + "../../../data/collections" +); + +// note that mock test path becomes works/work_id/chapter_id.html +// unlike in url, there is no /chapters/ directory +export default http.all( + "https://archiveofourown.org/collections/:collection_name/prompts/:prompt_id", + ({ params }) => { + const html = fs.readFileSync( + path.resolve( + COLLECTIONS_DATA_DIR, + filenamify(params.collection_name as string), + filenamify("prompts"), + `${filenamify((params.prompt_id as string) || "index")}.html` + ) + ); + + console.log("in prompt.ts") + return new HttpResponse(html, { + headers: { "Content-Type": "text/html" }, + }); + } +); From 12ba05875432906961730d7ee3474471d468c308 Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Sat, 24 Feb 2024 17:24:37 +1030 Subject: [PATCH 13/31] gets prompt summaries + removed console logs --- src/{ => collections}/prompts/index.ts | 9 +- src/collections/prompts/prompt-getters.ts | 15 + src/index.ts | 2 +- src/prompts/prompt-getters.ts | 8 - .../prompts/3566161.html | 346 ++++++++++++++++++ tests/mocks/handlers/collections/prompt.ts | 1 - tests/prompts.test.ts | 33 +- types/entities.ts | 1 + 8 files changed, 390 insertions(+), 25 deletions(-) rename src/{ => collections}/prompts/index.ts (66%) create mode 100644 src/collections/prompts/prompt-getters.ts delete mode 100644 src/prompts/prompt-getters.ts create mode 100644 tests/mocks/data/collections/test_prompt_meme_2024/prompts/3566161.html diff --git a/src/prompts/index.ts b/src/collections/prompts/index.ts similarity index 66% rename from src/prompts/index.ts rename to src/collections/prompts/index.ts index ff8a78c..7da1557 100644 --- a/src/prompts/index.ts +++ b/src/collections/prompts/index.ts @@ -3,10 +3,11 @@ import { } from "types/entities" import { - getUpdatedAt + getUpdatedAt, + getPromptSummary } from "./prompt-getters" -import {loadPromptPage} from "../page-loaders" +import {loadPromptPage} from "../../page-loaders" export const getPrompt = async ({ promptId, @@ -15,12 +16,12 @@ export const getPrompt = async ({ promptId: string; collectionName: string; }): Promise => { - console.log("Get Prompt!!") const promptPage = await loadPromptPage({id: promptId, collectionName: collectionName});//TODO return { - updatedAt: getUpdatedAt(promptPage) + updatedAt: getUpdatedAt(promptPage), + summary: getPromptSummary(promptPage) } } \ No newline at end of file diff --git a/src/collections/prompts/prompt-getters.ts b/src/collections/prompts/prompt-getters.ts new file mode 100644 index 0000000..b813982 --- /dev/null +++ b/src/collections/prompts/prompt-getters.ts @@ -0,0 +1,15 @@ +import { PromptPage } from "../../page-loaders"; + +export const getUpdatedAt = ($promptPage : PromptPage): string => { + const dateElement = $promptPage("p.datetime"); + const date = dateElement.text(); + + return date; +} + +export const getPromptSummary = ($promptPage : PromptPage): string | null => { + const summary = $promptPage("blockquote.userstuff.summary").html(); + // trim returns a new string, removes any whitespace at the start and end + // usually a new line '\n is returned at the beginning and end of the summary. + return summary ? summary.trim() : null; +}; \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index cc1afb3..8bcd5af 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,6 @@ export * from "./users"; export * from "./tags"; export * from "./works"; export * from "./series"; -export * from "./prompts"; +export * from "./collections/prompts"; export { setFetcher } from "./fetcher"; diff --git a/src/prompts/prompt-getters.ts b/src/prompts/prompt-getters.ts deleted file mode 100644 index d3237aa..0000000 --- a/src/prompts/prompt-getters.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { PromptPage } from "../page-loaders"; - -export const getUpdatedAt = ($promptPage : PromptPage): string => { - const dateElement = $promptPage("p.datetime"); - const date = dateElement.text(); - - return date; -} \ No newline at end of file diff --git a/tests/mocks/data/collections/test_prompt_meme_2024/prompts/3566161.html b/tests/mocks/data/collections/test_prompt_meme_2024/prompts/3566161.html new file mode 100644 index 0000000..b337b3f --- /dev/null +++ b/tests/mocks/data/collections/test_prompt_meme_2024/prompts/3566161.html @@ -0,0 +1,346 @@ + + + + + + + + + + + + + + + Show + Prompt + | + Archive of Our Own + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/mocks/handlers/collections/prompt.ts b/tests/mocks/handlers/collections/prompt.ts index ae6444b..5af13b7 100644 --- a/tests/mocks/handlers/collections/prompt.ts +++ b/tests/mocks/handlers/collections/prompt.ts @@ -23,7 +23,6 @@ export default http.all( ) ); - console.log("in prompt.ts") return new HttpResponse(html, { headers: { "Content-Type": "text/html" }, }); diff --git a/tests/prompts.test.ts b/tests/prompts.test.ts index e053734..4767812 100644 --- a/tests/prompts.test.ts +++ b/tests/prompts.test.ts @@ -41,24 +41,35 @@ describe("Gets url from data", () => { describe("Fetches prompt information", () => { - console.log("Describe??") + test("Fetches prompt updated date", async () => { - console.log("test???") - //getWork > getPrompt - //work > prompt - //calls the prompt ard recieves object below: const prompt = await getPrompt({ promptId: "2644428", collectionName: "mo_dao_zu_shi_kink_meme_2020" }); - - //work > prompt + + expect(prompt).toMatchObject({ + updatedAt: "23 May 2022", + summary: `

A big round of applause for all our prompters and fillers for making the first round of the MDZS Kink Meme on AO3 such a rousing success! If you want to submit your own prompt, the most recent round of prompts (2022) can be found here, and any past or future rounds can be found in the MDZS Kink Meme Parent Collection.

KEEP CLAIMING & FILLING THESE PROMPTS! Prompts from ANY round of the MDZS Kink Meme can be filled indefinitely. We will always accept more fills for old prompts!
2020 Prompts
2021 Q1 Prompts
2021 Q2 Prompts

Also, if you'd like to fill a deleted prompt you found on the Pinboard, you can add it to the collection by claiming & filling this prompt!

` + }); + }); + + + test("Fetches null summary", async () => { + const prompt = await getPrompt({ + promptId: "3566161", + collectionName: "test_prompt_meme_2024" + }); + expect(prompt).toMatchObject({ - //changed id to example prompt id - //added collectionName - updatedAt: "23 May 2022" + summary: null, }); - }) + }); + + + /*whether it actually is the updated date or the creation date is still up in the air. + altered an older prompt at about 5pm on 24/02/24 and it's still showing 23. + may be slow to update. may be something else. */ /* authors: [{ username: "KBstories", pseud: "KBstories" }], title: "waiting//wishing", diff --git a/types/entities.ts b/types/entities.ts index 259ed2c..0b2371f 100644 --- a/types/entities.ts +++ b/types/entities.ts @@ -177,6 +177,7 @@ export interface Chapter { export interface Prompt { updatedAt: string; + summary: string | null; /* id: string; collection: string; From 3bc27cb1e331844a76ecc58211de9baa7b240eaf Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Sat, 24 Feb 2024 17:44:10 +1030 Subject: [PATCH 14/31] extracted collection display name from prompt page --- notes.md | 91 ++++++++++++++++++++++- src/collections/prompts/index.ts | 6 +- src/collections/prompts/prompt-getters.ts | 8 +- tests/prompts.test.ts | 22 ++++++ types/entities.ts | 1 + 5 files changed, 124 insertions(+), 4 deletions(-) diff --git a/notes.md b/notes.md index 1cbd8d6..eb0006e 100644 --- a/notes.md +++ b/notes.md @@ -1 +1,90 @@ -TODO: delete this file (eventually) \ No newline at end of file +**creating a mock of a prompt** is a two-step process: + +1. create the directory +2. download and add the prompt page with curl. + +curl https://archiveofourown.org/works/51394438/chapters/136175206 > tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428.html + +1. mkdir tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/ +2. curl https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428 > tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428.html + + +curl https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3566161 > tests/mocks/data//collections/test_prompt_meme_2024/prompts/3566161.html + +If you're certain of your paths, you can do both at once: + +https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3566161 + +! note: The result of curl may be different depending on your terminal and your OS. + + +--- + +I'm now **troubleshooting** a new an issue with getting the mock route to fuction correctly, so I decided to **create a new test script**. To do this, I added a new line to scripts (test-1) which now reads: +```js +"scripts": { + "build": "rm -rf dist/ && tsup src/index.ts src/urls.ts --format esm,cjs --dts", + "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --no-cache .test.ts$ --verbose=true", + "test-1": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --no-cache prompts.test.ts$ --verbose=true", + "encode-mock-files": "ts-node-esm tests/mocks/scripts/encode-mock-files.mts" + }, +``` +this can be run with the command npm run test-1. + +--- + +When adding the new route handler to handlers.ts, ensure that the new export goes *before* `allHandlers`. Otherwise, allHandlers will handle your route instead. + +```js +export default [ + profileHandlers, + feedHandlers, + tagWorksHandlers, + worksHandlers, + nameHandlers, + workPageHandlers, + worksNavigateHandlers, + worksChapterHandlers, + seriesHandlers, + promptHandlers, + allHandlers +]; +``` +note that my new Handler, promptHandlers, is before allHandlers, which is last. + + +my first attempt to create a mock route did not work, so I went to look at the documentation to see if I could gain a better understanding of why, and what was going on. https://mswjs.io/docs/api/http/#httpall + +Files I'm inspecting: +1. [./tests\mocks\handlers\all.ts](./tests\mocks\handlers\all.ts) +1. [TypeScript types](./tests\mocks\handlers\collections\prompt.ts) +2. + +...ok, curl did not work?!? + +https://curl.se/docs/ +--create-dirs + + +--- + +I'm creating these notes with a markdown file that I created by making a new file called notes.md. the .md is a file extension that indicates it's a markdown file. + +I've used three hyphens: --- to create horizontal rules separating the sections. + +I've used numbers: 1. to create a numbered list. + +I've used three backtics followed by js ```js to create the new js file. + +writing something directly before a --- will cause it to become a heading? + +--- + +When getting the collection display title from the scraper in [prompt-getters](src\collections\prompts\prompt-getters.ts), my test initially failed because the the returned information had newlines at the beginning and end. I removed them with .trim(). + +The display title is the "display" name of the collection eg. "Mó Dào Zǔ Shī | The Untamed Kink Meme 2020" which is in contrast to the collection name, which appears in the url: mo_dao_zu_shi_kink_meme_2020 + + + + + diff --git a/src/collections/prompts/index.ts b/src/collections/prompts/index.ts index 7da1557..bb0460c 100644 --- a/src/collections/prompts/index.ts +++ b/src/collections/prompts/index.ts @@ -4,7 +4,8 @@ import { import { getUpdatedAt, - getPromptSummary + getPromptSummary, + getCollectionDisplayTitle } from "./prompt-getters" import {loadPromptPage} from "../../page-loaders" @@ -21,7 +22,8 @@ export const getPrompt = async ({ return { updatedAt: getUpdatedAt(promptPage), - summary: getPromptSummary(promptPage) + summary: getPromptSummary(promptPage), + collectionDisplayTitle: getCollectionDisplayTitle(promptPage) } } \ No newline at end of file diff --git a/src/collections/prompts/prompt-getters.ts b/src/collections/prompts/prompt-getters.ts index b813982..2e9b022 100644 --- a/src/collections/prompts/prompt-getters.ts +++ b/src/collections/prompts/prompt-getters.ts @@ -12,4 +12,10 @@ export const getPromptSummary = ($promptPage : PromptPage): string | null => { // trim returns a new string, removes any whitespace at the start and end // usually a new line '\n is returned at the beginning and end of the summary. return summary ? summary.trim() : null; -}; \ No newline at end of file +}; + +export const getCollectionDisplayTitle = ($promptPage : PromptPage): string => { + const titleElement = $promptPage("h2.collections"); + const title = titleElement.text().trim(); + return title; +} \ No newline at end of file diff --git a/tests/prompts.test.ts b/tests/prompts.test.ts index 4767812..a00092d 100644 --- a/tests/prompts.test.ts +++ b/tests/prompts.test.ts @@ -65,6 +65,28 @@ describe("Gets url from data", () => { summary: null, }); }); + + test("Fetches null summary", async () => { + const prompt = await getPrompt({ + promptId: "3566161", + collectionName: "test_prompt_meme_2024" + }); + + expect(prompt).toMatchObject({ + summary: null, + }); + }); + + test("Fetches display title", async () => { + const prompt = await getPrompt({ + promptId: "2644428", + collectionName: "mo_dao_zu_shi_kink_meme_2020" + }); + + expect(prompt).toMatchObject({ + collectionDisplayTitle: "Mó Dào Zǔ Shī | The Untamed Kink Meme 2020", + }); + }); /*whether it actually is the updated date or the creation date is still up in the air. diff --git a/types/entities.ts b/types/entities.ts index 0b2371f..0b0bb33 100644 --- a/types/entities.ts +++ b/types/entities.ts @@ -178,6 +178,7 @@ export interface Chapter { export interface Prompt { updatedAt: string; summary: string | null; + collectionDisplayTitle: string; /* id: string; collection: string; From 09d7f781fb0fc6bb137292f4ebd19770142389c7 Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Sat, 24 Feb 2024 20:54:14 +1030 Subject: [PATCH 15/31] fetching rating lists for prompts --- notes.md | 34 +- src/collections/prompts/index.ts | 6 +- src/collections/prompts/prompt-getters.ts | 24 +- .../prompts/1927806.html | 359 ++++++++++++++++++ tests/prompts.test.ts | 102 ++--- types/entities.ts | 1 + 6 files changed, 440 insertions(+), 86 deletions(-) create mode 100644 tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806.html diff --git a/notes.md b/notes.md index eb0006e..700d23d 100644 --- a/notes.md +++ b/notes.md @@ -9,13 +9,14 @@ curl https://archiveofourown.org/works/51394438/chapters/136175206 > tests/mocks 2. curl https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428 > tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428.html -curl https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3566161 > tests/mocks/data//collections/test_prompt_meme_2024/prompts/3566161.html -If you're certain of your paths, you can do both at once: +actually... mkdir failed because it wouldn't create multiple levels of directory. huh. I had to do it twice with first the collection name, and then the prompts. -https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3566161 +A beter solution: curl --create-dirs --output tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806.html https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806 -! note: The result of curl may be different depending on your terminal and your OS. +! note: The result of curl may be different depending on your terminal and your OS. I use windows and had to open up a new "Git Bash" terminal. + +curl info here: https://man.developpez.com/man1/curl/#:~:text=%2D%2Dcreate%2Ddirs%20When%20used,no%20dir%20will%20be%20created. --- @@ -84,7 +85,32 @@ When getting the collection display title from the scraper in [prompt-getters](s The display title is the "display" name of the collection eg. "Mó Dào Zǔ Shī | The Untamed Kink Meme 2020" which is in contrast to the collection name, which appears in the url: mo_dao_zu_shi_kink_meme_2020 +--- + +A work can have multiple ratings values, or none. Therefore what we return will be an array. + +This one has General, Teen and Mature ratings, so I used to in the test: +https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806 + +now, to add it to the local file path... + +curl --create-dirs --output tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806.html https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806 +getting the ratings was make more difficult by the fact I didn't have the correct key in my toMatchObject(Object) parameter. I misspelled it, and that caused me trouble! +The error showed all possible key/value pairs that might be in the object, which confused me a lot. + +--- + +Deciding how to name my boolean I looked it up and grabbed this quote: + +In many languages, the convention for naming Booleans is typically to prefix them with "is", "has" or "can". This convention seems to be applied mostly to fields and method + +--- +What these attributes actually do: +updatedAt: The last date the prompt was updated. Appears in the upper-right hand corner of a prompt. (I am not actually certain this is the updated date and not the posted date at present, currently performing a test here: https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3564199) +summary: The test description of the prompt, as html +collectionDisplayTitle: the title displayed on the collection pages and in tags. Not the same as collectionName, which is used to contruct the collection's url. +ratings: a list of the requested ratings on the prompt. The prompt will display the highest of these on its UI. If the fic has no ratings, "Not Rated" will be returned. diff --git a/src/collections/prompts/index.ts b/src/collections/prompts/index.ts index bb0460c..4d0e2e1 100644 --- a/src/collections/prompts/index.ts +++ b/src/collections/prompts/index.ts @@ -5,7 +5,8 @@ import { import { getUpdatedAt, getPromptSummary, - getCollectionDisplayTitle + getCollectionDisplayTitle, + getPromptRatings } from "./prompt-getters" import {loadPromptPage} from "../../page-loaders" @@ -23,7 +24,8 @@ export const getPrompt = async ({ return { updatedAt: getUpdatedAt(promptPage), summary: getPromptSummary(promptPage), - collectionDisplayTitle: getCollectionDisplayTitle(promptPage) + collectionDisplayTitle: getCollectionDisplayTitle(promptPage), + ratings: getPromptRatings(promptPage) } } \ No newline at end of file diff --git a/src/collections/prompts/prompt-getters.ts b/src/collections/prompts/prompt-getters.ts index 2e9b022..4302c25 100644 --- a/src/collections/prompts/prompt-getters.ts +++ b/src/collections/prompts/prompt-getters.ts @@ -1,3 +1,6 @@ +import { + WorkRatings +} from "types/entities" import { PromptPage } from "../../page-loaders"; export const getUpdatedAt = ($promptPage : PromptPage): string => { @@ -18,4 +21,23 @@ export const getCollectionDisplayTitle = ($promptPage : PromptPage): string => { const titleElement = $promptPage("h2.collections"); const title = titleElement.text().trim(); return title; -} \ No newline at end of file +} + +export const getPromptRatings = ($promptPage: PromptPage): WorkRatings[] => { + const ratingsString = $promptPage("ul.required-tags span.rating").text().trim(); + //if the work has no rating, the string gathered from the page will be "No rating" + const hasRatings = !(ratingsString === "No rating"); + const ratingsArray = ratingsString.split(', '); + + if (hasRatings){ + ratingsArray.forEach(rating => { + if (!Object.values(WorkRatings).includes(rating as WorkRatings)) { + throw new Error("An unknown rating was found on the page: \""+ rating+"\""); + } + }) + } + + if (hasRatings) return ratingsArray as WorkRatings[] + else return ["Not Rated"] as WorkRatings[] + +}; \ No newline at end of file diff --git a/tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806.html b/tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806.html new file mode 100644 index 0000000..b00bb21 --- /dev/null +++ b/tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806.html @@ -0,0 +1,359 @@ + + + + + + + + + + + + + + + Show + Prompt + | + Archive of Our Own + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + +
+ +
+

Dashboard

+ + +

Prompt Meme

+ +

Contents

+ +
+ + +
+
+ +

Request by Anonymous

+ + + + + + +
+
+ +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/prompts.test.ts b/tests/prompts.test.ts index a00092d..b830b0f 100644 --- a/tests/prompts.test.ts +++ b/tests/prompts.test.ts @@ -42,6 +42,10 @@ describe("Gets url from data", () => { describe("Fetches prompt information", () => { + /*whether it actually is the updated date or the creation date is still up in the air. + altered an older prompt at about 5pm on 24/02/24 and it's still showing 23. + may be slow to update. may be something else. */ + test("Fetches prompt updated date", async () => { const prompt = await getPrompt({ promptId: "2644428", @@ -66,100 +70,40 @@ describe("Gets url from data", () => { }); }); - test("Fetches null summary", async () => { + test("Fetches display title", async () => { const prompt = await getPrompt({ - promptId: "3566161", - collectionName: "test_prompt_meme_2024" + promptId: "2644428", + collectionName: "mo_dao_zu_shi_kink_meme_2020" }); expect(prompt).toMatchObject({ - summary: null, + collectionDisplayTitle: "Mó Dào Zǔ Shī | The Untamed Kink Meme 2020", }); }); - test("Fetches display title", async () => { + + test("Fetches Ratings", async () => { const prompt = await getPrompt({ - promptId: "2644428", + promptId: "1927806", collectionName: "mo_dao_zu_shi_kink_meme_2020" }); expect(prompt).toMatchObject({ - collectionDisplayTitle: "Mó Dào Zǔ Shī | The Untamed Kink Meme 2020", + ratings: ["General Audiences", "Teen And Up Audiences", "Mature"], }); }); - - /*whether it actually is the updated date or the creation date is still up in the air. - altered an older prompt at about 5pm on 24/02/24 and it's still showing 23. - may be slow to update. may be something else. */ -/* - authors: [{ username: "KBstories", pseud: "KBstories" }], - title: "waiting//wishing", - words: 36352, - language: "English", - rating: "Mature", - category: ["Gen", "F/M"], - fandoms: [ - "僕のヒーローアカデミア | Boku no Hero Academia | My Hero Academia", - ], - tags: { - warnings: ["Graphic Depictions Of Violence"], - characters: [ - "Kaminari Denki", - "Bakugou Katsuki", - "Kirishima Eijirou", - "Jirou Kyouka", - "Sero Hanta", - "Ashido Mina", - "Yamada Hizashi | Present Mic", - "Class 1-A (My Hero Academia)", - ], - relationships: [ - "Bakugou Katsuki/Kirishima Eijirou", - "Jirou Kyouka/Kaminari Denki", - "Bakugou Katsuki & Kaminari Denki", - "Ashido Mina & Bakugou Katsuki & Jirou Kyouka & Kaminari Denki & Kirishima Eijirou & Sero Hanta", - ], - additional: [ - "Post-Paranormal Liberation War Arc (My Hero Academia)", - "Developing Friendships", - "Character Study", - "Injury Recovery", - "Protective Bakusquad (My Hero Academia)", - "Queerplatonic Relationships", - "POV Kaminari Denki", - "the romance is There but it's not the point (the point is found family)", - "Medical Inaccuracies", - "Some Fluff", - "Asexual Bakugou Katsuki", - "Post-Traumatic Stress Disorder - PTSD", - "@ U.A. give these kids proper therapy or die by my sword", - "Hurt/Comfort", - "Angst with a Happy Ending", - "Bakusquad-centric (My Hero Academia)", - "Hospitals", - "Anxiety", - "POV Bakugou Katsuki", - "(epilogue only)", - "Canon compliant up to CH306", - "Hurt Bakugou Katsuki", - ], - }, - publishedAt: "2021-01-28", - updatedAt: "2021-03-03", - chapters: { - published: 7, - total: 7, - }, - summary: - "

Bakugou will know what to do. Top of the class, always quick on his feet and possessing the strongest nerves in all of 1-A – all of U.A., possibly. They’re at their most invincible with Bakugou there to hone their focus, to push them forward with that unique kind of teeth-bared tenacity Kaminari has come to rely on in the past year. When Kaminari looks, he sees–

Iida, helmet off, severe face twisted with agitation as he argues with the medics on the scene. Blood, so much blood, staining the gleaming chrome of his armor up to his neck in wet, intersecting streaks of crimson.

And in his arms, mask torn and body limp, is Bakugou Katsuki.”

In which disaster strikes, the Bakusquad comes together as a family once more, and Kaminari Denki is the MVP all the way through.

", - stats: { - bookmarks: 173, - comments: 110, - hits: 10903, - kudos: 664, - }, + test("Fetches \"Not Rated\" for no specified ratings", async () => { + const prompt = await getPrompt( + await getPromptDetailsFromUrl({ + url: "https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428", + }) + ); + + expect(prompt).toMatchObject({ + ratings: ["Not Rated"], }); - */ + }); + }); diff --git a/types/entities.ts b/types/entities.ts index 0b0bb33..b008046 100644 --- a/types/entities.ts +++ b/types/entities.ts @@ -179,6 +179,7 @@ export interface Prompt { updatedAt: string; summary: string | null; collectionDisplayTitle: string; + ratings: WorkRatings[]; /* id: string; collection: string; From 5f0a1d87927c54510d4b93e04e9380e19bf7188a Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Wed, 28 Feb 2024 12:20:11 +1030 Subject: [PATCH 16/31] ran tests for fetching ratings --- tests/prompts.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/prompts.test.ts b/tests/prompts.test.ts index b830b0f..4a7c163 100644 --- a/tests/prompts.test.ts +++ b/tests/prompts.test.ts @@ -105,5 +105,6 @@ describe("Gets url from data", () => { }); }); + }); From 96bec3a2eaeace5a08786f23ef0f8df16664cbdc Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Wed, 28 Feb 2024 16:19:53 +1030 Subject: [PATCH 17/31] created tests for prompt authors + added mocks for this purpose --- src/collections/prompts/index.ts | 3 +- .../prompts/3573835.html | 354 ++++++++++++++++++ .../prompts/3574012.html | 350 +++++++++++++++++ tests/prompts.test.ts | 41 ++ types/entities.ts | 3 + 5 files changed, 750 insertions(+), 1 deletion(-) create mode 100644 tests/mocks/data/collections/test_prompt_meme_2024/prompts/3573835.html create mode 100644 tests/mocks/data/collections/test_prompt_meme_2024/prompts/3574012.html diff --git a/src/collections/prompts/index.ts b/src/collections/prompts/index.ts index 4d0e2e1..25f2b02 100644 --- a/src/collections/prompts/index.ts +++ b/src/collections/prompts/index.ts @@ -25,7 +25,8 @@ export const getPrompt = async ({ updatedAt: getUpdatedAt(promptPage), summary: getPromptSummary(promptPage), collectionDisplayTitle: getCollectionDisplayTitle(promptPage), - ratings: getPromptRatings(promptPage) + ratings: getPromptRatings(promptPage), + author: {username: "TO DO", pseud: "To DO"} } } \ No newline at end of file diff --git a/tests/mocks/data/collections/test_prompt_meme_2024/prompts/3573835.html b/tests/mocks/data/collections/test_prompt_meme_2024/prompts/3573835.html new file mode 100644 index 0000000..17f581d --- /dev/null +++ b/tests/mocks/data/collections/test_prompt_meme_2024/prompts/3573835.html @@ -0,0 +1,354 @@ + + + + + + + + + + + + + + + Show + Prompt + | + Archive of Our Own + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/mocks/data/collections/test_prompt_meme_2024/prompts/3574012.html b/tests/mocks/data/collections/test_prompt_meme_2024/prompts/3574012.html new file mode 100644 index 0000000..6621b2e --- /dev/null +++ b/tests/mocks/data/collections/test_prompt_meme_2024/prompts/3574012.html @@ -0,0 +1,350 @@ + + + + + + + + + + + + + + + Show + Prompt + | + Archive of Our Own + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/prompts.test.ts b/tests/prompts.test.ts index 4a7c163..a493376 100644 --- a/tests/prompts.test.ts +++ b/tests/prompts.test.ts @@ -104,6 +104,47 @@ describe("Gets url from data", () => { ratings: ["Not Rated"], }); }); + + test("Fetches Author(+pseud)", async () => { + const prompt = await getPrompt( + await getPromptDetailsFromUrl({ + url: "https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3573835", + }) + ); + + expect(prompt).toMatchObject({ + author: { + username: "RabbitPie", + pseud: "cottontailcake"} + }); + }); + + test("Fetches Anonymous Author", async () => { + const prompt = await getPrompt( + await getPromptDetailsFromUrl({ + url: "https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3574012", + }) + ); + + expect(prompt).toMatchObject({ + author: "Anonymous" + }); + }); + + test("Fetches Non-Pseuded Author", async () => { + const prompt = await getPrompt( + await getPromptDetailsFromUrl({ + url: "https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428", + }) + ); + + expect(prompt).toMatchObject({ + author: { + username: "merelydovely", + pseud: "merelydovely" + }, + }); + }); }); diff --git a/types/entities.ts b/types/entities.ts index b008046..b459d2c 100644 --- a/types/entities.ts +++ b/types/entities.ts @@ -180,6 +180,9 @@ export interface Prompt { summary: string | null; collectionDisplayTitle: string; ratings: WorkRatings[]; + author: Author | "Anonymous"; + + /* id: string; collection: string; From 1addc20f4dd8b627ff99e93b83d34d754fd62a3c Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Sat, 2 Mar 2024 14:45:54 +1030 Subject: [PATCH 18/31] implemented get prompt authors --- src/collections/prompts/index.ts | 5 +++-- src/collections/prompts/prompt-getters.ts | 25 ++++++++++++++++++++++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/collections/prompts/index.ts b/src/collections/prompts/index.ts index 25f2b02..1975baf 100644 --- a/src/collections/prompts/index.ts +++ b/src/collections/prompts/index.ts @@ -6,7 +6,8 @@ import { getUpdatedAt, getPromptSummary, getCollectionDisplayTitle, - getPromptRatings + getPromptRatings, + getPromptAuthor } from "./prompt-getters" import {loadPromptPage} from "../../page-loaders" @@ -26,7 +27,7 @@ export const getPrompt = async ({ summary: getPromptSummary(promptPage), collectionDisplayTitle: getCollectionDisplayTitle(promptPage), ratings: getPromptRatings(promptPage), - author: {username: "TO DO", pseud: "To DO"} + author: getPromptAuthor(promptPage) } } \ No newline at end of file diff --git a/src/collections/prompts/prompt-getters.ts b/src/collections/prompts/prompt-getters.ts index 4302c25..a687ac5 100644 --- a/src/collections/prompts/prompt-getters.ts +++ b/src/collections/prompts/prompt-getters.ts @@ -1,4 +1,5 @@ import { + Author, WorkRatings } from "types/entities" import { PromptPage } from "../../page-loaders"; @@ -40,4 +41,26 @@ export const getPromptRatings = ($promptPage: PromptPage): WorkRatings[] => { if (hasRatings) return ratingsArray as WorkRatings[] else return ["Not Rated"] as WorkRatings[] -}; \ No newline at end of file +}; + +export const getPromptAuthor = ($promptPage: PromptPage): Author | "Anonymous"=> { + + const requestHeading = $promptPage("#main.prompts-show.dashboard.region > h2").text().trim(); + + if(requestHeading === "Request by Anonymous") return "Anonymous" + + const pseudAndUser = /Request by ([^\(]*)?\(?([^\)]*)/g + + const captures = pseudAndUser.exec(requestHeading); + + if (!captures) throw new Error("Could not evalueate Prompt Author String"); + + const pseud = captures[1].trim(); + const user = captures[2] ? captures[2] : pseud; + + return { + username: user, + pseud: pseud + } as Author + +} \ No newline at end of file From 5fedc198ab004694f0356ace9ee5bf8212c2afd8 Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Sat, 2 Mar 2024 16:35:52 +1030 Subject: [PATCH 19/31] testing upstream/fork relationship --- notes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/notes.md b/notes.md index 700d23d..7e3372b 100644 --- a/notes.md +++ b/notes.md @@ -114,3 +114,5 @@ updatedAt: The last date the prompt was updated. Appears in the upper-right hand summary: The test description of the prompt, as html collectionDisplayTitle: the title displayed on the collection pages and in tags. Not the same as collectionName, which is used to contruct the collection's url. ratings: a list of the requested ratings on the prompt. The prompt will display the highest of these on its UI. If the fic has no ratings, "Not Rated" will be returned. + +Test change. \ No newline at end of file From c17f71bd9b9d5a3003cfd073d44af2e35ae00ac9 Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Sun, 3 Mar 2024 16:30:57 +1030 Subject: [PATCH 20/31] created test for get tags --- src/collections/prompts/index.ts | 9 ++++++++- tests/prompts.test.ts | 20 +++++++++++++++++++- types/entities.ts | 8 +++++++- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/collections/prompts/index.ts b/src/collections/prompts/index.ts index 1975baf..f8650c5 100644 --- a/src/collections/prompts/index.ts +++ b/src/collections/prompts/index.ts @@ -27,7 +27,14 @@ export const getPrompt = async ({ summary: getPromptSummary(promptPage), collectionDisplayTitle: getCollectionDisplayTitle(promptPage), ratings: getPromptRatings(promptPage), - author: getPromptAuthor(promptPage) + author: getPromptAuthor(promptPage), + fandoms: ["To do"], + tags: { + warnings: [], + characters: [], + relationships: [], + additional: [] + } } } \ No newline at end of file diff --git a/tests/prompts.test.ts b/tests/prompts.test.ts index a493376..1a76198 100644 --- a/tests/prompts.test.ts +++ b/tests/prompts.test.ts @@ -144,7 +144,25 @@ describe("Gets url from data", () => { pseud: "merelydovely" }, }); - }); + }); + + test("Gets tags", async () => { + const prompt = await getPrompt( + await getPromptDetailsFromUrl({ + url: "https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428", + }) + ); + + expect(prompt).toMatchObject({ + fandoms: ["SD Gundam G Generation Series (Video Games)", "Babel - R. F. Kuang"], + tags: { + warnings: ["Choose Not To Use Archive Warnings"], + characters: ["Kate Schmidt (Fear Street)","Sa Beining","Ffion Foxwell"], + relationships: ["Sophie Lee/Rune (Sdorica)","CC-2224 | Cody & CT-7567 | Rex","Denji/Mitaka Asa"], + additional: ["Ewok Species (Star Wars)","FS Lobby Discord's GP Predictions Game","Natasha \"Phoenix\" Trace Needs a Hug"] + } + }); + }); }); diff --git a/types/entities.ts b/types/entities.ts index b459d2c..c9e2627 100644 --- a/types/entities.ts +++ b/types/entities.ts @@ -181,7 +181,13 @@ export interface Prompt { collectionDisplayTitle: string; ratings: WorkRatings[]; author: Author | "Anonymous"; - + fandoms: string[]; + tags: { + warnings: WorkWarnings[]; + characters: string[]; + relationships: string[]; + additional: string[]; + }; /* id: string; From f4c64c4b5c8f39d7ff1cf431f934127a633a9b91 Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Sun, 3 Mar 2024 17:48:50 +1030 Subject: [PATCH 21/31] added tags functionality; updatedAt became postedAt; discovered I need better tests --- notes.md | 17 ++++--- src/collections/prompts/index.ts | 21 +++++---- src/collections/prompts/prompt-getters.ts | 56 +++++++++++++++++++++-- tests/prompts.test.ts | 12 ++--- types/entities.ts | 43 +++++++++-------- 5 files changed, 101 insertions(+), 48 deletions(-) diff --git a/notes.md b/notes.md index 7e3372b..83f19d5 100644 --- a/notes.md +++ b/notes.md @@ -9,7 +9,6 @@ curl https://archiveofourown.org/works/51394438/chapters/136175206 > tests/mocks 2. curl https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428 > tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428.html - actually... mkdir failed because it wouldn't create multiple levels of directory. huh. I had to do it twice with first the collection name, and then the prompts. A beter solution: curl --create-dirs --output tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806.html https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806 @@ -108,11 +107,15 @@ In many languages, the convention for naming Booleans is typically to prefix the --- -What these attributes actually do: +# Attribute Descriptions + +* **postedAt** The date the prompt was posted. +* **summary**: The test description of the prompt, as html +* **collectionDisplayTitle**: the title displayed on the collection pages and in tags. Not the same as collectionName, which is used to contruct the collection's url. +* **ratings**: a list of the requested ratings on the prompt. The prompt will display the highest of these on its UI. If the fic has no ratings, "Not Rated" will be returned. -updatedAt: The last date the prompt was updated. Appears in the upper-right hand corner of a prompt. (I am not actually certain this is the updated date and not the posted date at present, currently performing a test here: https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3564199) -summary: The test description of the prompt, as html -collectionDisplayTitle: the title displayed on the collection pages and in tags. Not the same as collectionName, which is used to contruct the collection's url. -ratings: a list of the requested ratings on the prompt. The prompt will display the highest of these on its UI. If the fic has no ratings, "Not Rated" will be returned. +---- -Test change. \ No newline at end of file +# TODO: +1. Query selectors need to be redone: Currently, they may pick up the prompt fills!! ... oh man, I need the prompt fills! +2. New, more thorough tests to test different types of prompts in their entirety: will fail most of the time. I'll have to see how the series-getter approaches the issue of multiple \ No newline at end of file diff --git a/src/collections/prompts/index.ts b/src/collections/prompts/index.ts index f8650c5..a0a7a62 100644 --- a/src/collections/prompts/index.ts +++ b/src/collections/prompts/index.ts @@ -3,11 +3,16 @@ import { } from "types/entities" import { - getUpdatedAt, + getPostedAt, getPromptSummary, getCollectionDisplayTitle, getPromptRatings, - getPromptAuthor + getPromptAuthor, + getPromptFandoms, + getPromptAdditionalTags, + getPromptCharacters, + getPromptRelationships, + getPromptWarnings } from "./prompt-getters" import {loadPromptPage} from "../../page-loaders" @@ -23,17 +28,17 @@ export const getPrompt = async ({ const promptPage = await loadPromptPage({id: promptId, collectionName: collectionName});//TODO return { - updatedAt: getUpdatedAt(promptPage), + postedAt: getPostedAt(promptPage), summary: getPromptSummary(promptPage), collectionDisplayTitle: getCollectionDisplayTitle(promptPage), ratings: getPromptRatings(promptPage), author: getPromptAuthor(promptPage), - fandoms: ["To do"], + fandoms: getPromptFandoms(promptPage), tags: { - warnings: [], - characters: [], - relationships: [], - additional: [] + warnings: getPromptWarnings(promptPage), + characters: getPromptCharacters(promptPage), + relationships: getPromptRelationships(promptPage), + additional: getPromptAdditionalTags(promptPage) } } diff --git a/src/collections/prompts/prompt-getters.ts b/src/collections/prompts/prompt-getters.ts index a687ac5..029b5a8 100644 --- a/src/collections/prompts/prompt-getters.ts +++ b/src/collections/prompts/prompt-getters.ts @@ -1,10 +1,11 @@ import { Author, - WorkRatings + WorkRatings, + WorkWarnings } from "types/entities" import { PromptPage } from "../../page-loaders"; -export const getUpdatedAt = ($promptPage : PromptPage): string => { +export const getPostedAt = ($promptPage : PromptPage): string => { const dateElement = $promptPage("p.datetime"); const date = dateElement.text(); @@ -62,5 +63,54 @@ export const getPromptAuthor = ($promptPage: PromptPage): Author | "Anonymous"=> username: user, pseud: pseud } as Author +} + +export const getPromptFandoms = ($promptPage: PromptPage): string[] => { + const fandoms: string[] = []; + + $promptPage("h5.fandoms.heading a.tag").each(function (i, element) { + fandoms[i] = $promptPage(element).text().trim(); + }); + return fandoms; +}; + +export const getPromptAdditionalTags = ($promptPage: PromptPage): string[] => { + const freeform: string[] = []; + $promptPage("li.freeforms a.tag").each(function (i) { + freeform[i] = $promptPage(this).text().trim(); + }); + return freeform; +}; + +export const getPromptWarnings = ($promptPage: PromptPage): WorkWarnings[] => { + const warnings: WorkWarnings[] = []; + + $promptPage("li.warnings a.tag").each(function (i, element) { + const warning = $promptPage(element).text().trim(); + console.log(warning); + if (!Object.values(WorkWarnings).includes(warning as WorkWarnings)) { + throw new Error("An unknown warning was found on the page"); + } + + warnings[i] = warning as WorkWarnings; + }); + return warnings; +}; + +export const getPromptCharacters = ($promptPage: PromptPage): string[] => { + const characters: string[] = []; + + $promptPage("li.characters a.tag").each(function (i, character) { + characters[i] = $promptPage(character).text().trim(); + }); + return characters; +}; + +export const getPromptRelationships = ($promptPage: PromptPage): string[] => { + const ships: string[] = []; -} \ No newline at end of file + $promptPage("li.relationships a.tag").each(function (i, ship) { + ships[i] = $promptPage(ship).text().trim(); + }); + return ships; +}; \ No newline at end of file diff --git a/tests/prompts.test.ts b/tests/prompts.test.ts index 1a76198..d4f8050 100644 --- a/tests/prompts.test.ts +++ b/tests/prompts.test.ts @@ -42,10 +42,6 @@ describe("Gets url from data", () => { describe("Fetches prompt information", () => { - /*whether it actually is the updated date or the creation date is still up in the air. - altered an older prompt at about 5pm on 24/02/24 and it's still showing 23. - may be slow to update. may be something else. */ - test("Fetches prompt updated date", async () => { const prompt = await getPrompt({ promptId: "2644428", @@ -53,7 +49,7 @@ describe("Gets url from data", () => { }); expect(prompt).toMatchObject({ - updatedAt: "23 May 2022", + postedAt: "23 May 2022", summary: `

A big round of applause for all our prompters and fillers for making the first round of the MDZS Kink Meme on AO3 such a rousing success! If you want to submit your own prompt, the most recent round of prompts (2022) can be found here, and any past or future rounds can be found in the MDZS Kink Meme Parent Collection.

KEEP CLAIMING & FILLING THESE PROMPTS! Prompts from ANY round of the MDZS Kink Meme can be filled indefinitely. We will always accept more fills for old prompts!
2020 Prompts
2021 Q1 Prompts
2021 Q2 Prompts

Also, if you'd like to fill a deleted prompt you found on the Pinboard, you can add it to the collection by claiming & filling this prompt!

` }); }); @@ -146,17 +142,17 @@ describe("Gets url from data", () => { }); }); - test("Gets tags", async () => { + test("Fetches fandoms, addition, characters, relationships and warnings tags", async () => { const prompt = await getPrompt( await getPromptDetailsFromUrl({ - url: "https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428", + url: "https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3573835", }) ); expect(prompt).toMatchObject({ fandoms: ["SD Gundam G Generation Series (Video Games)", "Babel - R. F. Kuang"], tags: { - warnings: ["Choose Not To Use Archive Warnings"], + warnings: ["Creator Chose Not To Use Archive Warnings"], characters: ["Kate Schmidt (Fear Street)","Sa Beining","Ffion Foxwell"], relationships: ["Sophie Lee/Rune (Sdorica)","CC-2224 | Cody & CT-7567 | Rex","Denji/Mitaka Asa"], additional: ["Ewok Species (Star Wars)","FS Lobby Discord's GP Predictions Game","Natasha \"Phoenix\" Trace Needs a Hug"] diff --git a/types/entities.ts b/types/entities.ts index c9e2627..076e403 100644 --- a/types/entities.ts +++ b/types/entities.ts @@ -174,9 +174,21 @@ export interface Chapter { url: string; } +export enum PromptWarnings { + GRAPHIC_VIOLENCE = "Graphic Depictions Of Violence", + MAJOR_CHARACTER_DEATH = "Major Character Death", + NO_WARNINGS_APPLY = "No Archive Warnings Apply", + NONCON = "Rape/Non-Con", + UNDERAGE = "Underage", + CHOOSE_NOT_TO_WARN = "Choose Not To Use Archive Warnings", +} + +export interface PromptWorkSummary { + +} export interface Prompt { - updatedAt: string; + postedAt: string; summary: string | null; collectionDisplayTitle: string; ratings: WorkRatings[]; @@ -189,27 +201,14 @@ export interface Prompt { additional: string[]; }; - /* - id: string; - collection: string; - - - title: string; - fandoms: string[]; - //pseuds don't seem to have a noticable effect on the interface - prompter: "Anonymous" | string; - rating: WorkRatings; - tags: { - warnings: WorkWarnings[]; - characters: string[]; - relationships: string[]; - additional: string[]; - }; - fulfilled: boolean; - //there's a HTML option? - summary: string; - //Which of these applies to prompts? - //TODO currently doing test at https://archiveofourown.org/collections/test_prompt_meme_2024/requests +/* + fills: PromptWorkSummary[], + filled: boolean + id: string, + collection: string, + title: string +*/ +/* publishedAt: string; updatedAt: string | null; */ From 1077f86ab2806d125b8c6dc491b15db72e54f9b3 Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Sun, 3 Mar 2024 18:52:25 +1030 Subject: [PATCH 22/31] Prompt entities now describe the whole prompt --- src/collections/prompts/index.ts | 17 +++++++++++++++-- types/entities.ts | 29 ++++++++++++++--------------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/collections/prompts/index.ts b/src/collections/prompts/index.ts index a0a7a62..3730fec 100644 --- a/src/collections/prompts/index.ts +++ b/src/collections/prompts/index.ts @@ -1,5 +1,6 @@ import { - Prompt + Prompt, + WorkCategory } from "types/entities" import { @@ -34,12 +35,24 @@ export const getPrompt = async ({ ratings: getPromptRatings(promptPage), author: getPromptAuthor(promptPage), fandoms: getPromptFandoms(promptPage), + //TODO needs work: tags: { warnings: getPromptWarnings(promptPage), characters: getPromptCharacters(promptPage), relationships: getPromptRelationships(promptPage), additional: getPromptAdditionalTags(promptPage) - } + }, + //TODO: + claims: { + anonymousClaims: 12, + knownClaimaints: [{username: "TODO", pseud: "TODO2"}], + }, + title: "TODO", + collectionName: "TODO", + id: "TODO", + filled: true, + fills: [{todo:"TODO"}], + categories: [] } } \ No newline at end of file diff --git a/types/entities.ts b/types/entities.ts index 076e403..a02d4ce 100644 --- a/types/entities.ts +++ b/types/entities.ts @@ -184,7 +184,7 @@ export enum PromptWarnings { } export interface PromptWorkSummary { - + todo: "TODO" } export interface Prompt { @@ -194,23 +194,22 @@ export interface Prompt { ratings: WorkRatings[]; author: Author | "Anonymous"; fandoms: string[]; + // warnings are not neccessarily tags in prompts, + // but are here to be consistent with the WorkSummary interface tags: { warnings: WorkWarnings[]; characters: string[]; relationships: string[]; additional: string[]; - }; - -/* - fills: PromptWorkSummary[], - filled: boolean - id: string, - collection: string, - title: string -*/ -/* - publishedAt: string; - updatedAt: string | null; - */ - + }; + claims: { + anonymousClaims: number; + knownClaimaints: Author[]; + } + title: string; + collectionName: string; + id: string; + filled: boolean; + fills: PromptWorkSummary[]; + categories: WorkCategory[]; } \ No newline at end of file From 052ef2c2a2c665499da91495f0ae1b0ebb75d9aa Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Sun, 3 Mar 2024 18:53:30 +1030 Subject: [PATCH 23/31] Prompt entities now describe the whole prompt --- src/collections/prompts/index.ts | 2 +- src/collections/prompts/prompt-getters.ts | 1 - types/entities.ts | 19 +++++++------------ 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/collections/prompts/index.ts b/src/collections/prompts/index.ts index 3730fec..f8326e6 100644 --- a/src/collections/prompts/index.ts +++ b/src/collections/prompts/index.ts @@ -51,7 +51,7 @@ export const getPrompt = async ({ collectionName: "TODO", id: "TODO", filled: true, - fills: [{todo:"TODO"}], + fills: [], categories: [] } diff --git a/src/collections/prompts/prompt-getters.ts b/src/collections/prompts/prompt-getters.ts index 029b5a8..5c90b04 100644 --- a/src/collections/prompts/prompt-getters.ts +++ b/src/collections/prompts/prompt-getters.ts @@ -87,7 +87,6 @@ export const getPromptWarnings = ($promptPage: PromptPage): WorkWarnings[] => { $promptPage("li.warnings a.tag").each(function (i, element) { const warning = $promptPage(element).text().trim(); - console.log(warning); if (!Object.values(WorkWarnings).includes(warning as WorkWarnings)) { throw new Error("An unknown warning was found on the page"); } diff --git a/types/entities.ts b/types/entities.ts index a02d4ce..1e1a240 100644 --- a/types/entities.ts +++ b/types/entities.ts @@ -174,17 +174,12 @@ export interface Chapter { url: string; } -export enum PromptWarnings { - GRAPHIC_VIOLENCE = "Graphic Depictions Of Violence", - MAJOR_CHARACTER_DEATH = "Major Character Death", - NO_WARNINGS_APPLY = "No Archive Warnings Apply", - NONCON = "Rape/Non-Con", - UNDERAGE = "Underage", - CHOOSE_NOT_TO_WARN = "Choose Not To Use Archive Warnings", -} - -export interface PromptWorkSummary { - todo: "TODO" +export interface PromptFillSummary + extends Omit< + WorkSummary, + | "publishedAt" + | "locked" + > { } export interface Prompt { @@ -210,6 +205,6 @@ export interface Prompt { collectionName: string; id: string; filled: boolean; - fills: PromptWorkSummary[]; + fills: PromptFillSummary[]; categories: WorkCategory[]; } \ No newline at end of file From b11ec64f3b256d4834e5a1510fc3634c50fc07c7 Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Mon, 4 Mar 2024 12:15:17 +1030 Subject: [PATCH 24/31] Created test+added mocks for prompts with multiple fills and anon/known prompt claimers. Squished bugs this created --- notes.md | 67 ++- src/collections/prompts/index.ts | 8 +- src/collections/prompts/prompt-getters.ts | 18 +- .../prompts/1909048.html | 525 ++++++++++++++++++ .../prompts/3583348.html | 351 ++++++++++++ tests/prompts.test.ts | 167 +++++- types/entities.ts | 3 +- 7 files changed, 1116 insertions(+), 23 deletions(-) create mode 100644 tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048.html create mode 100644 tests/mocks/data/collections/test_prompt_meme_2024/prompts/3583348.html diff --git a/notes.md b/notes.md index 83f19d5..a4486dc 100644 --- a/notes.md +++ b/notes.md @@ -1,22 +1,26 @@ -**creating a mock of a prompt** is a two-step process: +

Notes

-1. create the directory -2. download and add the prompt page with curl. +

Creating and Using Mocks

-curl https://archiveofourown.org/works/51394438/chapters/136175206 > tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428.html +Mocks are offline webpages that are used to test our scripts. -1. mkdir tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/ -2. curl https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428 > tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428.html +**To create a mock** you need to +1. create the directory +2. download and add the prompt page with curl. -actually... mkdir failed because it wouldn't create multiple levels of directory. huh. I had to do it twice with first the collection name, and then the prompts. - -A beter solution: curl --create-dirs --output tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806.html https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806 +``` +curl https://archiveofourown.org/works/51394438/chapters/136175206 > tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428.html +``` +This command will not work (1) if you are using Powershell, and (2) if the path does not yet exist. In order to use curl on Windows, open it in a git bash terminal. Powershell will do *something*, but not what we want it to. -! note: The result of curl may be different depending on your terminal and your OS. I use windows and had to open up a new "Git Bash" terminal. +To create the directory structure at the same time you use run curl, run this in the project's base directory: -curl info here: https://man.developpez.com/man1/curl/#:~:text=%2D%2Dcreate%2Ddirs%20When%20used,no%20dir%20will%20be%20created. +``` +curl --create-dirs --output tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806.html https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806 +``` +curl --create-dirs --output tests/mocks/data/collections/test_prompt_meme_2024/prompts/3583348.html https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3583348 --- @@ -107,15 +111,52 @@ In many languages, the convention for naming Booleans is typically to prefix the --- +I used this script to get tags from the prompt fills via the console. First, I needed to define $0 as a parent element. Then I put this into the console. + +```js +To get freeforms: +let q = $0 //on parent +w = [... q.querySelectorAll("li.characters a.tag")] +let ar = [] +w.forEach((e)=>{ar.push(e.innerText)}); +ar +``` + +--- + # Attribute Descriptions * **postedAt** The date the prompt was posted. * **summary**: The test description of the prompt, as html * **collectionDisplayTitle**: the title displayed on the collection pages and in tags. Not the same as collectionName, which is used to contruct the collection's url. -* **ratings**: a list of the requested ratings on the prompt. The prompt will display the highest of these on its UI. If the fic has no ratings, "Not Rated" will be returned. +* **ratings**: a list of the requested ratings on the prompt. The prompt will display the highest of these on its UI. If the prompt has no ratings, "Not Rated" will be returned. +* **claims**: [Object] information about people who have claimed the prompt. + * **anonymousClaims**: [number] the number of anon claims on the prompt. + * **knownClaimaints**: [string array] an array of people who have claimed the prompt. They are not pseuded, even if the user have signed up with a pseud. (This is a limitation on ao3's side.) ---- # TODO: 1. Query selectors need to be redone: Currently, they may pick up the prompt fills!! ... oh man, I need the prompt fills! -2. New, more thorough tests to test different types of prompts in their entirety: will fail most of the time. I'll have to see how the series-getter approaches the issue of multiple \ No newline at end of file + +2. As part of the query selector issue: More thorough tests to test different types of prompts in their entirety. The goal is not to have them pass immediately. I'll have to see how the series-getter approaches the issue of multiple works associated with a a request. + 1. Multiple known claimants + * ☑ [Mock created](/tests/mocks/data/collections/test_prompt_meme_2024/prompts/3583348.html) + * ☑ Test Created + * ☐ Test not Passed + 2. Multiple anon claimants + * ☑ [Mock Created](/tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048.html) + * ☑ Test Created (prompts.test.ts > describe("Fetches full Prompt") callback) + * ☐ Test not Passed + 3. Multiple fills + * ☑ [Mock Created - Same as Previous](/tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048.html) + * ☑ Test Created (prompts.test.ts > describe("Fetches full Prompt") callback) + * ☐ Test not Passed + +## Want tickboxes? +* U+2610 ☐ BALLOT BOX +* U+2611 ☑ BALLOT BOX WITH CHECK +* U+2612 ☒ BALLOT BOX WITH X + + +--- diff --git a/src/collections/prompts/index.ts b/src/collections/prompts/index.ts index f8326e6..e061f2c 100644 --- a/src/collections/prompts/index.ts +++ b/src/collections/prompts/index.ts @@ -13,7 +13,9 @@ import { getPromptAdditionalTags, getPromptCharacters, getPromptRelationships, - getPromptWarnings + getPromptWarnings, + getPromptAnonClaims, + getPromptKnownClaimaints } from "./prompt-getters" import {loadPromptPage} from "../../page-loaders" @@ -44,8 +46,8 @@ export const getPrompt = async ({ }, //TODO: claims: { - anonymousClaims: 12, - knownClaimaints: [{username: "TODO", pseud: "TODO2"}], + anonymousClaims: getPromptAnonClaims(promptPage), + knownClaimaints: getPromptKnownClaimaints(promptPage), }, title: "TODO", collectionName: "TODO", diff --git a/src/collections/prompts/prompt-getters.ts b/src/collections/prompts/prompt-getters.ts index 5c90b04..35aba3e 100644 --- a/src/collections/prompts/prompt-getters.ts +++ b/src/collections/prompts/prompt-getters.ts @@ -6,7 +6,7 @@ import { import { PromptPage } from "../../page-loaders"; export const getPostedAt = ($promptPage : PromptPage): string => { - const dateElement = $promptPage("p.datetime"); + const dateElement = $promptPage("p.datetime:first"); const date = dateElement.text(); return date; @@ -26,7 +26,8 @@ export const getCollectionDisplayTitle = ($promptPage : PromptPage): string => { } export const getPromptRatings = ($promptPage: PromptPage): WorkRatings[] => { - const ratingsString = $promptPage("ul.required-tags span.rating").text().trim(); + + const ratingsString = $promptPage("ul.required-tags:first span.rating").text().trim(); //if the work has no rating, the string gathered from the page will be "No rating" const hasRatings = !(ratingsString === "No rating"); const ratingsArray = ratingsString.split(', '); @@ -34,7 +35,10 @@ export const getPromptRatings = ($promptPage: PromptPage): WorkRatings[] => { if (hasRatings){ ratingsArray.forEach(rating => { if (!Object.values(WorkRatings).includes(rating as WorkRatings)) { + // console.log("working with cheerio") + // console.log($promptPage("ul.required-tags:first span.rating").text()); throw new Error("An unknown rating was found on the page: \""+ rating+"\""); + } }) } @@ -68,7 +72,7 @@ export const getPromptAuthor = ($promptPage: PromptPage): Author | "Anonymous"=> export const getPromptFandoms = ($promptPage: PromptPage): string[] => { const fandoms: string[] = []; - $promptPage("h5.fandoms.heading a.tag").each(function (i, element) { + $promptPage("h5.fandoms.heading:first a.tag").each(function (i, element) { fandoms[i] = $promptPage(element).text().trim(); }); return fandoms; @@ -112,4 +116,12 @@ export const getPromptRelationships = ($promptPage: PromptPage): string[] => { ships[i] = $promptPage(ship).text().trim(); }); return ships; +}; + +export const getPromptAnonClaims = ($promptPage: PromptPage): number => { + return 123456; +}; + +export const getPromptKnownClaimaints = ($promptPage: PromptPage): string[] => { + return ["TODO"]; }; \ No newline at end of file diff --git a/tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048.html b/tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048.html new file mode 100644 index 0000000..f32c6e8 --- /dev/null +++ b/tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048.html @@ -0,0 +1,525 @@ + + + + + + + + + + + + + + + Show + Prompt + | + Archive of Our Own + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + +
+ +
+

Dashboard

+ + +

Prompt Meme

+ +

Contents

+ +
+ + +
+
+ +

Request by Anonymous

+ + + + + + +
+
+ +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/mocks/data/collections/test_prompt_meme_2024/prompts/3583348.html b/tests/mocks/data/collections/test_prompt_meme_2024/prompts/3583348.html new file mode 100644 index 0000000..68c9898 --- /dev/null +++ b/tests/mocks/data/collections/test_prompt_meme_2024/prompts/3583348.html @@ -0,0 +1,351 @@ + + + + + + + + + + + + + + + Show + Prompt + | + Archive of Our Own + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + +
+ +
+

Dashboard

+ + +

Prompt Meme

+ +

Contents

+ +
+ + +
+
+ +

Request by Anonymous

+ + + + + + +
+
+ +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/prompts.test.ts b/tests/prompts.test.ts index d4f8050..8445e93 100644 --- a/tests/prompts.test.ts +++ b/tests/prompts.test.ts @@ -42,7 +42,7 @@ describe("Gets url from data", () => { describe("Fetches prompt information", () => { - test("Fetches prompt updated date", async () => { + test("Fetches prompt published date", async () => { const prompt = await getPrompt({ promptId: "2644428", collectionName: "mo_dao_zu_shi_kink_meme_2020" @@ -148,7 +148,6 @@ describe("Gets url from data", () => { url: "https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3573835", }) ); - expect(prompt).toMatchObject({ fandoms: ["SD Gundam G Generation Series (Video Games)", "Babel - R. F. Kuang"], tags: { @@ -158,8 +157,170 @@ describe("Gets url from data", () => { additional: ["Ewok Species (Star Wars)","FS Lobby Discord's GP Predictions Game","Natasha \"Phoenix\" Trace Needs a Hug"] } }); - }); + }); + + test("Fetches Anon Claims", async () => { + const prompt = await getPrompt( + await getPromptDetailsFromUrl({url: "https://https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048"}) + ); + expect(prompt).toMatchObject({ + claims: {anonymousClaims: 3}, + }); + }); + + test("Fetches Known Claimaints", async () => { + const prompt = await getPrompt( + await getPromptDetailsFromUrl({url: "https://https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3583348"}) + ); + expect(prompt).toMatchObject({ + claims: {knownClaimaints: ["RabbitPie","enigmalea"]}, + }); + }); + }); + + + describe("Fetches full Prompt", () => { + + test("Fetches multiple fills", async () => { + //https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048 + const prompt = await getPrompt({ + promptId: "1909048", + collectionName: "mo_dao_zu_shi_kink_meme_2020" + }); + + expect(prompt).toMatchObject({ + postedAt: '30 Nov 2020', + summary: "

Jin Guangyao reincarnates as a cockroach in the Cloud Recesses. Lan Xichen is still in seclusion and enjoys having a little bug friend. Up to you if he knows or just thinks the roach is A-Yao because of a marking or something, or if he doesn't know at all and is just being a friend to all animals. And lonely.

Bonus: Da-ge spiderbro.

DNW: Bugfucking, the whole thing being humor. Plz make this stone-cold crack treated seriously.

", + collectionDisplayTitle: "Mó Dào Zǔ Shī | The Untamed Kink Meme 2020", + categories: ["No Category"], + ratings: ["Not Rated"], + author: "Anonymous", + fandoms: ['陈情令 | The Untamed (TV)'], + + // tags: { + // warnings: ["Author Chose Not To Use Archive Warnings"], + // characters: [], + // relationships: ['Lan Huan | Lan Xichen/Meng Yao | Jin Guangyao'], + // additional: ['Crack Treated Seriously'], + // }, + // claims: { + // anonymousClaims: 3, + // knownClaimaints: [], + // }, + // title: "jgy reincarnates as a cockroach", + // collectionName: "mo_dao_zu_shi_kink_meme_2020", + // id: "1909048", + // filled: true, + // fills: [ + // {//Fill 1 + // id: "29946057", + // title: "Exoskeletons In My Closet", + // category: "Gen", + // updatedAt: "19 Nov 2021", + // summary: "

After dying, the last thing Jin Guangyao expected was to wake up again.

Finding himself reincarnated in the Cloud Recesses is a bit of a shock; particularly given the fact that he's in the perfect position to witness the exact effects the fallout of his bad choices have on the only true friend he ever had. Struck by guilt, he's determined to do right for once, and find a way to make things better for Lan Xichen.

A task which is significantly complicated by the fact that he wasn't actually reborn as a human. Instead he's… a cockroach?!

Can Jin Guangyao help Lan Xichen, despite being roach-ified?

(…And why on earth does it look like that big, hairy spider glowering at him from the corner across the Hanshi is trying to sharpen a tiny stick into a sabre?)

", + // rating: "General Audiences", + // adult: false, + // fandoms: ["魔道祖师 - 墨香铜臭 | Módào Zǔshī - Mòxiāng Tóngxiù, 魔道祖师 | Módào Zǔshī (Cartoon)", "陈情令 | The Untamed (TV)"], + + + // tags: { + // warnings: ["No Archive Warnings Apply"], + // characters: ['Meng Yao | Jin Guangyao','Lan Huan | Lan Xichen','Nie Mingjue'], + // relationships: ["Lán Huàn | Lán Xīchén & Mèng Yáo | Jīn Guāngyáo", "Meng Yao | Jin Guangyao & Nie Mingjue"], + // additional:['Reincarnation', 'Cockroaches', 'Spiders', 'Bugs & Insects', 'Crack Treated Seriously', 'Rebirth', 'Redemption', 'Mèng Yáo | Jīn Guāngyáo Redemption', 'Da-ge Spider-Bro', 'JGY is a Cockroach', 'Protective Niè Míngjué', 'Oblivious Lán Huàn | Lán Xīchén', 'Lán Huàn | Lán Xīchén in Seclusion', "Niè Míngjué Is Lán Xīchén's Self-Appointed Guard Spider", "Jīn Guāngyáo's Life Is Hard", 'Being A Cockroach Is Surprisingly Dangerous'], + // }, + // authors: [{username: "DeiStarr", pseud: "DeiStarr"}], + // language: "English", + // words: 4386, + // chapters: { + // published: 7, + // total: 17, + // }, + // series: [ + // { + // id: "1928872", + // index: 28, + // name: "MDZS Kink Meme 2020 Prompt Fills" + // } + // ], + // complete: false, + // stats: { + // bookmarks: 45, + // comments: 62, + // kudos: 181, + // hits: 2320, + // }, + // }, + // { + // id: "29946057", + // title: "Exoskeletons In My Closet", + // category: ["Gen"], + // publishedAt: "19 Nov 2021", + // summary: "

After dying, the last thing Jin Guangyao expected was to wake up again.

Finding himself reincarnated in the Cloud Recesses is a bit of a shock; particularly given the fact that he's in the perfect position to witness the exact effects the fallout of his bad choices have on the only true friend he ever had. Struck by guilt, he's determined to do right for once, and find a way to make things better for Lan Xichen.

A task which is significantly complicated by the fact that he wasn't actually reborn as a human. Instead he's… a cockroach?!

Can Jin Guangyao help Lan Xichen, despite being roach-ified?

(…And why on earth does it look like that big, hairy spider glowering at him from the corner across the Hanshi is trying to sharpen a tiny stick into a sabre?)

", + // rating: "General Audiences", + // adult: false, + // fandoms: ["陈情令 | The Untamed (TV)"], + // tags: { + // warnings: ["No Archive Warnings Apply"], + // characters: ["Lan Huan | Lan Xichen","Meng Yao | Jin GuangyaoNie", "Mingjue"], + // relationships: ["3ZUN","Lan Huan | Lan Xichen/Meng Yao | Jin Guangyao/Nie Mingjue"], + // additional: ['Mourning', 'Reincarnation', 'lxc/jgy/nmj (past)', 'Crack Treated Seriously'], + // }, + // authors: [{username: "Xygenscenic", pseud: "Xygenscenic"}], + // language: "English", + // words: 3018, + // chapters: { + // published: 1, + // total: 1, + // }, + // series: [], + // complete: true, + // stats: { + // bookmarks: 3, + // comments: 13, + // kudos: 29, + // hits: 318, + // }, + // }, + // { + // id: "31040711", + // title: "Bugyao and Xichen", + // category: "M/M", + // publishedAt: "02 May 2021", + // summary: '

Even reincarnated as a tiny bug, Er-Ge will love and care for his A-Yao and give him the best life possible.

', + // rating: "Not Rated", + // adult: true, + // fandoms: "陈情令 | The Untamed (TV)", + // tags: { + // warnings: ["Creator Chose Not To Use Archive Warnings"], + // characters: ['Lan Huan | Lan Xichen', 'Meng Yao | Jin Guangyao'], + // relationships: ['Lan XiChen/Jin GuangYao'], + // additional: ['Fanart'], + // }, + // authors: "Anonymous", + // language: "English", + // words: 0, + // chapters: { + // published: 1, + // total: 1, + // }, + // series: [], + // complete: true, + // stats: { + // bookmarks: 5, + // comments: 6, + // kudos: 70, + // hits: 582, + // }, + // } + // ], + + + }); + }); + + }); \ No newline at end of file diff --git a/types/entities.ts b/types/entities.ts index 1e1a240..803eded 100644 --- a/types/entities.ts +++ b/types/entities.ts @@ -197,9 +197,10 @@ export interface Prompt { relationships: string[]; additional: string[]; }; + // claimaints do not have pseuds as Ao3 is currently set up claims: { anonymousClaims: number; - knownClaimaints: Author[]; + knownClaimaints: string[]; } title: string; collectionName: string; From e9c5ebfd01f210774432550cf0a9391e30d3b6c4 Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Mon, 4 Mar 2024 16:19:39 +1030 Subject: [PATCH 25/31] restructured Prompt claims, rewrote and passed tests, added test for 0 claims --- notes.md | 33 ++++++++++----------- src/collections/prompts/index.ts | 8 ++---- src/collections/prompts/prompt-getters.ts | 35 ++++++++++++++++++----- tests/prompts.test.ts | 23 +++++++++------ types/entities.ts | 12 ++++---- 5 files changed, 69 insertions(+), 42 deletions(-) diff --git a/notes.md b/notes.md index a4486dc..98c1b57 100644 --- a/notes.md +++ b/notes.md @@ -130,9 +130,10 @@ ar * **summary**: The test description of the prompt, as html * **collectionDisplayTitle**: the title displayed on the collection pages and in tags. Not the same as collectionName, which is used to contruct the collection's url. * **ratings**: a list of the requested ratings on the prompt. The prompt will display the highest of these on its UI. If the prompt has no ratings, "Not Rated" will be returned. -* **claims**: [Object] information about people who have claimed the prompt. - * **anonymousClaims**: [number] the number of anon claims on the prompt. - * **knownClaimaints**: [string array] an array of people who have claimed the prompt. They are not pseuded, even if the user have signed up with a pseud. (This is a limitation on ao3's side.) +* **claims**: [Object] claims exist when users have "claimed" a prompt, but not yet filled it. Claims can have these structures: + * `{count: 0}` There are no claims. We don't know if the collection is anonymous or not. + * `{count: number; isAnonCollection: true; }` There is a non-zero amount of anonymous claims. + * `{count: number; isAnonCollection: false; claimerUsernames: string[]}` There is a non-zero amount of claimers, and the collection isn't anonymous, and you can return an array of strings containing their **usernames** not pseuds; (it's unknown if they have pseuds). ---- @@ -141,22 +142,22 @@ ar 2. As part of the query selector issue: More thorough tests to test different types of prompts in their entirety. The goal is not to have them pass immediately. I'll have to see how the series-getter approaches the issue of multiple works associated with a a request. 1. Multiple known claimants - * ☑ [Mock created](/tests/mocks/data/collections/test_prompt_meme_2024/prompts/3583348.html) - * ☑ Test Created - * ☐ Test not Passed + * ✅ [Mock created](/tests/mocks/data/collections/test_prompt_meme_2024/prompts/3583348.html) + * ✅ Test Created + * 🟡 Test not Passed 2. Multiple anon claimants - * ☑ [Mock Created](/tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048.html) - * ☑ Test Created (prompts.test.ts > describe("Fetches full Prompt") callback) - * ☐ Test not Passed + * ✅ [Mock Created](/tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048.html) + * ✅ Test Created (prompts.test.ts > describe("Fetches full Prompt") callback) + * 🟡 Test not Passed 3. Multiple fills - * ☑ [Mock Created - Same as Previous](/tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048.html) - * ☑ Test Created (prompts.test.ts > describe("Fetches full Prompt") callback) - * ☐ Test not Passed + * ✅ [Mock Created - Same as Previous](/tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048.html) + * ✅ Test Created (prompts.test.ts > describe("Fetches full Prompt") callback) + * 🟡 Test not Passed -## Want tickboxes? -* U+2610 ☐ BALLOT BOX -* U+2611 ☑ BALLOT BOX WITH CHECK -* U+2612 ☒ BALLOT BOX WITH X +✅ Task Complete +🟡 Task Incomplete or not started --- + + diff --git a/src/collections/prompts/index.ts b/src/collections/prompts/index.ts index e061f2c..88fa89e 100644 --- a/src/collections/prompts/index.ts +++ b/src/collections/prompts/index.ts @@ -14,8 +14,7 @@ import { getPromptCharacters, getPromptRelationships, getPromptWarnings, - getPromptAnonClaims, - getPromptKnownClaimaints + getPromptClaims } from "./prompt-getters" import {loadPromptPage} from "../../page-loaders" @@ -45,10 +44,7 @@ export const getPrompt = async ({ additional: getPromptAdditionalTags(promptPage) }, //TODO: - claims: { - anonymousClaims: getPromptAnonClaims(promptPage), - knownClaimaints: getPromptKnownClaimaints(promptPage), - }, + claims: getPromptClaims(promptPage), title: "TODO", collectionName: "TODO", id: "TODO", diff --git a/src/collections/prompts/prompt-getters.ts b/src/collections/prompts/prompt-getters.ts index 35aba3e..e9a1fba 100644 --- a/src/collections/prompts/prompt-getters.ts +++ b/src/collections/prompts/prompt-getters.ts @@ -1,7 +1,8 @@ import { Author, WorkRatings, - WorkWarnings + WorkWarnings, + Prompt } from "types/entities" import { PromptPage } from "../../page-loaders"; @@ -118,10 +119,30 @@ export const getPromptRelationships = ($promptPage: PromptPage): string[] => { return ships; }; -export const getPromptAnonClaims = ($promptPage: PromptPage): number => { - return 123456; -}; +export const getPromptClaims = ($promptPage: PromptPage): Prompt["claims"] => { + const claimNodesText = $promptPage(".commas.index.group").text().trim(); + + //There are no claims + if(claimNodesText === "") return {count: 0} as Prompt["claims"]; + + const regexAnonCount = /([^ ]*) anonymous/g + const captures = regexAnonCount.exec(claimNodesText); + + if (!captures) { + //No anon claims. Get known claims: + const claimants:string[] = []; + + const lis = $promptPage("div.claims li").each(function (i, element) { + claimants[i] = $promptPage(element).text().trim(); + }); + + if(lis.length === 0) throw new Error("Could not process Claimants"); + return {count: lis.length, isAnonCollection: false, claimantUsernames: claimants} as Prompt["claims"]; + }; + + //There are anonymous claimes + const anonCount = Number(captures[1].replace(/,/g, "")); + if (Number.isNaN(anonCount)) throw new Error("Error processing prompt anonymous claim count: NaN"); -export const getPromptKnownClaimaints = ($promptPage: PromptPage): string[] => { - return ["TODO"]; -}; \ No newline at end of file + return {count: anonCount, isAnonCollection: true} as Prompt["claims"]; +} \ No newline at end of file diff --git a/tests/prompts.test.ts b/tests/prompts.test.ts index 8445e93..7728df3 100644 --- a/tests/prompts.test.ts +++ b/tests/prompts.test.ts @@ -159,21 +159,31 @@ describe("Gets url from data", () => { }); }); - test("Fetches Anon Claims", async () => { + + test("Fetches 0 claims", async () => { + const prompt = await getPrompt( + await getPromptDetailsFromUrl({url: "https://https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3573835"}) + ); + expect(prompt).toMatchObject({ + claims: {count: 0}, + }); + }); + + test("Fetches Anon Claims + No Known Claimaints", async () => { const prompt = await getPrompt( await getPromptDetailsFromUrl({url: "https://https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048"}) ); expect(prompt).toMatchObject({ - claims: {anonymousClaims: 3}, + claims: {count: 3, isAnonCollection: true}, }); }); - test("Fetches Known Claimaints", async () => { + test("Fetches Known Claimaints+No Anon Claimaints", async () => { const prompt = await getPrompt( await getPromptDetailsFromUrl({url: "https://https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3583348"}) ); expect(prompt).toMatchObject({ - claims: {knownClaimaints: ["RabbitPie","enigmalea"]}, + claims: {count: 2, isAnonCollection: false, claimantUsernames:["RabbitPie","enigmalea"]}, }); }); @@ -207,10 +217,7 @@ describe("Gets url from data", () => { // relationships: ['Lan Huan | Lan Xichen/Meng Yao | Jin Guangyao'], // additional: ['Crack Treated Seriously'], // }, - // claims: { - // anonymousClaims: 3, - // knownClaimaints: [], - // }, + // claims: {count: 3, isAnonCollection: true;}, // title: "jgy reincarnates as a cockroach", // collectionName: "mo_dao_zu_shi_kink_meme_2020", // id: "1909048", diff --git a/types/entities.ts b/types/entities.ts index 803eded..a3438e2 100644 --- a/types/entities.ts +++ b/types/entities.ts @@ -197,11 +197,13 @@ export interface Prompt { relationships: string[]; additional: string[]; }; - // claimaints do not have pseuds as Ao3 is currently set up - claims: { - anonymousClaims: number; - knownClaimaints: string[]; - } + // Ao3 does not show pseuds in claimant lists, only usernames. + // whether claims are anon or not is dependant on collection's "anonymous collection" setting. + // see https://github.com/otwcode/otwarchive/blob/master/app/views/prompts/_prompt_blurb.html.erb and https://github.com/otwcode/otwarchive/blob/759b21eb45ae6eda5a0c1fd8451928f6b41033a1/app/models/collection.rb + claims: + {count: 0;} + | {count: number; isAnonCollection: true;} + | {count: number; isAnonCollection: false; claimantUsernames: string[];}; title: string; collectionName: string; id: string; From 478f87c898bea90ec23acfe91d5f95fce0f873e4 Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Tue, 5 Mar 2024 12:38:50 +1030 Subject: [PATCH 26/31] (untested) created tests for categories --- notes.md | 33 ++++++++++------- src/collections/prompts/index.ts | 5 +-- src/collections/prompts/prompt-getters.ts | 8 +++++ tests/prompts.test.ts | 43 +++++++++++++++++++---- types/entities.ts | 8 +++-- 5 files changed, 74 insertions(+), 23 deletions(-) diff --git a/notes.md b/notes.md index 98c1b57..07517ca 100644 --- a/notes.md +++ b/notes.md @@ -130,34 +130,43 @@ ar * **summary**: The test description of the prompt, as html * **collectionDisplayTitle**: the title displayed on the collection pages and in tags. Not the same as collectionName, which is used to contruct the collection's url. * **ratings**: a list of the requested ratings on the prompt. The prompt will display the highest of these on its UI. If the prompt has no ratings, "Not Rated" will be returned. -* **claims**: [Object] claims exist when users have "claimed" a prompt, but not yet filled it. Claims can have these structures: +* **claims**: [Object] claims exist when users have "claimed" a prompt, but not yet filled it. Claims can have three different types of structres. To check if a variable exists, you can check the variable it depends on (eg. check `count > 0 before` accessing isAnonCollection and `inAnonCollection === false` before accessing claimerUsernames), or use `if "isAnonCollection" in variable`. * `{count: 0}` There are no claims. We don't know if the collection is anonymous or not. * `{count: number; isAnonCollection: true; }` There is a non-zero amount of anonymous claims. * `{count: number; isAnonCollection: false; claimerUsernames: string[]}` There is a non-zero amount of claimers, and the collection isn't anonymous, and you can return an array of strings containing their **usernames** not pseuds; (it's unknown if they have pseuds). - ----- +* **categories**: `null | string[]`
+null if no categories are selected, or an array of strings (WorkCategory objects).
# TODO: -1. Query selectors need to be redone: Currently, they may pick up the prompt fills!! ... oh man, I need the prompt fills! -2. As part of the query selector issue: More thorough tests to test different types of prompts in their entirety. The goal is not to have them pass immediately. I'll have to see how the series-getter approaches the issue of multiple works associated with a a request. +* 🟡 Get Categories + * ✅ Establish Category structure + * 🟡 Create test for no categories + * 🟡 Create test for one category + * 🟡 Create test for multiple categories + * 🟡 Pass tests + +in Fandom Coders, the idea of returning `null` if there are no warnings was brought up. However, I (RabbitPie) am not sure which variable would be considered "no warnings"? No Archive Warnings apply? "Author chose not to use archive warnings"? + +✅ Task Complete +🟡 Task Incomplete or not started + +# Done: + +1. As part of the query selector issue: More thorough tests to test different types of prompts in their entirety. The goal is not to have them pass immediately. I'll have to see how the series-getter approaches the issue of multiple works associated with a a request. 1. Multiple known claimants * ✅ [Mock created](/tests/mocks/data/collections/test_prompt_meme_2024/prompts/3583348.html) * ✅ Test Created - * 🟡 Test not Passed + * ✅ Test Passed 2. Multiple anon claimants * ✅ [Mock Created](/tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048.html) * ✅ Test Created (prompts.test.ts > describe("Fetches full Prompt") callback) - * 🟡 Test not Passed + * ✅ Test Passed 3. Multiple fills * ✅ [Mock Created - Same as Previous](/tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048.html) * ✅ Test Created (prompts.test.ts > describe("Fetches full Prompt") callback) - * 🟡 Test not Passed - + * ✅ Test Passed -✅ Task Complete -🟡 Task Incomplete or not started ---- diff --git a/src/collections/prompts/index.ts b/src/collections/prompts/index.ts index 88fa89e..44daf0c 100644 --- a/src/collections/prompts/index.ts +++ b/src/collections/prompts/index.ts @@ -14,7 +14,8 @@ import { getPromptCharacters, getPromptRelationships, getPromptWarnings, - getPromptClaims + getPromptClaims, + getPromptCategories } from "./prompt-getters" import {loadPromptPage} from "../../page-loaders" @@ -50,7 +51,7 @@ export const getPrompt = async ({ id: "TODO", filled: true, fills: [], - categories: [] + categories: getPromptCategories(promptPage) } } \ No newline at end of file diff --git a/src/collections/prompts/prompt-getters.ts b/src/collections/prompts/prompt-getters.ts index e9a1fba..9b50b43 100644 --- a/src/collections/prompts/prompt-getters.ts +++ b/src/collections/prompts/prompt-getters.ts @@ -145,4 +145,12 @@ export const getPromptClaims = ($promptPage: PromptPage): Prompt["claims"] => { if (Number.isNaN(anonCount)) throw new Error("Error processing prompt anonymous claim count: NaN"); return {count: anonCount, isAnonCollection: true} as Prompt["claims"]; +} + +export const getPromptCategories = ($promptPage: PromptPage): Prompt["categories"] => { + + + + + return [] } \ No newline at end of file diff --git a/tests/prompts.test.ts b/tests/prompts.test.ts index 7728df3..f84f3c1 100644 --- a/tests/prompts.test.ts +++ b/tests/prompts.test.ts @@ -162,7 +162,7 @@ describe("Gets url from data", () => { test("Fetches 0 claims", async () => { const prompt = await getPrompt( - await getPromptDetailsFromUrl({url: "https://https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3573835"}) + await getPromptDetailsFromUrl({url: "https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3573835"}) ); expect(prompt).toMatchObject({ claims: {count: 0}, @@ -171,7 +171,7 @@ describe("Gets url from data", () => { test("Fetches Anon Claims + No Known Claimaints", async () => { const prompt = await getPrompt( - await getPromptDetailsFromUrl({url: "https://https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048"}) + await getPromptDetailsFromUrl({url: "https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048"}) ); expect(prompt).toMatchObject({ claims: {count: 3, isAnonCollection: true}, @@ -180,7 +180,7 @@ describe("Gets url from data", () => { test("Fetches Known Claimaints+No Anon Claimaints", async () => { const prompt = await getPrompt( - await getPromptDetailsFromUrl({url: "https://https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3583348"}) + await getPromptDetailsFromUrl({url: "https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3583348"}) ); expect(prompt).toMatchObject({ claims: {count: 2, isAnonCollection: false, claimantUsernames:["RabbitPie","enigmalea"]}, @@ -188,6 +188,35 @@ describe("Gets url from data", () => { }); + //WIP PROMPTS + test("Fetches Prompt Categores (multiple)", async () => { + const prompt = await getPrompt( + await getPromptDetailsFromUrl({url: "https://www.archiveofourown.org/collections/test_prompt_meme_2024/prompts/3573835"}) + ); + expect(prompt).toMatchObject({ + categories: ["M/M", "Other"], + }); + }); + + test("Fetches Prompt Categores (single)", async () => { + const prompt = await getPrompt( + await getPromptDetailsFromUrl({url: "https://www.archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806"}) + ); + expect(prompt).toMatchObject({ + categories: ["Gen"], + }); + }); + + test("Fetches Prompt Categores (0 as null)", async () => { + const prompt = await getPrompt( + await getPromptDetailsFromUrl({url: "http://www.archiveofourown.org/collections/test_prompt_meme_2024/prompts/3583348"}) + ); + expect(prompt).toMatchObject({ + categories: null, + }); + }); + + }); @@ -206,7 +235,7 @@ describe("Gets url from data", () => { postedAt: '30 Nov 2020', summary: "

Jin Guangyao reincarnates as a cockroach in the Cloud Recesses. Lan Xichen is still in seclusion and enjoys having a little bug friend. Up to you if he knows or just thinks the roach is A-Yao because of a marking or something, or if he doesn't know at all and is just being a friend to all animals. And lonely.

Bonus: Da-ge spiderbro.

DNW: Bugfucking, the whole thing being humor. Plz make this stone-cold crack treated seriously.

", collectionDisplayTitle: "Mó Dào Zǔ Shī | The Untamed Kink Meme 2020", - categories: ["No Category"], + categories: null, ratings: ["Not Rated"], author: "Anonymous", fandoms: ['陈情令 | The Untamed (TV)'], @@ -226,7 +255,7 @@ describe("Gets url from data", () => { // {//Fill 1 // id: "29946057", // title: "Exoskeletons In My Closet", - // category: "Gen", + // categories: "Gen", // updatedAt: "19 Nov 2021", // summary: "

After dying, the last thing Jin Guangyao expected was to wake up again.

Finding himself reincarnated in the Cloud Recesses is a bit of a shock; particularly given the fact that he's in the perfect position to witness the exact effects the fallout of his bad choices have on the only true friend he ever had. Struck by guilt, he's determined to do right for once, and find a way to make things better for Lan Xichen.

A task which is significantly complicated by the fact that he wasn't actually reborn as a human. Instead he's… a cockroach?!

Can Jin Guangyao help Lan Xichen, despite being roach-ified?

(…And why on earth does it look like that big, hairy spider glowering at him from the corner across the Hanshi is trying to sharpen a tiny stick into a sabre?)

", // rating: "General Audiences", @@ -265,7 +294,7 @@ describe("Gets url from data", () => { // { // id: "29946057", // title: "Exoskeletons In My Closet", - // category: ["Gen"], + // categories: ["Gen"], // publishedAt: "19 Nov 2021", // summary: "

After dying, the last thing Jin Guangyao expected was to wake up again.

Finding himself reincarnated in the Cloud Recesses is a bit of a shock; particularly given the fact that he's in the perfect position to witness the exact effects the fallout of his bad choices have on the only true friend he ever had. Struck by guilt, he's determined to do right for once, and find a way to make things better for Lan Xichen.

A task which is significantly complicated by the fact that he wasn't actually reborn as a human. Instead he's… a cockroach?!

Can Jin Guangyao help Lan Xichen, despite being roach-ified?

(…And why on earth does it look like that big, hairy spider glowering at him from the corner across the Hanshi is trying to sharpen a tiny stick into a sabre?)

", // rating: "General Audiences", @@ -296,7 +325,7 @@ describe("Gets url from data", () => { // { // id: "31040711", // title: "Bugyao and Xichen", - // category: "M/M", + // categories: "M/M", // publishedAt: "02 May 2021", // summary: '

Even reincarnated as a tiny bug, Er-Ge will love and care for his A-Yao and give him the best life possible.

', // rating: "Not Rated", diff --git a/types/entities.ts b/types/entities.ts index a3438e2..85f7994 100644 --- a/types/entities.ts +++ b/types/entities.ts @@ -200,6 +200,10 @@ export interface Prompt { // Ao3 does not show pseuds in claimant lists, only usernames. // whether claims are anon or not is dependant on collection's "anonymous collection" setting. // see https://github.com/otwcode/otwarchive/blob/master/app/views/prompts/_prompt_blurb.html.erb and https://github.com/otwcode/otwarchive/blob/759b21eb45ae6eda5a0c1fd8451928f6b41033a1/app/models/collection.rb + + //proposed alternation: + // null + // | {count: number, usernames: string[] | null} claims: {count: 0;} | {count: number; isAnonCollection: true;} @@ -208,6 +212,6 @@ export interface Prompt { collectionName: string; id: string; filled: boolean; - fills: PromptFillSummary[]; - categories: WorkCategory[]; + fills: PromptFillSummary[]|null; + categories: WorkCategory[] | null; } \ No newline at end of file From 0cba4c3a3213ee8f2e4b803fd001a453b2b05db8 Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Tue, 5 Mar 2024 13:34:35 +1030 Subject: [PATCH 27/31] added test for prompt categories + multiple fills --- notes.md | 7 ++++--- tests/prompts.test.ts | 26 +++++++++++++------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/notes.md b/notes.md index 07517ca..b84b442 100644 --- a/notes.md +++ b/notes.md @@ -141,9 +141,10 @@ null if no categories are selected, or an array of strings (WorkCategory objects * 🟡 Get Categories * ✅ Establish Category structure - * 🟡 Create test for no categories - * 🟡 Create test for one category - * 🟡 Create test for multiple categories + * ✅ Create test for no categories + * ✅ Create test for one category + * ✅ Create test for multiple categories + * ✅ Create test for multiple fills * 🟡 Pass tests in Fandom Coders, the idea of returning `null` if there are no warnings was brought up. However, I (RabbitPie) am not sure which variable would be considered "no warnings"? No Archive Warnings apply? "Author chose not to use archive warnings"? diff --git a/tests/prompts.test.ts b/tests/prompts.test.ts index f84f3c1..3ab72bb 100644 --- a/tests/prompts.test.ts +++ b/tests/prompts.test.ts @@ -207,9 +207,9 @@ describe("Gets url from data", () => { }); }); - test("Fetches Prompt Categores (0 as null)", async () => { + test("Fetches Prompt Categores (0 as null) with multiple fills", async () => { const prompt = await getPrompt( - await getPromptDetailsFromUrl({url: "http://www.archiveofourown.org/collections/test_prompt_meme_2024/prompts/3583348"}) + await getPromptDetailsFromUrl({url: "http://www.archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048"}) ); expect(prompt).toMatchObject({ categories: null, @@ -240,17 +240,17 @@ describe("Gets url from data", () => { author: "Anonymous", fandoms: ['陈情令 | The Untamed (TV)'], - // tags: { - // warnings: ["Author Chose Not To Use Archive Warnings"], - // characters: [], - // relationships: ['Lan Huan | Lan Xichen/Meng Yao | Jin Guangyao'], - // additional: ['Crack Treated Seriously'], - // }, - // claims: {count: 3, isAnonCollection: true;}, - // title: "jgy reincarnates as a cockroach", - // collectionName: "mo_dao_zu_shi_kink_meme_2020", - // id: "1909048", - // filled: true, + tags: { + warnings: ["Author Chose Not To Use Archive Warnings"], + characters: [], + relationships: ['Lan Huan | Lan Xichen/Meng Yao | Jin Guangyao'], + additional: ['Crack Treated Seriously'], + }, + claims: {count: 3, isAnonCollection: true;}, + title: "jgy reincarnates as a cockroach", + collectionName: "mo_dao_zu_shi_kink_meme_2020", + id: "1909048", + filled: true, // fills: [ // {//Fill 1 // id: "29946057", From 42294d19c619417c9f374db4e9318e7e0cb849a4 Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Tue, 5 Mar 2024 13:37:35 +1030 Subject: [PATCH 28/31] get categories passes tests --- notes.md | 4 ++-- src/collections/prompts/prompt-getters.ts | 9 ++++++--- tests/prompts.test.ts | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/notes.md b/notes.md index b84b442..e2e5ff6 100644 --- a/notes.md +++ b/notes.md @@ -139,13 +139,13 @@ null if no categories are selected, or an array of strings (WorkCategory objects # TODO: -* 🟡 Get Categories +* ✅ Get Categories * ✅ Establish Category structure * ✅ Create test for no categories * ✅ Create test for one category * ✅ Create test for multiple categories * ✅ Create test for multiple fills - * 🟡 Pass tests + * ✅ Pass tests in Fandom Coders, the idea of returning `null` if there are no warnings was brought up. However, I (RabbitPie) am not sure which variable would be considered "no warnings"? No Archive Warnings apply? "Author chose not to use archive warnings"? diff --git a/src/collections/prompts/prompt-getters.ts b/src/collections/prompts/prompt-getters.ts index 9b50b43..b1b358c 100644 --- a/src/collections/prompts/prompt-getters.ts +++ b/src/collections/prompts/prompt-getters.ts @@ -2,7 +2,8 @@ import { Author, WorkRatings, WorkWarnings, - Prompt + Prompt, + WorkCategory } from "types/entities" import { PromptPage } from "../../page-loaders"; @@ -148,9 +149,11 @@ export const getPromptClaims = ($promptPage: PromptPage): Prompt["claims"] => { } export const getPromptCategories = ($promptPage: PromptPage): Prompt["categories"] => { + const categoriesString = $promptPage("span.category:first span.text").text().trim(); + if (categoriesString === "No category") return null; + const categories = categoriesString.split(", ") - - return [] + return categories as WorkCategory[]; } \ No newline at end of file diff --git a/tests/prompts.test.ts b/tests/prompts.test.ts index 3ab72bb..ce22d22 100644 --- a/tests/prompts.test.ts +++ b/tests/prompts.test.ts @@ -246,7 +246,7 @@ describe("Gets url from data", () => { relationships: ['Lan Huan | Lan Xichen/Meng Yao | Jin Guangyao'], additional: ['Crack Treated Seriously'], }, - claims: {count: 3, isAnonCollection: true;}, + claims: {count: 3, isAnonCollection: true}, title: "jgy reincarnates as a cockroach", collectionName: "mo_dao_zu_shi_kink_meme_2020", id: "1909048", From ae8edb5746d5036044e83f7b72dde8f2844cf2c1 Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Wed, 6 Mar 2024 16:52:04 +1030 Subject: [PATCH 29/31] fetches prompt id and collectionName --- notes.md | 23 ++++++++++++++++------- src/collections/prompts/index.ts | 4 ++-- tests/prompts.test.ts | 15 +++++++++++++++ types/entities.ts | 2 +- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/notes.md b/notes.md index e2e5ff6..610dc3e 100644 --- a/notes.md +++ b/notes.md @@ -139,13 +139,15 @@ null if no categories are selected, or an array of strings (WorkCategory objects # TODO: -* ✅ Get Categories - * ✅ Establish Category structure - * ✅ Create test for no categories - * ✅ Create test for one category - * ✅ Create test for multiple categories - * ✅ Create test for multiple fills - * ✅ Pass tests +* ✅ Get collectionName +* ✅ get collection id +* 🟡 Get additional tags from prompts with multiple fills +* 🟡 Get character tags from prompts with multiple fills +* 🟡 Get warning tags from prompts with multiple fills +* 🟡 get prompt title (anon and not anon author, title and no title prompt meme) +* 🟡 get works +* 🟡 reimplement claims, possibly as `claims: { count: number, usernames: string[] | null } | null;` + in Fandom Coders, the idea of returning `null` if there are no warnings was brought up. However, I (RabbitPie) am not sure which variable would be considered "no warnings"? No Archive Warnings apply? "Author chose not to use archive warnings"? @@ -168,6 +170,13 @@ in Fandom Coders, the idea of returning `null` if there are no warnings was brou * ✅ Test Created (prompts.test.ts > describe("Fetches full Prompt") callback) * ✅ Test Passed +* ✅ Get Categories + * ✅ Establish Category structure + * ✅ Create test for no categories + * ✅ Create test for one category + * ✅ Create test for multiple categories + * ✅ Create test for multiple fills + * ✅ Pass tests diff --git a/src/collections/prompts/index.ts b/src/collections/prompts/index.ts index 44daf0c..3043d94 100644 --- a/src/collections/prompts/index.ts +++ b/src/collections/prompts/index.ts @@ -47,8 +47,8 @@ export const getPrompt = async ({ //TODO: claims: getPromptClaims(promptPage), title: "TODO", - collectionName: "TODO", - id: "TODO", + collectionName: collectionName, + id: promptId, filled: true, fills: [], categories: getPromptCategories(promptPage) diff --git a/tests/prompts.test.ts b/tests/prompts.test.ts index ce22d22..28bb590 100644 --- a/tests/prompts.test.ts +++ b/tests/prompts.test.ts @@ -216,12 +216,27 @@ describe("Gets url from data", () => { }); }); + test("Fetches collectionName & PromptID", async () => { + const prompt = await getPrompt( + await getPromptDetailsFromUrl({url: "http://www.archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048"}) + ); + expect(prompt).toMatchObject({ + collectionName: "mo_dao_zu_shi_kink_meme_2020", + id: "1909048" + }); + }); }); + + + + + + describe("Fetches full Prompt", () => { test("Fetches multiple fills", async () => { diff --git a/types/entities.ts b/types/entities.ts index 85f7994..1c3236b 100644 --- a/types/entities.ts +++ b/types/entities.ts @@ -199,7 +199,7 @@ export interface Prompt { }; // Ao3 does not show pseuds in claimant lists, only usernames. // whether claims are anon or not is dependant on collection's "anonymous collection" setting. - // see https://github.com/otwcode/otwarchive/blob/master/app/views/prompts/_prompt_blurb.html.erb and https://github.com/otwcode/otwarchive/blob/759b21eb45ae6eda5a0c1fd8451928f6b41033a1/app/models/collection.rb + // see https://github.com/otwcode/otwarchive/blob/master/app/views/prompts/_prompt_blurb.html.erb and https://github.com/otwcode/otwarchive/blob/app/models/collection.rb //proposed alternation: // null From 4189922a982d2346d4a9d74ace3e98c488833c8a Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Wed, 6 Mar 2024 18:23:09 +1030 Subject: [PATCH 30/31] updated get tags for multiple fills --- notes.md | 14 ++++---- src/collections/prompts/prompt-getters.ts | 9 +++--- tests/prompts.test.ts | 39 ++++++++++++++++++----- 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/notes.md b/notes.md index 610dc3e..319d9f6 100644 --- a/notes.md +++ b/notes.md @@ -139,11 +139,12 @@ null if no categories are selected, or an array of strings (WorkCategory objects # TODO: -* ✅ Get collectionName -* ✅ get collection id -* 🟡 Get additional tags from prompts with multiple fills -* 🟡 Get character tags from prompts with multiple fills -* 🟡 Get warning tags from prompts with multiple fills +Questions: +* Do we want characters, additional and ship tags to return a null if there are no tags in that category? + +* ✅ Get additional tags from prompts with multiple fills +* ✅ Get character tags from prompts with multiple fills +* ✅ Get warning tags from prompts with multiple fills * 🟡 get prompt title (anon and not anon author, title and no title prompt meme) * 🟡 get works * 🟡 reimplement claims, possibly as `claims: { count: number, usernames: string[] | null } | null;` @@ -177,6 +178,7 @@ in Fandom Coders, the idea of returning `null` if there are no warnings was brou * ✅ Create test for multiple categories * ✅ Create test for multiple fills * ✅ Pass tests - +* ✅ Get collectionName +* ✅ get collection id diff --git a/src/collections/prompts/prompt-getters.ts b/src/collections/prompts/prompt-getters.ts index b1b358c..8a928dc 100644 --- a/src/collections/prompts/prompt-getters.ts +++ b/src/collections/prompts/prompt-getters.ts @@ -82,7 +82,7 @@ export const getPromptFandoms = ($promptPage: PromptPage): string[] => { export const getPromptAdditionalTags = ($promptPage: PromptPage): string[] => { const freeform: string[] = []; - $promptPage("li.freeforms a.tag").each(function (i) { + $promptPage("ul.tags.commas:first li.freeforms a.tag").each(function (i) { freeform[i] = $promptPage(this).text().trim(); }); return freeform; @@ -91,7 +91,7 @@ export const getPromptAdditionalTags = ($promptPage: PromptPage): string[] => { export const getPromptWarnings = ($promptPage: PromptPage): WorkWarnings[] => { const warnings: WorkWarnings[] = []; - $promptPage("li.warnings a.tag").each(function (i, element) { + $promptPage("ul.tags.commas:first li.warnings a.tag").each(function (i, element) { const warning = $promptPage(element).text().trim(); if (!Object.values(WorkWarnings).includes(warning as WorkWarnings)) { throw new Error("An unknown warning was found on the page"); @@ -99,13 +99,14 @@ export const getPromptWarnings = ($promptPage: PromptPage): WorkWarnings[] => { warnings[i] = warning as WorkWarnings; }); + if (warnings.length === 0) return ["Creator Chose Not To Use Archive Warnings"] as WorkWarnings[]; return warnings; }; export const getPromptCharacters = ($promptPage: PromptPage): string[] => { const characters: string[] = []; - $promptPage("li.characters a.tag").each(function (i, character) { + $promptPage("ul.tags.commas:first li.characters a.tag").each(function (i, character) { characters[i] = $promptPage(character).text().trim(); }); return characters; @@ -114,7 +115,7 @@ export const getPromptCharacters = ($promptPage: PromptPage): string[] => { export const getPromptRelationships = ($promptPage: PromptPage): string[] => { const ships: string[] = []; - $promptPage("li.relationships a.tag").each(function (i, ship) { + $promptPage("ul.tags.commas:first li.relationships a.tag").each(function (i, ship) { ships[i] = $promptPage(ship).text().trim(); }); return ships; diff --git a/tests/prompts.test.ts b/tests/prompts.test.ts index 28bb590..2351163 100644 --- a/tests/prompts.test.ts +++ b/tests/prompts.test.ts @@ -142,23 +142,46 @@ describe("Gets url from data", () => { }); }); - test("Fetches fandoms, addition, characters, relationships and warnings tags", async () => { + test("Fetches fandoms, additional, characters, relationships and warnings (multiple warning tags)", async () => { const prompt = await getPrompt( await getPromptDetailsFromUrl({ - url: "https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3573835", + url: "https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3574012", }) ); expect(prompt).toMatchObject({ - fandoms: ["SD Gundam G Generation Series (Video Games)", "Babel - R. F. Kuang"], + fandoms: ["K (Anime)", "U2 (Band)"], tags: { - warnings: ["Creator Chose Not To Use Archive Warnings"], - characters: ["Kate Schmidt (Fear Street)","Sa Beining","Ffion Foxwell"], - relationships: ["Sophie Lee/Rune (Sdorica)","CC-2224 | Cody & CT-7567 | Rex","Denji/Mitaka Asa"], - additional: ["Ewok Species (Star Wars)","FS Lobby Discord's GP Predictions Game","Natasha \"Phoenix\" Trace Needs a Hug"] + warnings: ["Creator Chose Not To Use Archive Warnings", "No Archive Warnings Apply", + "Graphic Depictions Of Violence", + "Major Character Death", + "Rape/Non-Con"], + characters: ["Klaatu","Kim Jikang | JK", "Uuma | Souma Yoshimi"], + relationships: ["lkay Gündoğan/Rodrigo Hernández","Fatima Jha/Rufus Weller"], + additional: ["Mentioned Other K-pop Artist(s)","P. T. Barnum Needs a Hug","Bai Yu/Zhu Yilong Character Combinations"] } }); }); + test("Fetches fandoms, additional, characters, relationships and warnings tags (no warning tag, multiple fills)", async () => { + const prompt = await getPrompt( + await getPromptDetailsFromUrl({ + url: "https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048", + }) + ); + expect(prompt).toMatchObject({ + fandoms: ["陈情令 | The Untamed (TV)"], + tags: { + warnings: ["Creator Chose Not To Use Archive Warnings"], + characters: [], + relationships: ["Lan Huan | Lan Xichen/Meng Yao | Jin Guangyao"], + additional: ["Crack Treated Seriously"] + } + }); + }); + + + + test("Fetches 0 claims", async () => { const prompt = await getPrompt( @@ -256,7 +279,7 @@ describe("Gets url from data", () => { fandoms: ['陈情令 | The Untamed (TV)'], tags: { - warnings: ["Author Chose Not To Use Archive Warnings"], + warnings: ["Creator Chose Not To Use Archive Warnings"], characters: [], relationships: ['Lan Huan | Lan Xichen/Meng Yao | Jin Guangyao'], additional: ['Crack Treated Seriously'], From a65b1d54b48ceea6b35ffdaba4f2fe8f25eed6e6 Mon Sep 17 00:00:00 2001 From: Rabbit Pie Date: Thu, 7 Mar 2024 10:40:24 +1030 Subject: [PATCH 31/31] removed cross-env package --- notes.md | 184 ------------------------------------------ package-lock.json | 20 +++-- package.json | 7 +- tests/prompts.test.ts | 18 ++--- 4 files changed, 20 insertions(+), 209 deletions(-) delete mode 100644 notes.md diff --git a/notes.md b/notes.md deleted file mode 100644 index 319d9f6..0000000 --- a/notes.md +++ /dev/null @@ -1,184 +0,0 @@ -

Notes

- -

Creating and Using Mocks

- -Mocks are offline webpages that are used to test our scripts. - -**To create a mock** you need to - -1. create the directory -2. download and add the prompt page with curl. - -``` -curl https://archiveofourown.org/works/51394438/chapters/136175206 > tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428.html -``` -This command will not work (1) if you are using Powershell, and (2) if the path does not yet exist. In order to use curl on Windows, open it in a git bash terminal. Powershell will do *something*, but not what we want it to. - -To create the directory structure at the same time you use run curl, run this in the project's base directory: - -``` -curl --create-dirs --output tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806.html https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806 -``` - -curl --create-dirs --output tests/mocks/data/collections/test_prompt_meme_2024/prompts/3583348.html https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3583348 - ---- - -I'm now **troubleshooting** a new an issue with getting the mock route to fuction correctly, so I decided to **create a new test script**. To do this, I added a new line to scripts (test-1) which now reads: -```js -"scripts": { - "build": "rm -rf dist/ && tsup src/index.ts src/urls.ts --format esm,cjs --dts", - "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --no-cache .test.ts$ --verbose=true", - "test-1": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --no-cache prompts.test.ts$ --verbose=true", - "encode-mock-files": "ts-node-esm tests/mocks/scripts/encode-mock-files.mts" - }, -``` -this can be run with the command npm run test-1. - ---- - -When adding the new route handler to handlers.ts, ensure that the new export goes *before* `allHandlers`. Otherwise, allHandlers will handle your route instead. - -```js -export default [ - profileHandlers, - feedHandlers, - tagWorksHandlers, - worksHandlers, - nameHandlers, - workPageHandlers, - worksNavigateHandlers, - worksChapterHandlers, - seriesHandlers, - promptHandlers, - allHandlers -]; -``` -note that my new Handler, promptHandlers, is before allHandlers, which is last. - - -my first attempt to create a mock route did not work, so I went to look at the documentation to see if I could gain a better understanding of why, and what was going on. https://mswjs.io/docs/api/http/#httpall - -Files I'm inspecting: -1. [./tests\mocks\handlers\all.ts](./tests\mocks\handlers\all.ts) -1. [TypeScript types](./tests\mocks\handlers\collections\prompt.ts) -2. - -...ok, curl did not work?!? - -https://curl.se/docs/ ---create-dirs - - ---- - -I'm creating these notes with a markdown file that I created by making a new file called notes.md. the .md is a file extension that indicates it's a markdown file. - -I've used three hyphens: --- to create horizontal rules separating the sections. - -I've used numbers: 1. to create a numbered list. - -I've used three backtics followed by js ```js to create the new js file. - -writing something directly before a --- will cause it to become a heading? - ---- - -When getting the collection display title from the scraper in [prompt-getters](src\collections\prompts\prompt-getters.ts), my test initially failed because the the returned information had newlines at the beginning and end. I removed them with .trim(). - -The display title is the "display" name of the collection eg. "Mó Dào Zǔ Shī | The Untamed Kink Meme 2020" which is in contrast to the collection name, which appears in the url: mo_dao_zu_shi_kink_meme_2020 - ---- - -A work can have multiple ratings values, or none. Therefore what we return will be an array. - -This one has General, Teen and Mature ratings, so I used to in the test: -https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806 - -now, to add it to the local file path... - -curl --create-dirs --output tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806.html https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1927806 - -getting the ratings was make more difficult by the fact I didn't have the correct key in my toMatchObject(Object) parameter. I misspelled it, and that caused me trouble! - -The error showed all possible key/value pairs that might be in the object, which confused me a lot. - ---- - -Deciding how to name my boolean I looked it up and grabbed this quote: - -In many languages, the convention for naming Booleans is typically to prefix them with "is", "has" or "can". This convention seems to be applied mostly to fields and method - ---- - -I used this script to get tags from the prompt fills via the console. First, I needed to define $0 as a parent element. Then I put this into the console. - -```js -To get freeforms: -let q = $0 //on parent -w = [... q.querySelectorAll("li.characters a.tag")] -let ar = [] -w.forEach((e)=>{ar.push(e.innerText)}); -ar -``` - ---- - -# Attribute Descriptions - -* **postedAt** The date the prompt was posted. -* **summary**: The test description of the prompt, as html -* **collectionDisplayTitle**: the title displayed on the collection pages and in tags. Not the same as collectionName, which is used to contruct the collection's url. -* **ratings**: a list of the requested ratings on the prompt. The prompt will display the highest of these on its UI. If the prompt has no ratings, "Not Rated" will be returned. -* **claims**: [Object] claims exist when users have "claimed" a prompt, but not yet filled it. Claims can have three different types of structres. To check if a variable exists, you can check the variable it depends on (eg. check `count > 0 before` accessing isAnonCollection and `inAnonCollection === false` before accessing claimerUsernames), or use `if "isAnonCollection" in variable`. - * `{count: 0}` There are no claims. We don't know if the collection is anonymous or not. - * `{count: number; isAnonCollection: true; }` There is a non-zero amount of anonymous claims. - * `{count: number; isAnonCollection: false; claimerUsernames: string[]}` There is a non-zero amount of claimers, and the collection isn't anonymous, and you can return an array of strings containing their **usernames** not pseuds; (it's unknown if they have pseuds). -* **categories**: `null | string[]`
-null if no categories are selected, or an array of strings (WorkCategory objects).
- -# TODO: - -Questions: -* Do we want characters, additional and ship tags to return a null if there are no tags in that category? - -* ✅ Get additional tags from prompts with multiple fills -* ✅ Get character tags from prompts with multiple fills -* ✅ Get warning tags from prompts with multiple fills -* 🟡 get prompt title (anon and not anon author, title and no title prompt meme) -* 🟡 get works -* 🟡 reimplement claims, possibly as `claims: { count: number, usernames: string[] | null } | null;` - - -in Fandom Coders, the idea of returning `null` if there are no warnings was brought up. However, I (RabbitPie) am not sure which variable would be considered "no warnings"? No Archive Warnings apply? "Author chose not to use archive warnings"? - -✅ Task Complete -🟡 Task Incomplete or not started - -# Done: - -1. As part of the query selector issue: More thorough tests to test different types of prompts in their entirety. The goal is not to have them pass immediately. I'll have to see how the series-getter approaches the issue of multiple works associated with a a request. - 1. Multiple known claimants - * ✅ [Mock created](/tests/mocks/data/collections/test_prompt_meme_2024/prompts/3583348.html) - * ✅ Test Created - * ✅ Test Passed - 2. Multiple anon claimants - * ✅ [Mock Created](/tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048.html) - * ✅ Test Created (prompts.test.ts > describe("Fetches full Prompt") callback) - * ✅ Test Passed - 3. Multiple fills - * ✅ [Mock Created - Same as Previous](/tests/mocks/data/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048.html) - * ✅ Test Created (prompts.test.ts > describe("Fetches full Prompt") callback) - * ✅ Test Passed - -* ✅ Get Categories - * ✅ Establish Category structure - * ✅ Create test for no categories - * ✅ Create test for one category - * ✅ Create test for multiple categories - * ✅ Create test for multiple fills - * ✅ Pass tests -* ✅ Get collectionName -* ✅ get collection id - - diff --git a/package-lock.json b/package-lock.json index 64d5e63..c05a13c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1868,18 +1868,11 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, - "cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "requires": { - "cross-spawn": "^7.0.1" - } - }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2481,7 +2474,8 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, "istanbul-lib-coverage": { "version": "3.2.2", @@ -3460,7 +3454,8 @@ "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true }, "path-parse": { "version": "1.0.7", @@ -3681,6 +3676,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "requires": { "shebang-regex": "^3.0.0" } @@ -3688,7 +3684,8 @@ "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true }, "signal-exit": { "version": "3.0.7", @@ -4170,6 +4167,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "requires": { "isexe": "^2.0.0" } diff --git a/package.json b/package.json index 1b722c8..b922215 100644 --- a/package.json +++ b/package.json @@ -33,8 +33,8 @@ ], "scripts": { "build": "rm -rf dist/ && tsup src/index.ts src/urls.ts --format esm,cjs --dts", - "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --no-cache .test.ts$ --verbose=true", - "test-1": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --no-cache prompts.test.ts$ --verbose=true", + "test": "NODE_OPTIONS=--experimental-vm-modules jest --no-cache .test.ts$ --verbose=true", + "test-prompts": "NODE_OPTIONS=--experimental-vm-modules jest --no-cache prompts.test.ts$ --verbose=true", "encode-mock-files": "ts-node-esm tests/mocks/scripts/encode-mock-files.mts" }, "repository": "https://github.com/essential-randomness/AO3.js.git", @@ -55,7 +55,6 @@ "typescript": "^5.1.6" }, "dependencies": { - "cheerio": "^1.0.0-rc.10", - "cross-env": "^7.0.3" + "cheerio": "^1.0.0-rc.10" } } diff --git a/tests/prompts.test.ts b/tests/prompts.test.ts index 2351163..c4c57b2 100644 --- a/tests/prompts.test.ts +++ b/tests/prompts.test.ts @@ -89,7 +89,7 @@ describe("Gets url from data", () => { }); }); - test("Fetches \"Not Rated\" for no specified ratings", async () => { + test("Fetches Ratings: \"Not Rated\" for no specified ratings", async () => { const prompt = await getPrompt( await getPromptDetailsFromUrl({ url: "https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428", @@ -101,7 +101,7 @@ describe("Gets url from data", () => { }); }); - test("Fetches Author(+pseud)", async () => { + test("Fetches Author (+pseud)", async () => { const prompt = await getPrompt( await getPromptDetailsFromUrl({ url: "https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3573835", @@ -115,7 +115,7 @@ describe("Gets url from data", () => { }); }); - test("Fetches Anonymous Author", async () => { + test("Fetches Author (Anonymous)", async () => { const prompt = await getPrompt( await getPromptDetailsFromUrl({ url: "https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3574012", @@ -127,7 +127,7 @@ describe("Gets url from data", () => { }); }); - test("Fetches Non-Pseuded Author", async () => { + test("Fetches Author (Non-Pseuded Author)", async () => { const prompt = await getPrompt( await getPromptDetailsFromUrl({ url: "https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/2644428", @@ -183,7 +183,7 @@ describe("Gets url from data", () => { - test("Fetches 0 claims", async () => { + test("Fetches claims: 0 claims", async () => { const prompt = await getPrompt( await getPromptDetailsFromUrl({url: "https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3573835"}) ); @@ -192,7 +192,7 @@ describe("Gets url from data", () => { }); }); - test("Fetches Anon Claims + No Known Claimaints", async () => { + test("Fetches claims: Anon Claims + No Known Claimaints", async () => { const prompt = await getPrompt( await getPromptDetailsFromUrl({url: "https://archiveofourown.org/collections/mo_dao_zu_shi_kink_meme_2020/prompts/1909048"}) ); @@ -201,7 +201,7 @@ describe("Gets url from data", () => { }); }); - test("Fetches Known Claimaints+No Anon Claimaints", async () => { + test("Fetches claims: Known Claimaints+No Anon Claimaints", async () => { const prompt = await getPrompt( await getPromptDetailsFromUrl({url: "https://archiveofourown.org/collections/test_prompt_meme_2024/prompts/3583348"}) ); @@ -249,9 +249,7 @@ describe("Gets url from data", () => { }); }); - - }); - + });