🚨 fix linting

This commit is contained in:
zS1L3NT Windows 2023-07-30 00:09:18 +08:00
parent df173dfe47
commit ab7aaaee8c
22 changed files with 887 additions and 152 deletions

View File

@ -1,3 +1,7 @@
[*]
indent_size = 4
indent_style = tab
[{*.yml, *.yaml}]
indent_size = 2
indent_style = space

42
.eslintrc.json Normal file
View File

@ -0,0 +1,42 @@
{
"env": {
"browser": true,
"es2021": true,
"node": true
},
"extends": [
// "next/core-web-vitals",
"eslint:recommended",
// "plugin:react/recommended",
"plugin:@typescript-eslint/recommended",
"prettier"
],
"overrides": [],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": [
// "react",
"@typescript-eslint",
"simple-import-sort"
],
"rules": {
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/ban-types": "warn",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-explicit-any": "off",
"linebreak-style": ["error", "unix"],
"no-empty": "warn",
"no-empty-function": "off",
"no-empty-pattern": "warn",
// "react/react-in-jsx-scope": "off",
"simple-import-sort/imports": [
"warn",
{
"groups": [["^\\w"], ["^@\\w+"], ["^@/"], ["^\\."]]
}
]
}
}

View File

@ -7,3 +7,4 @@
.editorconfig
.npmrc
tsconfig.json
.eslintrc.json

View File

@ -1,8 +1,11 @@
{
"semi": false,
"arrowParens": "avoid",
"trailingComma": "none",
"trailingComma": "all",
"jsxSingleQuote": false,
"jsxBracketSameLine": true,
"printWidth": 100
"printWidth": 100,
"singleAttributePerLine": true,
"bracketSameLine": true,
"useTabs": true,
"tabWidth": 4
}

View File

@ -13,7 +13,12 @@
"scripts": {
"test": "ts-mocha --timeout 30000 src/__tests__/**/*.spec.ts",
"docs:dev": "vuepress dev docs",
"docs:build": "vuepress build docs"
"docs:build": "vuepress build docs",
"lint": "eslint src",
"lint:fix": "eslint src --fix",
"prettier": "prettier src --check",
"prettier:fix": "prettier src --write",
"clean": "tsc --noEmit && eslint src --fix && prettier src --write"
},
"dependencies": {
"axios": "^0.27.2",
@ -26,10 +31,17 @@
"@types/mocha": "^10.0.1",
"@types/node": "^18.11.17",
"@types/tough-cookie": "^4.0.2",
"@typescript-eslint/eslint-plugin": "latest",
"@typescript-eslint/parser": "latest",
"@vuepress/plugin-search": "^2.0.0-beta.46",
"eslint": "latest",
"eslint-config-prettier": "latest",
"eslint-plugin-simple-import-sort": "latest",
"mocha": "^10.2.0",
"mocha.parallel": "^0.15.6",
"prettier": "latest",
"ts-mocha": "^10.0.0",
"ts-node": "^10.9.1",
"typescript": "^4.9.4",
"vuepress": "^2.0.0-beta.46"
},

View File

@ -31,18 +31,39 @@ devDependencies:
'@types/tough-cookie':
specifier: ^4.0.2
version: 4.0.2
'@typescript-eslint/eslint-plugin':
specifier: latest
version: 6.2.0(@typescript-eslint/parser@6.2.0)(eslint@8.46.0)(typescript@4.9.4)
'@typescript-eslint/parser':
specifier: latest
version: 6.2.0(eslint@8.46.0)(typescript@4.9.4)
'@vuepress/plugin-search':
specifier: ^2.0.0-beta.46
version: 2.0.0-beta.46
eslint:
specifier: latest
version: 8.46.0
eslint-config-prettier:
specifier: latest
version: 8.9.0(eslint@8.46.0)
eslint-plugin-simple-import-sort:
specifier: latest
version: 10.0.0(eslint@8.46.0)
mocha:
specifier: ^10.2.0
version: 10.2.0
mocha.parallel:
specifier: ^0.15.6
version: 0.15.6(mocha@10.2.0)
prettier:
specifier: latest
version: 3.0.0
ts-mocha:
specifier: ^10.0.0
version: 10.0.0(mocha@10.2.0)
ts-node:
specifier: ^10.9.1
version: 10.9.1(@types/node@18.11.17)(typescript@4.9.4)
typescript:
specifier: ^4.9.4
version: 4.9.4
@ -52,6 +73,11 @@ devDependencies:
packages:
/@aashutoshrathi/word-wrap@1.2.6:
resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==}
engines: {node: '>=0.10.0'}
dev: true
/@babel/helper-validator-identifier@7.16.7:
resolution: {integrity: sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==}
engines: {node: '>=6.9.0'}
@ -73,6 +99,86 @@ packages:
to-fast-properties: 2.0.0
dev: true
/@cspotcode/source-map-support@0.8.1:
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
dependencies:
'@jridgewell/trace-mapping': 0.3.9
dev: true
/@eslint-community/eslint-utils@4.4.0(eslint@8.46.0):
resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
dependencies:
eslint: 8.46.0
eslint-visitor-keys: 3.4.2
dev: true
/@eslint-community/regexpp@4.6.2:
resolution: {integrity: sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==}
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
dev: true
/@eslint/eslintrc@2.1.1:
resolution: {integrity: sha512-9t7ZA7NGGK8ckelF0PQCfcxIUzs1Md5rrO6U/c+FIQNanea5UZC0wqKXH4vHBccmu4ZJgZ2idtPeW7+Q2npOEA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
ajv: 6.12.6
debug: 4.3.4(supports-color@8.1.1)
espree: 9.6.1
globals: 13.20.0
ignore: 5.2.0
import-fresh: 3.3.0
js-yaml: 4.1.0
minimatch: 3.1.2
strip-json-comments: 3.1.1
transitivePeerDependencies:
- supports-color
dev: true
/@eslint/js@8.46.0:
resolution: {integrity: sha512-a8TLtmPi8xzPkCbp/OGFUo5yhRkHM2Ko9kOWP4znJr0WAhWyThaw3PnwX4vOTWOAMsV2uRt32PPDcEz63esSaA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
/@humanwhocodes/config-array@0.11.10:
resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==}
engines: {node: '>=10.10.0'}
dependencies:
'@humanwhocodes/object-schema': 1.2.1
debug: 4.3.4(supports-color@8.1.1)
minimatch: 3.1.2
transitivePeerDependencies:
- supports-color
dev: true
/@humanwhocodes/module-importer@1.0.1:
resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
engines: {node: '>=12.22'}
dev: true
/@humanwhocodes/object-schema@1.2.1:
resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==}
dev: true
/@jridgewell/resolve-uri@3.1.1:
resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==}
engines: {node: '>=6.0.0'}
dev: true
/@jridgewell/sourcemap-codec@1.4.15:
resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
dev: true
/@jridgewell/trace-mapping@0.3.9:
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
dependencies:
'@jridgewell/resolve-uri': 3.1.1
'@jridgewell/sourcemap-codec': 1.4.15
dev: true
/@nodelib/fs.scandir@2.1.5:
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
@ -94,6 +200,22 @@ packages:
fastq: 1.13.0
dev: true
/@tsconfig/node10@1.0.9:
resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==}
dev: true
/@tsconfig/node12@1.0.11:
resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==}
dev: true
/@tsconfig/node14@1.0.3:
resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==}
dev: true
/@tsconfig/node16@1.0.4:
resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
dev: true
/@types/debug@4.1.7:
resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==}
dependencies:
@ -110,6 +232,10 @@ packages:
resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
dev: true
/@types/json-schema@7.0.12:
resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==}
dev: true
/@types/json5@0.0.29:
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
requiresBuild: true
@ -143,10 +269,146 @@ packages:
resolution: {integrity: sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng==}
dev: true
/@types/semver@7.5.0:
resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==}
dev: true
/@types/tough-cookie@4.0.2:
resolution: {integrity: sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==}
dev: true
/@typescript-eslint/eslint-plugin@6.2.0(@typescript-eslint/parser@6.2.0)(eslint@8.46.0)(typescript@4.9.4):
resolution: {integrity: sha512-rClGrMuyS/3j0ETa1Ui7s6GkLhfZGKZL3ZrChLeAiACBE/tRc1wq8SNZESUuluxhLj9FkUefRs2l6bCIArWBiQ==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
'@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha
eslint: ^7.0.0 || ^8.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@eslint-community/regexpp': 4.6.2
'@typescript-eslint/parser': 6.2.0(eslint@8.46.0)(typescript@4.9.4)
'@typescript-eslint/scope-manager': 6.2.0
'@typescript-eslint/type-utils': 6.2.0(eslint@8.46.0)(typescript@4.9.4)
'@typescript-eslint/utils': 6.2.0(eslint@8.46.0)(typescript@4.9.4)
'@typescript-eslint/visitor-keys': 6.2.0
debug: 4.3.4(supports-color@8.1.1)
eslint: 8.46.0
graphemer: 1.4.0
ignore: 5.2.4
natural-compare: 1.4.0
natural-compare-lite: 1.4.0
semver: 7.5.4
ts-api-utils: 1.0.1(typescript@4.9.4)
typescript: 4.9.4
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/parser@6.2.0(eslint@8.46.0)(typescript@4.9.4):
resolution: {integrity: sha512-igVYOqtiK/UsvKAmmloQAruAdUHihsOCvplJpplPZ+3h4aDkC/UKZZNKgB6h93ayuYLuEymU3h8nF1xMRbh37g==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/scope-manager': 6.2.0
'@typescript-eslint/types': 6.2.0
'@typescript-eslint/typescript-estree': 6.2.0(typescript@4.9.4)
'@typescript-eslint/visitor-keys': 6.2.0
debug: 4.3.4(supports-color@8.1.1)
eslint: 8.46.0
typescript: 4.9.4
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/scope-manager@6.2.0:
resolution: {integrity: sha512-1ZMNVgm5nnHURU8ZSJ3snsHzpFeNK84rdZjluEVBGNu7jDymfqceB3kdIZ6A4xCfEFFhRIB6rF8q/JIqJd2R0Q==}
engines: {node: ^16.0.0 || >=18.0.0}
dependencies:
'@typescript-eslint/types': 6.2.0
'@typescript-eslint/visitor-keys': 6.2.0
dev: true
/@typescript-eslint/type-utils@6.2.0(eslint@8.46.0)(typescript@4.9.4):
resolution: {integrity: sha512-DnGZuNU2JN3AYwddYIqrVkYW0uUQdv0AY+kz2M25euVNlujcN2u+rJgfJsBFlUEzBB6OQkUqSZPyuTLf2bP5mw==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/typescript-estree': 6.2.0(typescript@4.9.4)
'@typescript-eslint/utils': 6.2.0(eslint@8.46.0)(typescript@4.9.4)
debug: 4.3.4(supports-color@8.1.1)
eslint: 8.46.0
ts-api-utils: 1.0.1(typescript@4.9.4)
typescript: 4.9.4
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/types@6.2.0:
resolution: {integrity: sha512-1nRRaDlp/XYJQLvkQJG5F3uBTno5SHPT7XVcJ5n1/k2WfNI28nJsvLakxwZRNY5spuatEKO7d5nZWsQpkqXwBA==}
engines: {node: ^16.0.0 || >=18.0.0}
dev: true
/@typescript-eslint/typescript-estree@6.2.0(typescript@4.9.4):
resolution: {integrity: sha512-Mts6+3HQMSM+LZCglsc2yMIny37IhUgp1Qe8yJUYVyO6rHP7/vN0vajKu3JvHCBIy8TSiKddJ/Zwu80jhnGj1w==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/types': 6.2.0
'@typescript-eslint/visitor-keys': 6.2.0
debug: 4.3.4(supports-color@8.1.1)
globby: 11.1.0
is-glob: 4.0.3
semver: 7.5.4
ts-api-utils: 1.0.1(typescript@4.9.4)
typescript: 4.9.4
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/utils@6.2.0(eslint@8.46.0)(typescript@4.9.4):
resolution: {integrity: sha512-RCFrC1lXiX1qEZN8LmLrxYRhOkElEsPKTVSNout8DMzf8PeWoQG7Rxz2SadpJa3VSh5oYKGwt7j7X/VRg+Y3OQ==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.46.0)
'@types/json-schema': 7.0.12
'@types/semver': 7.5.0
'@typescript-eslint/scope-manager': 6.2.0
'@typescript-eslint/types': 6.2.0
'@typescript-eslint/typescript-estree': 6.2.0(typescript@4.9.4)
eslint: 8.46.0
semver: 7.5.4
transitivePeerDependencies:
- supports-color
- typescript
dev: true
/@typescript-eslint/visitor-keys@6.2.0:
resolution: {integrity: sha512-QbaYUQVKKo9bgCzpjz45llCfwakyoxHetIy8CAvYCtd16Zu1KrpzNHofwF8kGkpPOxZB2o6kz+0nqH8ZkIzuoQ==}
engines: {node: ^16.0.0 || >=18.0.0}
dependencies:
'@typescript-eslint/types': 6.2.0
eslint-visitor-keys: 3.4.2
dev: true
/@vitejs/plugin-vue@2.3.3(vite@2.9.9)(vue@3.2.36):
resolution: {integrity: sha512-SmQLDyhz+6lGJhPELsBdzXGc+AcaT8stgkbiTFGpXPe8Tl1tJaBw1A6pxDqDuRsVkD8uscrkx3hA7QDOoKYtyw==}
engines: {node: '>=12.0.0'}
@ -541,6 +803,34 @@ packages:
vue-demi: 0.12.4(vue@3.2.36)
dev: true
/acorn-jsx@5.3.2(acorn@8.10.0):
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
dependencies:
acorn: 8.10.0
dev: true
/acorn-walk@8.2.0:
resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
engines: {node: '>=0.4.0'}
dev: true
/acorn@8.10.0:
resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==}
engines: {node: '>=0.4.0'}
hasBin: true
dev: true
/ajv@6.12.6:
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
dependencies:
fast-deep-equal: 3.1.3
fast-json-stable-stringify: 2.1.0
json-schema-traverse: 0.4.1
uri-js: 4.4.1
dev: true
/ansi-colors@4.1.1:
resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==}
engines: {node: '>=6'}
@ -566,6 +856,10 @@ packages:
picomatch: 2.3.1
dev: true
/arg@4.1.3:
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
dev: true
/argparse@1.0.10:
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
dependencies:
@ -692,6 +986,11 @@ packages:
engines: {node: '>=8'}
dev: true
/callsites@3.1.0:
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
engines: {node: '>=6'}
dev: true
/camelcase@6.3.0:
resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
engines: {node: '>=10'}
@ -776,6 +1075,10 @@ packages:
engines: {node: '>=0.8'}
dev: true
/create-require@1.1.1:
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
dev: true
/cross-spawn@7.0.3:
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
engines: {node: '>= 8'}
@ -807,6 +1110,10 @@ packages:
engines: {node: '>=10'}
dev: true
/deep-is@0.1.4:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
dev: true
/defaults@1.0.3:
resolution: {integrity: sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==}
dependencies:
@ -823,6 +1130,11 @@ packages:
engines: {node: '>=0.3.1'}
dev: true
/diff@4.0.2:
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
engines: {node: '>=0.3.1'}
dev: true
/diff@5.0.0:
resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==}
engines: {node: '>=0.3.1'}
@ -835,6 +1147,13 @@ packages:
path-type: 4.0.0
dev: true
/doctrine@3.0.0:
resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
engines: {node: '>=6.0.0'}
dependencies:
esutils: 2.0.3
dev: true
/electron-to-chromium@1.4.141:
resolution: {integrity: sha512-mfBcbqc0qc6RlxrsIgLG2wCqkiPAjEezHxGTu7p3dHHFOurH4EjS9rFZndX5axC8264rI1Pcbw8uQP39oZckeA==}
dev: true
@ -1072,16 +1391,125 @@ packages:
engines: {node: '>=10'}
dev: true
/eslint-config-prettier@8.9.0(eslint@8.46.0):
resolution: {integrity: sha512-+sbni7NfVXnOpnRadUA8S28AUlsZt9GjgFvABIRL9Hkn8KqNzOp+7Lw4QWtrwn20KzU3wqu1QoOj2m+7rKRqkA==}
hasBin: true
peerDependencies:
eslint: '>=7.0.0'
dependencies:
eslint: 8.46.0
dev: true
/eslint-plugin-simple-import-sort@10.0.0(eslint@8.46.0):
resolution: {integrity: sha512-AeTvO9UCMSNzIHRkg8S6c3RPy5YEwKWSQPx3DYghLedo2ZQxowPFLGDN1AZ2evfg6r6mjBSZSLxLFsWSu3acsw==}
peerDependencies:
eslint: '>=5.0.0'
dependencies:
eslint: 8.46.0
dev: true
/eslint-scope@7.2.2:
resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
esrecurse: 4.3.0
estraverse: 5.3.0
dev: true
/eslint-visitor-keys@3.4.2:
resolution: {integrity: sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
/eslint@8.46.0:
resolution: {integrity: sha512-cIO74PvbW0qU8e0mIvk5IV3ToWdCq5FYG6gWPHHkx6gNdjlbAYvtfHmlCMXxjcoVaIdwy/IAt3+mDkZkfvb2Dg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
hasBin: true
dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.46.0)
'@eslint-community/regexpp': 4.6.2
'@eslint/eslintrc': 2.1.1
'@eslint/js': 8.46.0
'@humanwhocodes/config-array': 0.11.10
'@humanwhocodes/module-importer': 1.0.1
'@nodelib/fs.walk': 1.2.8
ajv: 6.12.6
chalk: 4.1.2
cross-spawn: 7.0.3
debug: 4.3.4(supports-color@8.1.1)
doctrine: 3.0.0
escape-string-regexp: 4.0.0
eslint-scope: 7.2.2
eslint-visitor-keys: 3.4.2
espree: 9.6.1
esquery: 1.5.0
esutils: 2.0.3
fast-deep-equal: 3.1.3
file-entry-cache: 6.0.1
find-up: 5.0.0
glob-parent: 6.0.2
globals: 13.20.0
graphemer: 1.4.0
ignore: 5.2.0
imurmurhash: 0.1.4
is-glob: 4.0.3
is-path-inside: 3.0.3
js-yaml: 4.1.0
json-stable-stringify-without-jsonify: 1.0.1
levn: 0.4.1
lodash.merge: 4.6.2
minimatch: 3.1.2
natural-compare: 1.4.0
optionator: 0.9.3
strip-ansi: 6.0.1
text-table: 0.2.0
transitivePeerDependencies:
- supports-color
dev: true
/espree@9.6.1:
resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
acorn: 8.10.0
acorn-jsx: 5.3.2(acorn@8.10.0)
eslint-visitor-keys: 3.4.2
dev: true
/esprima@4.0.1:
resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
engines: {node: '>=4'}
hasBin: true
dev: true
/esquery@1.5.0:
resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==}
engines: {node: '>=0.10'}
dependencies:
estraverse: 5.3.0
dev: true
/esrecurse@4.3.0:
resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
engines: {node: '>=4.0'}
dependencies:
estraverse: 5.3.0
dev: true
/estraverse@5.3.0:
resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
engines: {node: '>=4.0'}
dev: true
/estree-walker@2.0.2:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
dev: true
/esutils@2.0.3:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'}
dev: true
/execa@5.1.1:
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
engines: {node: '>=10'}
@ -1104,6 +1532,10 @@ packages:
is-extendable: 0.1.1
dev: true
/fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
dev: true
/fast-glob@3.2.11:
resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==}
engines: {node: '>=8.6.0'}
@ -1115,12 +1547,27 @@ packages:
micromatch: 4.0.5
dev: true
/fast-json-stable-stringify@2.1.0:
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
dev: true
/fast-levenshtein@2.0.6:
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
dev: true
/fastq@1.13.0:
resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==}
dependencies:
reusify: 1.0.4
dev: true
/file-entry-cache@6.0.1:
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
engines: {node: ^10.12.0 || >=12.0.0}
dependencies:
flat-cache: 3.0.4
dev: true
/fill-range@7.0.1:
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
engines: {node: '>=8'}
@ -1136,11 +1583,23 @@ packages:
path-exists: 4.0.0
dev: true
/flat-cache@3.0.4:
resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==}
engines: {node: ^10.12.0 || >=12.0.0}
dependencies:
flatted: 3.2.7
rimraf: 3.0.2
dev: true
/flat@5.0.2:
resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==}
hasBin: true
dev: true
/flatted@3.2.7:
resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==}
dev: true
/follow-redirects@1.15.2:
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
engines: {node: '>=4.0'}
@ -1206,6 +1665,13 @@ packages:
is-glob: 4.0.3
dev: true
/glob-parent@6.0.2:
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
engines: {node: '>=10.13.0'}
dependencies:
is-glob: 4.0.3
dev: true
/glob@7.2.0:
resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==}
dependencies:
@ -1217,6 +1683,13 @@ packages:
path-is-absolute: 1.0.1
dev: true
/globals@13.20.0:
resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==}
engines: {node: '>=8'}
dependencies:
type-fest: 0.20.2
dev: true
/globby@11.1.0:
resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
engines: {node: '>=10'}
@ -1233,6 +1706,10 @@ packages:
resolution: {integrity: sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==}
dev: true
/graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
dev: true
/gray-matter@4.0.3:
resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==}
engines: {node: '>=6.0'}
@ -1278,10 +1755,28 @@ packages:
engines: {node: '>= 4'}
dev: true
/ignore@5.2.4:
resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
engines: {node: '>= 4'}
dev: true
/immutable@4.0.0:
resolution: {integrity: sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==}
dev: true
/import-fresh@3.3.0:
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
engines: {node: '>=6'}
dependencies:
parent-module: 1.0.1
resolve-from: 4.0.0
dev: true
/imurmurhash@0.1.4:
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
engines: {node: '>=0.8.19'}
dev: true
/inflight@1.0.6:
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
dependencies:
@ -1338,6 +1833,11 @@ packages:
engines: {node: '>=0.12.0'}
dev: true
/is-path-inside@3.0.3:
resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
engines: {node: '>=8'}
dev: true
/is-plain-obj@2.1.0:
resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==}
engines: {node: '>=8'}
@ -1372,6 +1872,14 @@ packages:
argparse: 2.0.1
dev: true
/json-schema-traverse@0.4.1:
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
dev: true
/json-stable-stringify-without-jsonify@1.0.1:
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
dev: true
/json5@1.0.1:
resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==}
hasBin: true
@ -1394,6 +1902,14 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
/levn@0.4.1:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
dependencies:
prelude-ls: 1.2.1
type-check: 0.4.0
dev: true
/linkify-it@4.0.1:
resolution: {integrity: sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==}
dependencies:
@ -1407,6 +1923,10 @@ packages:
p-locate: 5.0.0
dev: true
/lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
dev: true
/log-symbols@4.1.0:
resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
engines: {node: '>=10'}
@ -1415,6 +1935,13 @@ packages:
is-unicode-supported: 0.1.0
dev: true
/lru-cache@6.0.0:
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
engines: {node: '>=10'}
dependencies:
yallist: 4.0.0
dev: true
/magic-string@0.25.9:
resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
dependencies:
@ -1578,6 +2105,14 @@ packages:
hasBin: true
dev: true
/natural-compare-lite@1.4.0:
resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}
dev: true
/natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
dev: true
/node-releases@2.0.5:
resolution: {integrity: sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==}
dev: true
@ -1612,6 +2147,18 @@ packages:
mimic-fn: 2.1.0
dev: true
/optionator@0.9.3:
resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==}
engines: {node: '>= 0.8.0'}
dependencies:
'@aashutoshrathi/word-wrap': 1.2.6
deep-is: 0.1.4
fast-levenshtein: 2.0.6
levn: 0.4.1
prelude-ls: 1.2.1
type-check: 0.4.0
dev: true
/ora@5.4.1:
resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==}
engines: {node: '>=10'}
@ -1641,6 +2188,13 @@ packages:
p-limit: 3.1.0
dev: true
/parent-module@1.0.1:
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
engines: {node: '>=6'}
dependencies:
callsites: 3.1.0
dev: true
/path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
@ -1687,6 +2241,17 @@ packages:
source-map-js: 1.0.2
dev: true
/prelude-ls@1.2.1:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
dev: true
/prettier@3.0.0:
resolution: {integrity: sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==}
engines: {node: '>=14'}
hasBin: true
dev: true
/prismjs@1.28.0:
resolution: {integrity: sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw==}
engines: {node: '>=6'}
@ -1699,7 +2264,6 @@ packages:
/punycode@2.1.1:
resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==}
engines: {node: '>=6'}
dev: false
/querystringify@2.2.0:
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
@ -1740,6 +2304,11 @@ packages:
resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
dev: false
/resolve-from@4.0.0:
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
engines: {node: '>=4'}
dev: true
/resolve@1.22.0:
resolution: {integrity: sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==}
hasBin: true
@ -1762,6 +2331,13 @@ packages:
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
dev: true
/rimraf@3.0.2:
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
hasBin: true
dependencies:
glob: 7.2.0
dev: true
/rollup@2.75.3:
resolution: {integrity: sha512-YA29fLU6MAYSaDxIQYrGGOcbXlDmG96h0krGGYObroezcQ0KgEPM3+7MtKD/qeuUbFuAJXvKZee5dA1dpwq1PQ==}
engines: {node: '>=10.0.0'}
@ -1803,6 +2379,14 @@ packages:
engines: {node: '>=0.8.0'}
dev: true
/semver@7.5.4:
resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==}
engines: {node: '>=10'}
hasBin: true
dependencies:
lru-cache: 6.0.0
dev: true
/serialize-javascript@6.0.0:
resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==}
dependencies:
@ -1918,6 +2502,10 @@ packages:
engines: {node: '>= 0.4'}
dev: true
/text-table@0.2.0:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
dev: true
/to-fast-properties@2.0.0:
resolution: {integrity: sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=}
engines: {node: '>=4'}
@ -1944,6 +2532,15 @@ packages:
url-parse: 1.5.10
dev: false
/ts-api-utils@1.0.1(typescript@4.9.4):
resolution: {integrity: sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==}
engines: {node: '>=16.13.0'}
peerDependencies:
typescript: '>=4.2.0'
dependencies:
typescript: 4.9.4
dev: true
/ts-debounce@4.0.0:
resolution: {integrity: sha512-+1iDGY6NmOGidq7i7xZGA4cm8DAa6fqdYcvO5Z6yBevH++Bdo9Qt/mN0TzHUgcCcKv1gmh9+W5dHqz8pMWbCbg==}
dev: true
@ -1961,6 +2558,37 @@ packages:
tsconfig-paths: 3.14.1
dev: true
/ts-node@10.9.1(@types/node@18.11.17)(typescript@4.9.4):
resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==}
hasBin: true
peerDependencies:
'@swc/core': '>=1.2.50'
'@swc/wasm': '>=1.2.50'
'@types/node': '*'
typescript: '>=2.7'
peerDependenciesMeta:
'@swc/core':
optional: true
'@swc/wasm':
optional: true
dependencies:
'@cspotcode/source-map-support': 0.8.1
'@tsconfig/node10': 1.0.9
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.4
'@types/node': 18.11.17
acorn: 8.10.0
acorn-walk: 8.2.0
arg: 4.1.3
create-require: 1.1.1
diff: 4.0.2
make-error: 1.3.6
typescript: 4.9.4
v8-compile-cache-lib: 3.0.1
yn: 3.1.1
dev: true
/ts-node@7.0.1:
resolution: {integrity: sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==}
engines: {node: '>=4.2.0'}
@ -1987,6 +2615,18 @@ packages:
dev: true
optional: true
/type-check@0.4.0:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'}
dependencies:
prelude-ls: 1.2.1
dev: true
/type-fest@0.20.2:
resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
engines: {node: '>=10'}
dev: true
/typescript@4.9.4:
resolution: {integrity: sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==}
engines: {node: '>=4.2.0'}
@ -2012,6 +2652,12 @@ packages:
engines: {node: '>=4'}
dev: true
/uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
dependencies:
punycode: 2.1.1
dev: true
/url-parse@1.5.10:
resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==}
dependencies:
@ -2023,6 +2669,10 @@ packages:
resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=}
dev: true
/v8-compile-cache-lib@3.0.1:
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
dev: true
/vite@2.9.9:
resolution: {integrity: sha512-ffaam+NgHfbEmfw/Vuh6BHKKlI/XIAhxE5QSS7gFLIngxg171mg1P3a4LSRME0z2ZU1ScxoKzphkipcYwSD5Ew==}
engines: {node: '>=12.2.0'}
@ -2155,6 +2805,10 @@ packages:
engines: {node: '>=10'}
dev: true
/yallist@4.0.0:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
dev: true
/yargs-parser@20.2.4:
resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==}
engines: {node: '>=10'}
@ -2188,6 +2842,11 @@ packages:
engines: {node: '>=4'}
dev: true
/yn@3.1.1:
resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
engines: {node: '>=6'}
dev: true
/yocto-queue@0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}

View File

@ -9,8 +9,16 @@ import SearchParser from "./parsers/SearchParser"
import SongParser from "./parsers/SongParser"
import VideoParser from "./parsers/VideoParser"
import {
AlbumDetailed, AlbumFull, ArtistDetailed, ArtistFull, PlaylistFull, SearchResult, SongDetailed,
SongFull, VideoDetailed, VideoFull
AlbumDetailed,
AlbumFull,
ArtistDetailed,
ArtistFull,
PlaylistFull,
SearchResult,
SongDetailed,
SongFull,
VideoDetailed,
VideoFull,
} from "./schemas"
import traverse from "./utils/traverse"
import traverseList from "./utils/traverseList"
@ -33,9 +41,9 @@ export default class YTMusic {
headers: {
"User-Agent":
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36",
"Accept-Language": "en-US,en;q=0.5"
"Accept-Language": "en-US,en;q=0.5",
},
withCredentials: true
withCredentials: true,
})
this.client.interceptors.request.use(req => {
@ -89,14 +97,16 @@ export default class YTMusic {
.map(s => {
try {
return JSON.parse(s)
} catch {}
} catch {
return null
}
})
.filter(j => !!j)
for (const config of configs) {
this.config = {
...this.config,
...config
...config,
}
}
@ -115,7 +125,7 @@ export default class YTMusic {
private async constructRequest(
endpoint: string,
body: Record<string, any> = {},
query: Record<string, string> = {}
query: Record<string, string> = {},
) {
if (!this.config) {
throw new Error("API not initialized. Make sure to call the initialize() method first")
@ -131,13 +141,13 @@ export default class YTMusic {
"X-YouTube-Page-CL": this.config.PAGE_CL,
"X-YouTube-Page-Label": this.config.PAGE_BUILD_LABEL,
"X-YouTube-Utc-Offset": String(-new Date().getTimezoneOffset()),
"X-YouTube-Time-Zone": new Intl.DateTimeFormat().resolvedOptions().timeZone
"X-YouTube-Time-Zone": new Intl.DateTimeFormat().resolvedOptions().timeZone,
}
const searchParams = new URLSearchParams({
...query,
alt: "json",
key: this.config.INNERTUBE_API_KEY!
key: this.config.INNERTUBE_API_KEY!,
})
const res = await this.client.post(
@ -154,42 +164,42 @@ export default class YTMusic {
hl: this.config.HL,
locationInfo: {
locationPermissionAuthorizationStatus:
"LOCATION_PERMISSION_AUTHORIZATION_STATUS_UNSUPPORTED"
"LOCATION_PERMISSION_AUTHORIZATION_STATUS_UNSUPPORTED",
},
musicAppInfo: {
musicActivityMasterSwitch: "MUSIC_ACTIVITY_MASTER_SWITCH_INDETERMINATE",
musicLocationMasterSwitch: "MUSIC_LOCATION_MASTER_SWITCH_INDETERMINATE",
pwaInstallabilityStatus: "PWA_INSTALLABILITY_STATUS_UNKNOWN"
pwaInstallabilityStatus: "PWA_INSTALLABILITY_STATUS_UNKNOWN",
},
utcOffsetMinutes: -new Date().getTimezoneOffset()
utcOffsetMinutes: -new Date().getTimezoneOffset(),
},
request: {
internalExperimentFlags: [
{
key: "force_music_enable_outertube_tastebuilder_browse",
value: "true"
value: "true",
},
{
key: "force_music_enable_outertube_playlist_detail_browse",
value: "true"
value: "true",
},
{
key: "force_music_enable_outertube_search_suggestions",
value: "true"
}
value: "true",
},
],
sessionIndex: {}
sessionIndex: {},
},
user: {
enableSafetyMode: false
}
enableSafetyMode: false,
},
...body
},
...body,
},
{
responseType: "json",
headers
}
headers,
},
)
return "responseContext" in res.data ? res.data : res
@ -204,9 +214,9 @@ export default class YTMusic {
public async getSearchSuggestions(query: string): Promise<string[]> {
return traverseList(
await this.constructRequest("music/get_search_suggestions", {
input: query
input: query,
}),
"query"
"query",
)
}
@ -218,7 +228,7 @@ export default class YTMusic {
public async search(query: string): Promise<z.infer<typeof SearchResult>[]> {
const searchData = await this.constructRequest("search", {
query,
params: null
params: null,
})
return traverseList(searchData, "musicResponsiveListItemRenderer")
@ -234,11 +244,11 @@ export default class YTMusic {
public async searchSongs(query: string): Promise<z.infer<typeof SongDetailed>[]> {
const searchData = await this.constructRequest("search", {
query,
params: "Eg-KAQwIARAAGAAgACgAMABqChAEEAMQCRAFEAo%3D"
params: "Eg-KAQwIARAAGAAgACgAMABqChAEEAMQCRAFEAo%3D",
})
return traverseList(searchData, "musicResponsiveListItemRenderer").map(
SongParser.parseSearchResult
SongParser.parseSearchResult,
)
}
@ -250,11 +260,11 @@ export default class YTMusic {
public async searchVideos(query: string): Promise<z.infer<typeof VideoDetailed>[]> {
const searchData = await this.constructRequest("search", {
query,
params: "Eg-KAQwIABABGAAgACgAMABqChAEEAMQCRAFEAo%3D"
params: "Eg-KAQwIABABGAAgACgAMABqChAEEAMQCRAFEAo%3D",
})
return traverseList(searchData, "musicResponsiveListItemRenderer").map(
VideoParser.parseSearchResult
VideoParser.parseSearchResult,
)
}
@ -266,11 +276,11 @@ export default class YTMusic {
public async searchArtists(query: string): Promise<z.infer<typeof ArtistDetailed>[]> {
const searchData = await this.constructRequest("search", {
query,
params: "Eg-KAQwIABAAGAAgASgAMABqChAEEAMQCRAFEAo%3D"
params: "Eg-KAQwIABAAGAAgASgAMABqChAEEAMQCRAFEAo%3D",
})
return traverseList(searchData, "musicResponsiveListItemRenderer").map(
ArtistParser.parseSearchResult
ArtistParser.parseSearchResult,
)
}
@ -282,11 +292,11 @@ export default class YTMusic {
public async searchAlbums(query: string): Promise<z.infer<typeof AlbumDetailed>[]> {
const searchData = await this.constructRequest("search", {
query,
params: "Eg-KAQwIABAAGAEgACgAMABqChAEEAMQCRAFEAo%3D"
params: "Eg-KAQwIABAAGAEgACgAMABqChAEEAMQCRAFEAo%3D",
})
return traverseList(searchData, "musicResponsiveListItemRenderer").map(
AlbumParser.parseSearchResult
AlbumParser.parseSearchResult,
)
}
@ -298,11 +308,11 @@ export default class YTMusic {
public async searchPlaylists(query: string): Promise<z.infer<typeof PlaylistFull>[]> {
const searchData = await this.constructRequest("search", {
query,
params: "Eg-KAQwIABAAGAAgACgBMABqChAEEAMQCRAFEAo%3D"
params: "Eg-KAQwIABAAGAAgACgBMABqChAEEAMQCRAFEAo%3D",
})
return traverseList(searchData, "musicResponsiveListItemRenderer").map(
PlaylistParser.parseSearchResult
PlaylistParser.parseSearchResult,
)
}
@ -344,7 +354,7 @@ export default class YTMusic {
*/
public async getArtist(artistId: string): Promise<z.infer<typeof ArtistFull>> {
const data = await this.constructRequest("browse", {
browseId: artistId
browseId: artistId,
})
return ArtistParser.parse(data, artistId)
@ -358,25 +368,25 @@ export default class YTMusic {
*/
public async getArtistSongs(artistId: string): Promise<z.infer<typeof SongDetailed>[]> {
const artistData = await this.constructRequest("browse", {
browseId: artistId
browseId: artistId,
})
const browseToken = traverse(artistData, "musicShelfRenderer", "title", "browseId")
if (browseToken instanceof Array) return []
const songsData = await this.constructRequest("browse", {
browseId: browseToken
browseId: browseToken,
})
const continueToken = traverse(songsData, "continuation")
const moreSongsData = await this.constructRequest(
"browse",
{},
{ continuation: continueToken }
{ continuation: continueToken },
)
return [
...traverseList(songsData, "musicResponsiveListItemRenderer"),
...traverseList(moreSongsData, "musicResponsiveListItemRenderer")
...traverseList(moreSongsData, "musicResponsiveListItemRenderer"),
].map(SongParser.parseArtistSong)
}
@ -388,7 +398,7 @@ export default class YTMusic {
*/
public async getArtistAlbums(artistId: string): Promise<z.infer<typeof AlbumDetailed>[]> {
const artistData = await this.constructRequest("browse", {
browseId: artistId
browseId: artistId,
})
const artistAlbumsData = traverseList(artistData, "musicCarouselShelfRenderer")[0]
const browseBody = traverse(artistAlbumsData, "moreContentButton", "browseEndpoint")
@ -398,8 +408,8 @@ export default class YTMusic {
return traverseList(albumsData, "musicTwoRowItemRenderer").map(item =>
AlbumParser.parseArtistAlbum(item, {
artistId,
name: traverseString(albumsData, "header", "runs", "text")()
})
name: traverseString(albumsData, "header", "runs", "text")(),
}),
)
}
@ -411,7 +421,7 @@ export default class YTMusic {
*/
public async getAlbum(albumId: string): Promise<z.infer<typeof AlbumFull>> {
const data = await this.constructRequest("browse", {
browseId: albumId
browseId: albumId,
})
return AlbumParser.parse(data, albumId)
@ -426,7 +436,7 @@ export default class YTMusic {
public async getPlaylist(playlistId: string): Promise<z.infer<typeof PlaylistFull>> {
if (playlistId.startsWith("PL")) playlistId = "VL" + playlistId
const data = await this.constructRequest("browse", {
browseId: playlistId
browseId: playlistId,
})
return PlaylistParser.parse(data, playlistId)
@ -441,18 +451,16 @@ export default class YTMusic {
public async getPlaylistVideos(playlistId: string): Promise<z.infer<typeof VideoDetailed>[]> {
if (playlistId.startsWith("PL")) playlistId = "VL" + playlistId
const playlistData = await this.constructRequest("browse", {
browseId: playlistId
browseId: playlistId,
})
const songs = traverseList(
playlistData,
"musicPlaylistShelfRenderer",
"musicResponsiveListItemRenderer"
"musicResponsiveListItemRenderer",
)
let continuation = traverse(playlistData, "continuation")
while (true) {
if (continuation instanceof Array) break
while (!(continuation instanceof Array)) {
const songsData = await this.constructRequest("browse", {}, { continuation })
songs.push(...traverseList(songsData, "musicResponsiveListItemRenderer"))
continuation = traverse(songsData, "continuation")

View File

@ -1,12 +1,19 @@
import { equal } from "assert"
import describeParallel from "mocha.parallel"
import { z } from "zod"
import {
AlbumDetailed, AlbumFull, ArtistDetailed, ArtistFull, PlaylistFull, SongDetailed, SongFull,
VideoDetailed, VideoFull
AlbumDetailed,
AlbumFull,
ArtistDetailed,
ArtistFull,
PlaylistFull,
SongDetailed,
SongFull,
VideoDetailed,
VideoFull,
} from "../schemas"
import YTMusic from "../YTMusic"
import { equal } from "assert"
const errors = <z.ZodError<any>[]>[]
const queries = ["Lilac", "Weekend", "Eill", "Eminem", "Lisa Hannigan"]
@ -61,8 +68,8 @@ queries.forEach(query => {
AlbumDetailed.or(ArtistDetailed)
.or(PlaylistFull)
.or(SongDetailed)
.or(VideoDetailed)
)
.or(VideoDetailed),
),
)
})

View File

@ -13,7 +13,7 @@ export type {
SongFull,
ThumbnailFull,
VideoDetailed,
VideoFull
VideoFull,
} from "./schemas"
export default YTMusic

View File

@ -8,13 +8,13 @@ export default class AlbumParser {
public static parse(data: any, albumId: string): AlbumFull {
const albumBasic: AlbumBasic = {
albumId,
name: traverseString(data, "header", "title", "text")()
name: traverseString(data, "header", "title", "text")(),
}
const artists: ArtistBasic[] = traverseList(data, "header", "subtitle", "runs")
.filter(run => "navigationEndpoint" in run)
.map(run => ({
artistId: traverseString(run, "browseId")(),
name: traverseString(run, "text")()
name: traverseString(run, "text")(),
}))
const thumbnails = traverseList(data, "header", "thumbnails")
@ -25,15 +25,15 @@ export default class AlbumParser {
playlistId: traverseString(data, "buttonRenderer", "playlistId")(),
artists,
year: AlbumParser.processYear(
traverseString(data, "header", "subtitle", "text")(-1)
traverseString(data, "header", "subtitle", "text")(-1),
),
thumbnails,
description: traverseString(data, "description", "text")(),
songs: traverseList(data, "musicResponsiveListItemRenderer").map(item =>
SongParser.parseAlbumSong(item, artists, albumBasic, thumbnails)
)
SongParser.parseAlbumSong(item, artists, albumBasic, thumbnails),
),
},
AlbumFull
AlbumFull,
)
}
@ -49,13 +49,13 @@ export default class AlbumParser {
.filter(run => "navigationEndpoint" in run)
.map(run => ({
artistId: traverseString(run, "browseId")(),
name: traverseString(run, "text")()
name: traverseString(run, "text")(),
})),
year: AlbumParser.processYear(traverseString(flexColumns[1], "runs", "text")(-1)),
name: traverseString(flexColumns[0], "runs", "text")(),
thumbnails: traverseList(item, "thumbnails")
thumbnails: traverseList(item, "thumbnails"),
},
AlbumDetailed
AlbumDetailed,
)
}
@ -68,9 +68,9 @@ export default class AlbumParser {
name: traverseString(item, "title", "text")(),
artists: [artistBasic],
year: AlbumParser.processYear(traverseString(item, "subtitle", "text")(-1)),
thumbnails: traverseList(item, "thumbnails")
thumbnails: traverseList(item, "thumbnails"),
},
AlbumDetailed
AlbumDetailed,
)
}
@ -83,9 +83,9 @@ export default class AlbumParser {
name: traverseString(item, "title", "text")(),
artists: [artistBasic],
year: AlbumParser.processYear(traverseString(item, "subtitle", "text")(-1)),
thumbnails: traverseList(item, "thumbnails")
thumbnails: traverseList(item, "thumbnails"),
},
AlbumDetailed
AlbumDetailed,
)
}

View File

@ -1,5 +1,3 @@
import { ArtistBasic, ArtistDetailed, ArtistFull } from "../schemas"
import checkType from "../utils/checkType"
import traverseList from "../utils/traverseList"
@ -12,7 +10,7 @@ export default class ArtistParser {
public static parse(data: any, artistId: string): ArtistFull {
const artistBasic: ArtistBasic = {
artistId,
name: traverseString(data, "header", "title", "text")()
name: traverseString(data, "header", "title", "text")(),
}
const description = traverseString(data, "header", "description", "text")()
@ -24,28 +22,28 @@ export default class ArtistParser {
thumbnails: traverseList(data, "header", "thumbnails"),
description,
topSongs: traverseList(data, "musicShelfRenderer", "contents").map(item =>
SongParser.parseArtistTopSong(item, artistBasic)
SongParser.parseArtistTopSong(item, artistBasic),
),
topAlbums:
traverseList(data, "musicCarouselShelfRenderer")
?.at(0)
?.contents.map((item: any) =>
AlbumParser.parseArtistTopAlbum(item, artistBasic)
AlbumParser.parseArtistTopAlbum(item, artistBasic),
) ?? [],
topSingles:
traverseList(data, "musicCarouselShelfRenderer")
?.at(1)
?.contents.map((item: any) =>
AlbumParser.parseArtistTopAlbum(item, artistBasic)
AlbumParser.parseArtistTopAlbum(item, artistBasic),
) ?? [],
topVideos:
traverseList(data, "musicCarouselShelfRenderer")
?.at(2)
?.contents.map((item: any) =>
VideoParser.parseArtistTopVideo(item, artistBasic)
) ?? []
VideoParser.parseArtistTopVideo(item, artistBasic),
) ?? [],
},
ArtistFull
ArtistFull,
)
}
@ -57,9 +55,9 @@ export default class ArtistParser {
type: "ARTIST",
artistId: traverseString(item, "browseId")(),
name: traverseString(flexColumns[0], "runs", "text")(),
thumbnails: traverseList(item, "thumbnails")
thumbnails: traverseList(item, "thumbnails"),
},
ArtistDetailed
ArtistDetailed,
)
}
}

View File

@ -18,7 +18,7 @@ export default class Parser {
K: number * 1000,
M: number * 1000 * 1000,
B: number * 1000 * 1000 * 1000,
T: number * 1000 * 1000 * 1000 * 1000
T: number * 1000 * 1000 * 1000 * 1000,
}[multiplier!] || NaN
)
} else {

View File

@ -12,11 +12,11 @@ export default class PlaylistParser {
name: traverseString(data, "header", "title", "text")(),
artist: {
artistId: traverseString(data, "header", "subtitle", "browseId")(),
name: traverseString(data, "header", "subtitle", "text")(2)
name: traverseString(data, "header", "subtitle", "text")(2),
},
thumbnails: traverseList(data, "header", "thumbnails")
thumbnails: traverseList(data, "header", "thumbnails"),
},
PlaylistFull
PlaylistFull,
)
}
@ -30,11 +30,11 @@ export default class PlaylistParser {
name: traverseString(flexColumns[0], "runs", "text")(),
artist: {
artistId: traverseString(flexColumns[1], "browseId")(),
name: traverseString(flexColumns[1], "runs", "text")(-3)
name: traverseString(flexColumns[1], "runs", "text")(-3),
},
thumbnails: traverseList(item, "thumbnails")
thumbnails: traverseList(item, "thumbnails"),
},
PlaylistFull
PlaylistFull,
)
}
}

View File

@ -25,7 +25,7 @@ export default class SearchParser {
EP: AlbumParser.parseSearchResult,
Single: AlbumParser.parseSearchResult,
Album: AlbumParser.parseSearchResult,
Playlist: PlaylistParser.parseSearchResult
Playlist: PlaylistParser.parseSearchResult,
}
if (parsers[type]) {

View File

@ -14,16 +14,16 @@ export default class SongParser {
artists: [
{
artistId: traverseString(data, "videoDetails", "channelId")(),
name: traverseString(data, "author")()
}
name: traverseString(data, "author")(),
},
],
duration: +traverseString(data, "videoDetails", "lengthSeconds")(),
thumbnails: traverseList(data, "videoDetails", "thumbnails"),
description: traverseString(data, "description")(),
formats: traverseList(data, "streamingData", "formats"),
adaptiveFormats: traverseList(data, "streamingData", "adaptiveFormats")
adaptiveFormats: traverseList(data, "streamingData", "adaptiveFormats"),
},
SongFull
SongFull,
)
}
@ -39,17 +39,17 @@ export default class SongParser {
.filter(run => "navigationEndpoint" in run)
.map(run => ({
artistId: traverseString(run, "browseId")(),
name: traverseString(run, "text")()
name: traverseString(run, "text")(),
}))
.slice(0, -1),
album: {
albumId: traverseString(flexColumns[1], "runs", "browseId")(-1),
name: traverseString(flexColumns[1], "runs", "text")(-3)
name: traverseString(flexColumns[1], "runs", "text")(-3),
},
duration: Parser.parseDuration(traverseString(flexColumns[1], "runs", "text")(-1)),
thumbnails: traverseList(item, "thumbnails")
thumbnails: traverseList(item, "thumbnails"),
},
SongDetailed
SongDetailed,
)
}
@ -66,24 +66,24 @@ export default class SongParser {
.filter(run => "navigationEndpoint" in run)
.map(run => ({
artistId: traverseString(run, "browseId")(),
name: traverseString(run, "text")()
name: traverseString(run, "text")(),
})),
album: {
albumId: traverseString(flexColumns[2], "browseId")(),
name: traverseString(flexColumns[2], "runs", "text")()
name: traverseString(flexColumns[2], "runs", "text")(),
},
duration: Parser.parseDuration(
traverseString(item, "fixedColumns", "runs", "text")()
traverseString(item, "fixedColumns", "runs", "text")(),
),
thumbnails: traverseList(item, "thumbnails")
thumbnails: traverseList(item, "thumbnails"),
},
SongDetailed
SongDetailed,
)
}
public static parseArtistTopSong(
item: any,
artistBasic: ArtistBasic
artistBasic: ArtistBasic,
): Omit<SongDetailed, "duration"> {
const flexColumns = traverseList(item, "flexColumns")
const videoId = traverseString(item, "playlistItemData", "videoId")()
@ -96,11 +96,11 @@ export default class SongParser {
artists: [artistBasic],
album: {
albumId: traverseString(flexColumns[2], "browseId")(),
name: traverseString(flexColumns[2], "runs", "text")()
name: traverseString(flexColumns[2], "runs", "text")(),
},
thumbnails: traverseList(item, "thumbnails")
thumbnails: traverseList(item, "thumbnails"),
},
SongDetailed.omit({ duration: true })
SongDetailed.omit({ duration: true }),
)
}
@ -108,7 +108,7 @@ export default class SongParser {
item: any,
artists: ArtistBasic[],
albumBasic: AlbumBasic,
thumbnails: ThumbnailFull[]
thumbnails: ThumbnailFull[],
): SongDetailed {
const flexColumns = traverseList(item, "flexColumns")
const videoId = traverseString(item, "playlistItemData", "videoId")()
@ -121,11 +121,11 @@ export default class SongParser {
artists,
album: albumBasic,
duration: Parser.parseDuration(
traverseString(item, "fixedColumns", "runs", "text")()
traverseString(item, "fixedColumns", "runs", "text")(),
),
thumbnails
thumbnails,
},
SongDetailed
SongDetailed,
)
}
}

View File

@ -14,8 +14,8 @@ export default class VideoParser {
artists: [
{
artistId: traverseString(data, "videoDetails", "channelId")(),
name: traverseString(data, "author")()
}
name: traverseString(data, "author")(),
},
],
duration: +traverseString(data, "videoDetails", "lengthSeconds")(),
thumbnails: traverseList(data, "videoDetails", "thumbnails"),
@ -23,7 +23,7 @@ export default class VideoParser {
unlisted: traverse(data, "unlisted"),
familySafe: traverse(data, "familySafe"),
paid: traverse(data, "paid"),
tags: traverseList(data, "tags")
tags: traverseList(data, "tags"),
}
}
@ -39,23 +39,23 @@ export default class VideoParser {
.filter(run => "navigationEndpoint" in run)
.map(run => ({
artistId: traverseString(run, "browseId")(),
name: traverseString(run, "text")()
name: traverseString(run, "text")(),
})),
duration: Parser.parseDuration(traverseString(flexColumns[1], "text")(-1)),
thumbnails: traverseList(item, "thumbnails")
thumbnails: traverseList(item, "thumbnails"),
}
}
public static parseArtistTopVideo(
item: any,
artistBasic: ArtistBasic
artistBasic: ArtistBasic,
): Omit<VideoDetailed, "duration"> {
return {
type: "VIDEO",
videoId: traverseString(item, "videoId")(),
name: traverseString(item, "runs", "text")(),
artists: [artistBasic],
thumbnails: traverseList(item, "thumbnails")
thumbnails: traverseList(item, "thumbnails"),
}
}
@ -74,14 +74,14 @@ export default class VideoParser {
.filter(run => "navigationEndpoint" in run)
.map(run => ({
artistId: traverseString(run, "browseId")(),
name: traverseString(run, "text")()
name: traverseString(run, "text")(),
})),
duration: Parser.parseDuration(
traverseString(item, "fixedColumns", "runs", "text")()
traverseString(item, "fixedColumns", "runs", "text")(),
),
thumbnails: traverseList(item, "thumbnails")
thumbnails: traverseList(item, "thumbnails"),
},
VideoDetailed
VideoDetailed,
)
}
}

View File

@ -4,19 +4,19 @@ export type ThumbnailFull = z.infer<typeof ThumbnailFull>
export const ThumbnailFull = z.object({
url: z.string(),
width: z.number(),
height: z.number()
height: z.number(),
})
export type ArtistBasic = z.infer<typeof ArtistBasic>
export const ArtistBasic = z.object({
artistId: z.string(),
name: z.string()
name: z.string(),
})
export type AlbumBasic = z.infer<typeof AlbumBasic>
export const AlbumBasic = z.object({
albumId: z.string(),
name: z.string()
name: z.string(),
})
export type SongDetailed = z.infer<typeof SongDetailed>
@ -27,7 +27,7 @@ export const SongDetailed = z.object({
artists: z.array(ArtistBasic),
album: AlbumBasic,
duration: z.number(),
thumbnails: z.array(ThumbnailFull)
thumbnails: z.array(ThumbnailFull),
})
export type VideoDetailed = z.infer<typeof VideoDetailed>
@ -37,7 +37,7 @@ export const VideoDetailed = z.object({
name: z.string(),
artists: z.array(ArtistBasic),
duration: z.number(),
thumbnails: z.array(ThumbnailFull)
thumbnails: z.array(ThumbnailFull),
})
export type ArtistDetailed = z.infer<typeof ArtistDetailed>
@ -45,7 +45,7 @@ export const ArtistDetailed = z.object({
artistId: z.string(),
name: z.string(),
type: z.literal("ARTIST"),
thumbnails: z.array(ThumbnailFull)
thumbnails: z.array(ThumbnailFull),
})
export type AlbumDetailed = z.infer<typeof AlbumDetailed>
@ -56,7 +56,7 @@ export const AlbumDetailed = z.object({
name: z.string(),
artists: z.array(ArtistBasic),
year: z.number().nullable(),
thumbnails: z.array(ThumbnailFull)
thumbnails: z.array(ThumbnailFull),
})
export type SongFull = z.infer<typeof SongFull>
@ -69,7 +69,7 @@ export const SongFull = z.object({
thumbnails: z.array(ThumbnailFull),
description: z.string(),
formats: z.array(z.any()),
adaptiveFormats: z.array(z.any())
adaptiveFormats: z.array(z.any()),
})
export type VideoFull = z.infer<typeof VideoFull>
@ -84,7 +84,7 @@ export const VideoFull = z.object({
unlisted: z.boolean(),
familySafe: z.boolean(),
paid: z.boolean(),
tags: z.array(z.string())
tags: z.array(z.string()),
})
export type ArtistFull = z.infer<typeof ArtistFull>
@ -97,7 +97,7 @@ export const ArtistFull = z.object({
topSongs: z.array(SongDetailed.omit({ duration: true })),
topAlbums: z.array(AlbumDetailed),
topSingles: z.array(AlbumDetailed),
topVideos: z.array(VideoDetailed.omit({ duration: true }))
topVideos: z.array(VideoDetailed.omit({ duration: true })),
})
export type AlbumFull = z.infer<typeof AlbumFull>
@ -110,7 +110,7 @@ export const AlbumFull = z.object({
year: z.number().nullable(),
thumbnails: z.array(ThumbnailFull),
description: z.string(),
songs: z.array(SongDetailed)
songs: z.array(SongDetailed),
})
export type PlaylistFull = z.infer<typeof PlaylistFull>
@ -119,7 +119,7 @@ export const PlaylistFull = z.object({
playlistId: z.string(),
name: z.string(),
artist: ArtistBasic,
thumbnails: z.array(ThumbnailFull)
thumbnails: z.array(ThumbnailFull),
})
export type SearchResult = z.infer<typeof SearchResult>

View File

@ -13,11 +13,11 @@ export default <T extends z.Schema>(data: z.infer<T>, schema: T): z.infer<T> =>
{
schema: zodtojson(schema),
data,
error: result.error
error: result.error,
},
null,
2
)
2,
),
)
}
return data

View File

@ -1,6 +1,6 @@
const traverse = (data: any, ...keys: string[]) => {
const again = (data: any, key: string): any => {
let res = []
const res = []
if (data instanceof Object && key in data) {
res.push(data[key])
@ -12,7 +12,7 @@ const traverse = (data: any, ...keys: string[]) => {
res.push(
...Object.keys(data)
.map(k => again(data[k], key))
.flat()
.flat(),
)
}

View File

@ -1,7 +1,8 @@
import traverse from "./traverse"
export default (data: any, ...keys: string[]) => (index = 0): string => {
export default (data: any, ...keys: string[]) =>
(index = 0): string => {
const value = traverse(data, ...keys)
const flatValue = [value].flat().at(index)
return flatValue || ""
}
}