├── .eslintrc.js ├── .gitattributes ├── .github └── workflows │ ├── ci.yml │ └── release.yml ├── .gitignore ├── LICENSE ├── README-CN.md ├── README.md ├── package.json ├── pnpm-lock.yaml ├── src ├── api.ts ├── client.ts ├── index.ts └── type.ts ├── test └── index.ts └── tsconfig.json /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | parser: '@typescript-eslint/parser', 7 | parserOptions: { 8 | ecmaVersion: 11, 9 | sourceType: 'module' 10 | }, 11 | extends: [ 12 | 'standard', 13 | 'plugin:@typescript-eslint/recommended' 14 | ], 15 | plugins: ['@typescript-eslint'], 16 | rules: { 17 | semi: [2, 'never'] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | strategy: 12 | matrix: 13 | node-version: [16.x] 14 | steps: 15 | - uses: actions/checkout@v3 16 | 17 | - name: Setup Node.js environment ${{ matrix.node-version }} 18 | uses: actions/setup-node@v2 19 | with: 20 | node-version: ${{ matrix.node-version }} 21 | 22 | - name: Setup PNPM 23 | uses: pnpm/action-setup@v2 24 | with: 25 | version: 7 26 | run_install: true 27 | 28 | - name: ESLint check 29 | run: pnpm lint 30 | 31 | - name: Build 32 | run: pnpm build 33 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - "**" 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | strategy: 12 | matrix: 13 | node-version: [16.x] 14 | steps: 15 | - uses: actions/checkout@v3 16 | 17 | - name: Setup Node.js environment ${{ matrix.node-version }} 18 | uses: actions/setup-node@v2 19 | with: 20 | node-version: ${{ matrix.node-version }} 21 | 22 | - name: Setup PNPM 23 | uses: pnpm/action-setup@v2 24 | with: 25 | version: 7 26 | run_install: true 27 | 28 | - name: ESLint check 29 | run: pnpm lint 30 | 31 | - name: Build 32 | run: pnpm build 33 | 34 | publish-npm: 35 | needs: build 36 | runs-on: ubuntu-latest 37 | steps: 38 | - uses: actions/checkout@v3 39 | - uses: actions/setup-node@v2 40 | with: 41 | node-version: 16 42 | registry-url: https://registry.npmjs.org/ 43 | 44 | - name: Setup PNPM 45 | uses: pnpm/action-setup@v2 46 | with: 47 | version: 7 48 | run_install: true 49 | 50 | - name: Publish to NPM 51 | run: npm publish --access public 52 | env: 53 | NODE_AUTH_TOKEN: ${{ secrets.TOKEN_NPM_PUBLISH }} 54 | 55 | publish-github: 56 | needs: build 57 | runs-on: ubuntu-latest 58 | steps: 59 | - uses: actions/checkout@v3 60 | - uses: actions/setup-node@v2 61 | with: 62 | node-version: 16 63 | registry-url: https://npm.pkg.github.com/ 64 | scope: '@l2studio' 65 | 66 | - name: Setup PNPM 67 | uses: pnpm/action-setup@v2 68 | with: 69 | version: 7 70 | run_install: true 71 | 72 | - run: echo registry=https://npm.pkg.github.com/l2studio >> .npmrc 73 | - name: Publish to GitHub 74 | run: npm publish 75 | env: 76 | NODE_AUTH_TOKEN: ${{ secrets.TOKEN_GITHUB_PUBLISH }} 77 | 78 | release: 79 | needs: [build, publish-npm, publish-github] 80 | runs-on: ubuntu-latest 81 | steps: 82 | - name: Checkout 83 | uses: actions/checkout@v3 84 | with: 85 | # Fetch all history 86 | fetch-depth: 0 87 | 88 | - name: Generate Changelog 89 | id: changelog 90 | shell: bash 91 | env: 92 | CURRENT: ${{ github.ref }} 93 | # Special thanks to this post on Stack Overflow regarding change set between two tags: 94 | # https://stackoverflow.com/questions/12082981 95 | # Do note that actions/checkout will enter detach mode by default, so you won't have 96 | # access to HEAD ref. Use GitHub-Action-supplied `github.ref` instead. 97 | # Special thanks to this issue ticket regarding escaping newline: 98 | # https://github.com/actions/create-release/issues/25 99 | # We use Bash parameter expansion to do find-and-replace. 100 | # https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html 101 | # Also we cannot use git rev-list because it always prepend "commit " 102 | # See https://stackoverflow.com/questions/36927089/ 103 | run: | 104 | current_tag=${CURRENT/refs\/tags\//} 105 | last_tag=`git describe --tags --abbrev=0 "$current_tag"^ 2>/dev/null || echo` 106 | if [ $last_tag ]; then 107 | changelog=`git log --pretty="format:%H: %s" ${last_tag}..$current_tag` 108 | else 109 | changelog=`git log --pretty="format:%H: %s"` 110 | fi 111 | changelog="${changelog//'%'/'%25'}" 112 | changelog="${changelog//$'\n'/' %0A'}" 113 | echo "::set-output name=value::Change set since ${last_tag:-the beginning}: %0A%0A$changelog" 114 | 115 | - name: GitHub Release 116 | uses: softprops/action-gh-release@v1 117 | env: 118 | GITHUB_TOKEN: ${{ secrets.TOKEN_GITHUB_PUBLISH }} 119 | with: 120 | token: ${{ secrets.TOKEN_GITHUB_PUBLISH }} 121 | body: | 122 | ${{ steps.changelog.outputs.value }} 123 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### JetBrains template 3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 4 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 5 | 6 | # User-specific stuff 7 | .idea/**/workspace.xml 8 | .idea/**/tasks.xml 9 | .idea/**/usage.statistics.xml 10 | .idea/**/dictionaries 11 | .idea/**/shelf 12 | 13 | # Generated files 14 | .idea/**/contentModel.xml 15 | 16 | # Sensitive or high-churn files 17 | .idea/**/dataSources/ 18 | .idea/**/dataSources.ids 19 | .idea/**/dataSources.local.xml 20 | .idea/**/sqlDataSources.xml 21 | .idea/**/dynamic.xml 22 | .idea/**/uiDesigner.xml 23 | .idea/**/dbnavigator.xml 24 | 25 | # Gradle 26 | .idea/**/gradle.xml 27 | .idea/**/libraries 28 | 29 | # Gradle and Maven with auto-import 30 | # When using Gradle or Maven with auto-import, you should exclude module files, 31 | # since they will be recreated, and may cause churn. Uncomment if using 32 | # auto-import. 33 | # .idea/artifacts 34 | # .idea/compiler.xml 35 | # .idea/jarRepositories.xml 36 | # .idea/modules.xml 37 | # .idea/*.iml 38 | # .idea/modules 39 | # *.iml 40 | # *.ipr 41 | 42 | # CMake 43 | cmake-build-*/ 44 | 45 | # Mongo Explorer plugin 46 | .idea/**/mongoSettings.xml 47 | 48 | # File-based project format 49 | *.iws 50 | 51 | # IntelliJ 52 | out/ 53 | 54 | # mpeltonen/sbt-idea plugin 55 | .idea_modules/ 56 | 57 | # JIRA plugin 58 | atlassian-ide-plugin.xml 59 | 60 | # Cursive Clojure plugin 61 | .idea/replstate.xml 62 | 63 | # Crashlytics plugin (for Android Studio and IntelliJ) 64 | com_crashlytics_export_strings.xml 65 | crashlytics.properties 66 | crashlytics-build.properties 67 | fabric.properties 68 | 69 | # Editor-based Rest Client 70 | .idea/httpRequests 71 | 72 | # Android studio 3.1+ serialized cache file 73 | .idea/caches/build_file_checksums.ser 74 | 75 | ### Node template 76 | # Logs 77 | logs 78 | *.log 79 | npm-debug.log* 80 | yarn-debug.log* 81 | yarn-error.log* 82 | lerna-debug.log* 83 | 84 | # Diagnostic reports (https://nodejs.org/api/report.html) 85 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 86 | 87 | # Runtime data 88 | pids 89 | *.pid 90 | *.seed 91 | *.pid.lock 92 | 93 | # Directory for instrumented libs generated by jscoverage/JSCover 94 | lib-cov 95 | 96 | # Coverage directory used by tools like istanbul 97 | coverage 98 | *.lcov 99 | 100 | # nyc test coverage 101 | .nyc_output 102 | 103 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 104 | .grunt 105 | 106 | # Bower dependency directory (https://bower.io/) 107 | bower_components 108 | 109 | # node-waf configuration 110 | .lock-wscript 111 | 112 | # Compiled binary addons (https://nodejs.org/api/addons.html) 113 | build/Release 114 | 115 | # Dependency directories 116 | node_modules/ 117 | jspm_packages/ 118 | 119 | # Snowpack dependency directory (https://snowpack.dev/) 120 | web_modules/ 121 | 122 | # TypeScript cache 123 | *.tsbuildinfo 124 | 125 | # Optional npm cache directory 126 | .npm 127 | 128 | # Optional eslint cache 129 | .eslintcache 130 | 131 | # Microbundle cache 132 | .rpt2_cache/ 133 | .rts2_cache_cjs/ 134 | .rts2_cache_es/ 135 | .rts2_cache_umd/ 136 | 137 | # Optional REPL history 138 | .node_repl_history 139 | 140 | # Output of 'npm pack' 141 | *.tgz 142 | 143 | # Yarn Integrity file 144 | .yarn-integrity 145 | 146 | # dotenv environment variables file 147 | .env 148 | .env.test 149 | 150 | # parcel-bundler cache (https://parceljs.org/) 151 | .cache 152 | .parcel-cache 153 | 154 | # Next.js build output 155 | .next 156 | out 157 | 158 | # Nuxt.js build / generate output 159 | .nuxt 160 | dist 161 | 162 | # Gatsby files 163 | .cache/ 164 | # Comment in the public line in if your project uses Gatsby and not Next.js 165 | # https://nextjs.org/blog/next-9-1#public-directory-support 166 | # public 167 | 168 | # vuepress build output 169 | .vuepress/dist 170 | 171 | # Serverless directories 172 | .serverless/ 173 | 174 | # FuseBox cache 175 | .fusebox/ 176 | 177 | # DynamoDB Local files 178 | .dynamodb/ 179 | 180 | # TernJS port file 181 | .tern-port 182 | 183 | # Stores VSCode versions used for testing VSCode extensions 184 | .vscode-test 185 | 186 | # yarn v2 187 | .yarn/cache 188 | .yarn/unplugged 189 | .yarn/build-state.yml 190 | .yarn/install-state.gz 191 | .pnp.* 192 | 193 | # user custom 194 | node_modules/.yarn-integrity 195 | .npmrc 196 | lib/ 197 | test/.token 198 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README-CN.md: -------------------------------------------------------------------------------- 1 | - [English](README.md) 2 | - **简体中文** 3 | 4 | # L2 Studio - PicaComic API 5 | 6 |

7 | 8 | 9 |

10 | 11 | 一个用于 PicaComic 哔咔的 HTTP 网站 API 12 | 13 | ## 安装 14 | 15 | ```shell 16 | npm install --save @l2studio/picacomic-api 17 | # 或者 18 | pnpm i @l2studio/picacomic-api 19 | ``` 20 | 21 | ## API 22 | 23 | > 目前为 v0.2.0 版本的文档。旧版本另见:[v0.1.x](https://github.com/l2studio/picacomic-api/tree/0.1.13#readme) 24 | 25 | **此 v0.2.x 是破坏性更新,但是对类型定义更具体化。以及对代码的重构和优化。** 26 | 27 | ```typescript 28 | import { PicaComicAPI } from '@l2studio/picacomic-api' 29 | 30 | class PicaComicAPI { 31 | public readonly fetch: Got 32 | public readonly appOptions?: Partial 33 | public readonly reauthorizationTokenCallback?: (self: this) => string | undefined | Promise 34 | constructor (options?: PicaComicAPIOptions) 35 | } 36 | ``` 37 | 38 | ### API 选项 39 | 40 | ```typescript 41 | interface PicaComicOptions { 42 | api: string 43 | apiKey: string 44 | signatureKey: string 45 | accept: string 46 | channel: '1' | '2' | '3' 47 | version: string 48 | uuid: string 49 | platform: string 50 | buildVersion: string 51 | userAgent: string 52 | imageQuality: 'original' | 'low' | 'medium' | 'high' 53 | } 54 | 55 | interface PicaComicAPIOptions { 56 | // Got 实例或扩展选项(可选) 57 | // 请见: https://github.com/sindresorhus/got/tree/v11 58 | fetch?: Got | ExtendOptions 59 | 60 | // PicaComic app 客户端选项(可选) 61 | // 另见上: PicaComicOptions 62 | appOptions?: Partial 63 | 64 | // 用于在令牌无效时重新认证并返回新令牌的回调函数。(可选) 65 | // 例子: 66 | // async reauthorizationTokenCallback (self) { 67 | // console.log('令牌无效, 重新认证...') 68 | // const response = await self.signIn({ 69 | // email : '你的 PicaComic 哔咔账户邮箱', 70 | // password: '你的 PicaComic 哔咔账户密码' 71 | // }) 72 | // return response.data.token 73 | // } 74 | reauthorizationTokenCallback?: (self: PicaComicAPI) => string | undefined | Promise 75 | } 76 | ``` 77 | 78 | ### PicaComicError 79 | 80 | ```typescript 81 | class PicaComicError extends Error { 82 | readonly code: number 83 | readonly error: string 84 | readonly message: string 85 | readonly detail?: string 86 | } 87 | ``` 88 | 89 | ### .register 90 | 91 | ```typescript 92 | /** 93 | * 使用给定的有效负载注册一个 PicaComic 哔咔帐户。 94 | * 95 | * @param payload - RegisterPayload { 96 | * name - 昵称(2 - 50 字符) 97 | * email - 邮箱(允许: [0-9 a-z . _]) 98 | * password - 密码(大于 8 个字符) 99 | * question1 - 安全问题 1 100 | * question2 - 2 101 | * question3 - 3 102 | * answer1 - 安全问题 1 答案 103 | * answer2 - 2 答案 104 | * answer3 - 3 答案 105 | * birthday - 生日('YYYY-MM-DD' | Date | Milliseconds)需要年满 18 岁 106 | * gender - 性别('m' | 'f' | 'bot') 107 | * } 108 | * @return BaseResponse 109 | */ 110 | PicaComicAPI.register(payload: RegisterPayload): Promise> 111 | ``` 112 | 113 | ### .signIn 114 | 115 | ```typescript 116 | /** 117 | * 使用给定的电子邮件和密码有效负载登录到 PicaComic 哔咔帐户。 118 | * 119 | * @param payload - SignInPayload { 120 | * email - 你的哔咔账户邮箱 121 | * password - 密码 122 | * } 123 | * @return SignInResponse 124 | */ 125 | PicaComicAPI.signIn(payload: SignInPayload): Promise 126 | ``` 127 | 128 | ### .punchIn 129 | 130 | ```typescript 131 | /** 132 | * 使用给定的访问令牌有效负载打卡 PicaComic 哔咔帐户。 133 | * 134 | * @param payload - AuthorizationPayload { token - 访问令牌 } 135 | * @return PunchInResponse 136 | */ 137 | PicaComicAPI.punchIn(payload: AuthorizationPayload): Promise 138 | ``` 139 | 140 | ### .fetchUserProfile 141 | 142 | ```typescript 143 | /** 144 | * 使用给定的访问令牌有效负载获取用户档案。 145 | * 146 | * @param payload - AuthorizationPayload { token - 访问令牌 } 147 | * @return UserProfileResponse 148 | */ 149 | PicaComicAPI.fetchUserProfile(payload: AuthorizationPayload): Promise 150 | ``` 151 | 152 | ### .fetchUserFavourite 153 | 154 | ```typescript 155 | /** 156 | * 使用给定的有效负载获取用户收藏的漫画。 157 | * 158 | * @param payload - AuthorizationPayload & UserFavouritePayload { 159 | * token - 访问令牌 160 | * page - 页数(可选) 161 | * sort - 排序类型(可选) 162 | * } 163 | * @return UserFavouriteResponse 164 | */ 165 | PicaComicAPI.fetchUserFavourite(payload: AuthorizationPayload & UserFavouritePayload): Promise 166 | ``` 167 | 168 | ### .fetchCategories 169 | 170 | ```typescript 171 | /** 172 | * 使用给定的访问令牌有效负载获取所有分类。 173 | * 174 | * @param payload - AuthorizationPayload { token - 访问令牌 } 175 | * @return CategoriesResponse 176 | */ 177 | PicaComicAPI.fetchCategories(payload: AuthorizationPayload): Promise 178 | ``` 179 | 180 | ### .fetchComics 181 | 182 | ```typescript 183 | /** 184 | * 使用给定的有效负载获取漫画。 185 | * 186 | * @param payload - AuthorizationPayload & ComicsPayload { 187 | * token - 访问令牌 188 | * category - 分类名称(例如:'Cosplay') 189 | * page - 页数(可选) 190 | * sort - 排序(可选) 191 | * } 192 | * @return ComicsResponse 193 | */ 194 | PicaComicAPI.fetchComics(payload: AuthorizationPayload & ComicsPayload): Promise 195 | ``` 196 | 197 | ### .fetchComicDetail 198 | 199 | ```typescript 200 | /** 201 | * 使用给定的有效负载获取漫画详情。 202 | * 203 | * @param payload - AuthorizationPayload & ComicDetailPayload { 204 | * token - 访问令牌 205 | * comicId - 漫画 ID 206 | * } 207 | * @return ComicDetailResponse 208 | */ 209 | PicaComicAPI.fetchComicDetail(payload: AuthorizationPayload & ComicDetailPayload): Promise 210 | ``` 211 | 212 | ### .fetchComicEpisodes 213 | 214 | ```typescript 215 | /** 216 | * 使用给定的有效负载获取漫画分话。 217 | * 218 | * @param payload - AuthorizationPayload & ComicEpisodesPayload { 219 | * token - 访问令牌 220 | * comicId - 漫画 ID 221 | * page - 页数(可选) 222 | * } 223 | * @return ComicEpisodesResponse 224 | */ 225 | PicaComicAPI.fetchComicEpisodes(payload: AuthorizationPayload & ComicEpisodesPayload): Promise 226 | ``` 227 | 228 | ### .fetchComicEpisodePages 229 | 230 | ```typescript 231 | /** 232 | * 使用给定的有效负载获取指定漫画分话的页面。 233 | * 234 | * @param payload - AuthorizationPayload & ComicEpisodePagesPayload { 235 | * token - 访问令牌 236 | * comicId - 漫画 ID 237 | * order - 漫画分话顺序 238 | * page - 页数(可选) 239 | * } 240 | * @return ComicEpisodePagesResponse 241 | */ 242 | PicaComicAPI.fetchComicEpisodePages(payload: AuthorizationPayload & ComicEpisodePagesPayload): Promise 243 | ``` 244 | 245 | ### .fetchComicComments 246 | 247 | ```typescript 248 | /** 249 | * 使用给定的有效负载获取漫画评论。 250 | * 251 | * @param payload - AuthorizationPayload & ComicCommentsPayload { 252 | * token - 访问令牌 253 | * comicId - 漫画 ID 254 | * page - 页数(可选) 255 | * } 256 | * @return ComicCommentsResponse 257 | */ 258 | PicaComicAPI.fetchComicComments(payload: AuthorizationPayload & ComicCommentsPayload): Promise 259 | ``` 260 | 261 | ### .searchComics 262 | 263 | ```typescript 264 | /** 265 | * 使用给定的有效负载搜索漫画。 266 | * 267 | * @param payload - AuthorizationPayload & SearchComicsPayload { 268 | * token - 访问令牌 269 | * keyword - 关键字 270 | * categories - 分类名称数组(例如:['Cosplay'])(可选) 271 | * page - 页数(可选) 272 | * sort - 排序(可选) 273 | * } 274 | * @return SearchComicsResponse 275 | */ 276 | PicaComicAPI.searchComics(payload: AuthorizationPayload & SearchComicsPayload): Promise 277 | ``` 278 | 279 | ### .switchComicLike 280 | 281 | ```typescript 282 | /** 283 | * 使用给定的有效负载将漫画切换为喜欢或不喜欢。 284 | * 285 | * @param payload - AuthorizationPayload & ComicIdPayload { 286 | * toke - 访问令牌 287 | * comicId - 漫画 ID 288 | * } 289 | * @return SwitchComicLikeResponse 290 | */ 291 | PicaComicAPI.switchComicLike(payload: AuthorizationPayload & ComicIdPayload): Promise 292 | ``` 293 | 294 | ### .switchComicFavourite 295 | 296 | ```typescript 297 | /** 298 | * 使用给定的有效负载将漫画切换为收藏或取消收藏。 299 | * 300 | * @param payload - AuthorizationPayload & ComicIdPayload { 301 | * toke - 访问令牌 302 | * comicId - 漫画 ID 303 | * } 304 | * @return SwitchComicFavouriteResponse 305 | */ 306 | PicaComicAPI.switchComicFavourite(payload: AuthorizationPayload & ComicIdPayload): Promise 307 | ``` 308 | 309 | ### .setUserProfileSlogan 310 | 311 | ```typescript 312 | /** 313 | * 使用给定的有效负载设置用户档案的签名。 314 | * 315 | * @param payload - AuthorizationPayload & UserProfileSloganPayload { 316 | * toke - 访问令牌 317 | * slogan - 签名(不能是空白的) 318 | * } 319 | * @return BaseResponse 320 | */ 321 | PicaComicAPI.setUserProfileSlogan(payload: AuthorizationPayload & UserProfileSloganPayload): Promise> 322 | ``` 323 | 324 | ### .stringifyImageUrl 325 | 326 | ```typescript 327 | /** 328 | * 将给定的图像媒体数据字符串化为图像 URL 链接。 329 | * 330 | * @param payload - ImageMediaPayload = ImageMedia | { 331 | * path - 路径名称 332 | * fileServer - 文件服务器(可选) 333 | * } 334 | * @return string 335 | */ 336 | PicaComicAPI.stringifyImageUrl(payload: ImageMediaPayload): string 337 | ``` 338 | 339 | ### .createImageRequest 340 | 341 | ```typescript 342 | /** 343 | * 从给定的图像媒体数据创建一个图像请求。 344 | * 345 | * @param payload - ImageMediaPayload = ImageMedia | { 346 | * path - 路径名称 347 | * fileServer - 文件服务器(可选) 348 | * } 349 | * @return Request (Got request) 350 | */ 351 | PicaComicAPI.createImageRequest(payload: ImageMediaPayload): got.Request 352 | ``` 353 | 354 | ### .createImageRequestAsBuffer 355 | 356 | ```typescript 357 | /** 358 | * 从给定的图像媒体数据创建一个图像请求并写入到缓冲区。 359 | * 360 | * @param payload - ImageMediaPayload = ImageMedia | { 361 | * path - 路径名称 362 | * fileServer - 文件服务器(可选) 363 | * } 364 | * @return Buffer 365 | */ 366 | PicaComicAPI.createImageRequestAsBuffer(payload: ImageMediaPayload): Promise 367 | ``` 368 | 369 | ## 客户端 370 | 371 | 客户端只是对单个账户操作的封装,不需要自己去处理令牌失效的问题。 372 | 373 | > 注意: 客户端类似 API,但是不提供 `register` 和 `signIn` 方法。其他方法的 `payload` 参数不需要再提供 `token` 访问令牌属性。 374 | 375 | ```typescript 376 | import { PicaComicClient } from '@l2studio/picacomic-api' 377 | 378 | export class PicaComicClient { 379 | public readonly email: string 380 | public readonly password: string 381 | public readonly api: PicaComicAPI 382 | public readonly onTokenIssued?: (token: string) => void | Promise 383 | public token: string 384 | constructor (options: PicaComicClientOptions) 385 | } 386 | ``` 387 | 388 | ### 客户端选项 389 | 390 | ```typescript 391 | interface PicaComicClientOptions extends Omit { 392 | /// 继承于 PicaComicAPIOptions 选项 393 | /// 另见上 394 | fetch?: Got | ExtendOptions 395 | appOptions?: Partial 396 | /// 397 | 398 | /// 自有属性 399 | email: string // PicaComic 哔咔账户邮箱 400 | password: string // 密码 401 | token?: string // 账户访问令牌(可选) 402 | 403 | // 当令牌无效时,用于重新认证和使用新令牌的回调函数。(可选) 404 | // 例子: 405 | // onTokenIssued (token) { 406 | // console.log('新的令牌:', token) 407 | // fs.writeFileSync('token.txt', token) 408 | // } 409 | onTokenIssued?: (token: string) => void | Promise 410 | } 411 | ``` 412 | 413 | ### 例子 414 | 415 | 当令牌过期时,它将重新登录并更新令牌和持久化。无需每次都提供令牌。 416 | 417 | ```typescript 418 | import { PicaComicClient } from '@l2studio/picacomic-api' 419 | import path from 'path' 420 | import fs from 'fs' 421 | 422 | const tokenFile = path.join(__dirname, '.token') // 持久化令牌 423 | const picacomic = new PicaComicClient({ 424 | email : '你的 PicaComic 哔咔账户邮箱', 425 | password: '你的 PicaComic 哔咔账户密码', 426 | token: fs.existsSync(tokenFile) ? fs.readFileSync(tokenFile, 'utf8') : undefined, 427 | onTokenIssued (token) { 428 | console.log('新的令牌:', token) 429 | fs.writeFileSync(tokenFile, token) // 更新持久化令牌 430 | } 431 | }) 432 | 433 | ;(async () => { 434 | const response = await picacomic.fetchComics({ category: 'Cosplay' }) 435 | console.log(response) 436 | })() 437 | ``` 438 | 439 | ## 常见问题 440 | 441 | ### 如何配置 HTTP 代理 442 | 443 | > 另见 Got:[agent](https://github.com/sindresorhus/got/tree/v11#agent). 444 | 445 | 请配置 [`PicaComicAPIOptions`](#api-选项) 或 [`PicaComicClientOptions`](#客户端选项) 的 `fetch` 属性。 446 | 447 | 使用 [tunnel](https://github.com/koichik/node-tunnel) 的例子: 448 | 449 | ```typescript 450 | import { PicaComicClient } from '@l2studio/picacomic-api' 451 | import tunnel from 'tunnel' 452 | 453 | const picacomic = new PicaComicClient({ 454 | fetch: { 455 | agent: { 456 | https: tunnel.httpsOverHttp({ 457 | // 你的 Http 代理服务器主机和端口 458 | proxy: { 459 | host: '127.0.0.1', 460 | port: 10809 461 | } 462 | }) as any 463 | } 464 | }, 465 | ...other 466 | }) 467 | ``` 468 | 469 | ## 协议 470 | 471 | Apache-2.0 472 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | - **English** 2 | - [简体中文](README-CN.md) 3 | 4 | # L2 Studio - PicaComic API 5 | 6 |

7 | 8 | 9 |

10 | 11 | A library for PicaComic http web api 12 | 13 | ## Install 14 | 15 | ```shell 16 | npm install --save @l2studio/picacomic-api 17 | # or 18 | pnpm i @l2studio/picacomic-api 19 | ``` 20 | 21 | ## API 22 | 23 | > Currently the API documentation for version 0.2.x. See also [old documentation](https://github.com/l2studio/picacomic-api/tree/0.1.13#readme). 24 | 25 | **The v0.2.x is a breaking update, but more specific to type definitions. and code refactoring and optimization.** 26 | 27 | ```typescript 28 | import { PicaComicAPI } from '@l2studio/picacomic-api' 29 | 30 | class PicaComicAPI { 31 | public readonly fetch: Got 32 | public readonly appOptions?: Partial 33 | public readonly reauthorizationTokenCallback?: (self: this) => string | undefined | Promise 34 | constructor (options?: PicaComicAPIOptions) 35 | } 36 | ``` 37 | 38 | ### API Options 39 | 40 | ```typescript 41 | interface PicaComicOptions { 42 | api: string 43 | apiKey: string 44 | signatureKey: string 45 | accept: string 46 | channel: '1' | '2' | '3' 47 | version: string 48 | uuid: string 49 | platform: string 50 | buildVersion: string 51 | userAgent: string 52 | imageQuality: 'original' | 'low' | 'medium' | 'high' 53 | } 54 | 55 | interface PicaComicAPIOptions { 56 | // Got instance or options (optional) 57 | // See: https://github.com/sindresorhus/got/tree/v11 58 | fetch?: Got | ExtendOptions 59 | 60 | // PicaComic app client options (optional) 61 | // See above: PicaComicOptions 62 | appOptions?: Partial 63 | 64 | // Callback function used to re-authenticate and return a new token when the token is invalid. (optional) 65 | // Example: 66 | // async reauthorizationTokenCallback (self) { 67 | // console.log('Token invalid, re-authenticate...') 68 | // const response = await self.signIn({ 69 | // email : 'your picacomic account email', 70 | // password: 'your picacomic account password' 71 | // }) 72 | // return response.data.token 73 | // } 74 | reauthorizationTokenCallback?: (self: PicaComicAPI) => string | undefined | Promise 75 | } 76 | ``` 77 | 78 | ### PicaComicError 79 | 80 | ```typescript 81 | class PicaComicError extends Error { 82 | readonly code: number 83 | readonly error: string 84 | readonly message: string 85 | readonly detail?: string 86 | } 87 | ``` 88 | 89 | ### .register 90 | 91 | ```typescript 92 | /** 93 | * Register a PicaComic account with the given payload. 94 | * 95 | * @param payload - RegisterPayload { 96 | * name - Nickname (2 - 50 characters) 97 | * email - Email (Allow: [0-9 a-z . _]) 98 | * password - Password (Greater than 8 characters) 99 | * question1 - Security Question 1 100 | * question2 - 2 101 | * question3 - 3 102 | * answer1 - Security question 1 answer 103 | * answer2 - 2 answer 104 | * answer3 - 3 answer 105 | * birthday - Birthday ('YYYY-MM-DD' | Date | Milliseconds) Need to be 18 years or older 106 | * gender - Gender ('m' | 'f' | 'bot') 107 | * } 108 | * @return BaseResponse 109 | */ 110 | PicaComicAPI.register(payload: RegisterPayload): Promise> 111 | ``` 112 | 113 | ### .signIn 114 | 115 | ```typescript 116 | /** 117 | * Sign in to the PicaComic account with the given payload. 118 | * 119 | * @param payload - SignInPayload { 120 | * email - Your PicaComic account email 121 | * password - password 122 | * } 123 | * @return SignInResponse 124 | */ 125 | PicaComicAPI.signIn(payload: SignInPayload): Promise 126 | ``` 127 | 128 | ### .punchIn 129 | 130 | ```typescript 131 | /** 132 | * Punch in to the PicaComic account with the given payload. 133 | * 134 | * @param payload - AuthorizationPayload { token - Access token } 135 | * @return PunchInResponse 136 | */ 137 | PicaComicAPI.punchIn(payload: AuthorizationPayload): Promise 138 | ``` 139 | 140 | ### .fetchUserProfile 141 | 142 | ```typescript 143 | /** 144 | * Fetch user profile using the given payload. 145 | * 146 | * @param payload - AuthorizationPayload { token - Access token } 147 | * @return UserProfileResponse 148 | */ 149 | PicaComicAPI.fetchUserProfile(payload: AuthorizationPayload): Promise 150 | ``` 151 | 152 | ### .fetchUserFavourite 153 | 154 | ```typescript 155 | /** 156 | * Fetch user favourite comics using the given payload. 157 | * 158 | * @param payload - AuthorizationPayload & UserFavouritePayload { 159 | * token - Access token 160 | * page - Page number (optional) 161 | * sort - Sorting type (optional) 162 | * } 163 | * @return UserFavouriteResponse 164 | */ 165 | PicaComicAPI.fetchUserFavourite(payload: AuthorizationPayload & UserFavouritePayload): Promise 166 | ``` 167 | 168 | ### .fetchCategories 169 | 170 | ```typescript 171 | /** 172 | * Fetch all categories using the given payload. 173 | * 174 | * @param payload - AuthorizationPayload { token - Access token } 175 | * @return CategoriesResponse 176 | */ 177 | PicaComicAPI.fetchCategories(payload: AuthorizationPayload): Promise 178 | ``` 179 | 180 | ### .fetchComics 181 | 182 | ```typescript 183 | /** 184 | * Fetch comics using the given payload. 185 | * 186 | * @param payload - AuthorizationPayload & ComicsPayload { 187 | * token - Access token 188 | * category - Specify category name (e.g.: 'Cosplay') 189 | * page - Page number (optional) 190 | * sort - Sorting type (optional) 191 | * } 192 | * @return ComicsResponse 193 | */ 194 | PicaComicAPI.fetchComics(payload: AuthorizationPayload & ComicsPayload): Promise 195 | ``` 196 | 197 | ### .fetchComicDetail 198 | 199 | ```typescript 200 | /** 201 | * Fetch comic detail using the given payload. 202 | * 203 | * @param payload - AuthorizationPayload & ComicDetailPayload { 204 | * token - Access token 205 | * comicId - Specify comic id 206 | * } 207 | * @return ComicDetailResponse 208 | */ 209 | PicaComicAPI.fetchComicDetail(payload: AuthorizationPayload & ComicDetailPayload): Promise 210 | ``` 211 | 212 | ### .fetchComicEpisodes 213 | 214 | ```typescript 215 | /** 216 | * Fetch comic episodes using the given payload. 217 | * 218 | * @param payload - AuthorizationPayload & ComicEpisodesPayload { 219 | * token - Access token 220 | * comicId - Specify comic id 221 | * page - Page number (optional) 222 | * } 223 | * @return ComicEpisodesResponse 224 | */ 225 | PicaComicAPI.fetchComicEpisodes(payload: AuthorizationPayload & ComicEpisodesPayload): Promise 226 | ``` 227 | 228 | ### .fetchComicEpisodePages 229 | 230 | ```typescript 231 | /** 232 | * Fetch pages of the specified comic episode using the given payload. 233 | * 234 | * @param payload - AuthorizationPayload & ComicEpisodePagesPayload { 235 | * token - Access token 236 | * comicId - Specify comic id 237 | * order - Specify episode order of the comic 238 | * page - Page number (optional) 239 | * } 240 | * @return ComicEpisodePagesResponse 241 | */ 242 | PicaComicAPI.fetchComicEpisodePages(payload: AuthorizationPayload & ComicEpisodePagesPayload): Promise 243 | ``` 244 | 245 | ### .fetchComicComments 246 | 247 | ```typescript 248 | /** 249 | * Fetch comic comments using the given payload. 250 | * 251 | * @param payload - AuthorizationPayload & ComicCommentsPayload { 252 | * token - Access token 253 | * comicId - Specify comic id 254 | * page - Page number (optional) 255 | * } 256 | * @return ComicCommentsResponse 257 | */ 258 | PicaComicAPI.fetchComicComments(payload: AuthorizationPayload & ComicCommentsPayload): Promise 259 | ``` 260 | 261 | ### .searchComics 262 | 263 | ```typescript 264 | /** 265 | * Search comics using the given payload. 266 | * 267 | * @param payload - AuthorizationPayload & SearchComicsPayload { 268 | * token - Access token 269 | * keyword - Keyword 270 | * categories - Specify category name array (e.g.: ['Cosplay']) (optional) 271 | * page - Page number (optional) 272 | * sort - Sorting type (optional) 273 | * } 274 | * @return SearchComicsResponse 275 | */ 276 | PicaComicAPI.searchComics(payload: AuthorizationPayload & SearchComicsPayload): Promise 277 | ``` 278 | 279 | ### .switchComicLike 280 | 281 | ```typescript 282 | /** 283 | * Switch the comic as like or unlike using the given payload. 284 | * 285 | * @param payload - AuthorizationPayload & ComicIdPayload { 286 | * toke - Access token 287 | * comicId - Specify comic id 288 | * } 289 | * @return SwitchComicLikeResponse 290 | */ 291 | PicaComicAPI.switchComicLike(payload: AuthorizationPayload & ComicIdPayload): Promise 292 | ``` 293 | 294 | ### .switchComicFavourite 295 | 296 | ```typescript 297 | /** 298 | * Switch the comic as favourite or un_favourite using the given payload. 299 | * 300 | * @param payload - AuthorizationPayload & ComicIdPayload { 301 | * toke - Access token 302 | * comicId - Specify comic id 303 | * } 304 | * @return SwitchComicFavouriteResponse 305 | */ 306 | PicaComicAPI.switchComicFavourite(payload: AuthorizationPayload & ComicIdPayload): Promise 307 | ``` 308 | 309 | ### .setUserProfileSlogan 310 | 311 | ```typescript 312 | /** 313 | * Set the slogan of the user profile with the given payload. 314 | * 315 | * @param payload - AuthorizationPayload & UserProfileSloganPayload { 316 | * toke - Access token 317 | * slogan - Slogan (Cannot be blank) 318 | * } 319 | * @return BaseResponse 320 | */ 321 | PicaComicAPI.setUserProfileSlogan(payload: AuthorizationPayload & UserProfileSloganPayload): Promise> 322 | ``` 323 | 324 | ### .stringifyImageUrl 325 | 326 | ```typescript 327 | /** 328 | * Stringify the given image media data into image url. 329 | * 330 | * @param payload - ImageMediaPayload = ImageMedia | { 331 | * path - Path name 332 | * fileServer - File server (Optional) 333 | * } 334 | * @return string 335 | */ 336 | PicaComicAPI.stringifyImageUrl(payload: ImageMediaPayload): string 337 | ``` 338 | 339 | ### .createImageRequest 340 | 341 | ```typescript 342 | /** 343 | * Create an image request from the given image media data. 344 | * 345 | * @param payload - ImageMediaPayload = ImageMedia | { 346 | * path - Path name 347 | * fileServer - File server (Optional) 348 | * } 349 | * @return Request (Got request) 350 | */ 351 | PicaComicAPI.createImageRequest(payload: ImageMediaPayload): got.Request 352 | ``` 353 | 354 | ### .createImageRequestAsBuffer 355 | 356 | ```typescript 357 | /** 358 | * Create an image request and as buffer from the given image media data. 359 | * 360 | * @param payload - ImageMediaPayload = ImageMedia | { 361 | * path - Path name 362 | * fileServer - File server (Optional) 363 | * } 364 | * @return Buffer 365 | */ 366 | PicaComicAPI.createImageRequestAsBuffer(payload: ImageMediaPayload): Promise 367 | ``` 368 | 369 | ## Client 370 | 371 | The client is just a wrapper for a single account operation, and does not need to handle the problem of token invalidation by itself. 372 | 373 | > Note: The client is similar to the API, but does not provide `register` and `signIn` methods. The `payload` parameters of other methods do not need to provide the `token` access token property. 374 | 375 | ```typescript 376 | import { PicaComicClient } from '@l2studio/picacomic-api' 377 | 378 | export class PicaComicClient { 379 | public readonly email: string 380 | public readonly password: string 381 | public readonly api: PicaComicAPI 382 | public readonly onTokenIssued?: (token: string) => void | Promise 383 | public token: string 384 | constructor (options: PicaComicClientOptions) 385 | } 386 | ``` 387 | 388 | ### Client Options 389 | 390 | ```typescript 391 | interface PicaComicClientOptions extends Omit { 392 | /// Extende PicaComicAPIOptions options 393 | /// See above 394 | fetch?: Got | ExtendOptions 395 | appOptions?: Partial 396 | /// 397 | 398 | // Owned options 399 | email: string // PicaComic account email 400 | password: string // PicaComic account password 401 | token?: string // PicaComic account access token (Optional) 402 | 403 | // Callback function for re-authenticate and consuming a new token when the token is invalid. (Optional) 404 | // Example: 405 | // onTokenIssued (token) { 406 | // console.log('New token:', token) 407 | // fs.writeFileSync('token.txt', token) 408 | // } 409 | onTokenIssued?: (token: string) => void | Promise 410 | } 411 | ``` 412 | 413 | ### Example 414 | 415 | When the token expires, it will re-login and renew the token and persistence. No need to provide token every time. 416 | 417 | ```typescript 418 | import { PicaComicClient } from '@l2studio/picacomic-api' 419 | import path from 'path' 420 | import fs from 'fs' 421 | 422 | const tokenFile = path.join(__dirname, '.token') // Persistent token 423 | const picacomic = new PicaComicClient({ 424 | email : 'your picacomic email', 425 | password: 'your picacomic password', 426 | token: fs.existsSync(tokenFile) ? fs.readFileSync(tokenFile, 'utf8') : undefined, 427 | onTokenIssued (token) { 428 | console.log('New token:', token) 429 | fs.writeFileSync(tokenFile, token) // Update persistent token 430 | } 431 | }) 432 | 433 | ;(async () => { 434 | const response = await picacomic.fetchComics({ category: 'Cosplay' }) 435 | console.log(response) 436 | })() 437 | ``` 438 | 439 | ## FAQ 440 | 441 | ### How to configure http proxy 442 | 443 | > See also Got [agent](https://github.com/sindresorhus/got/tree/v11#agent). 444 | 445 | Please configure the `fetch` property of [`PicaComicAPIOptions`](#api-options) or [`PicaComicClientOptions`](#client-options). 446 | 447 | Example using [tunnel](https://github.com/koichik/node-tunnel): 448 | 449 | ```typescript 450 | import { PicaComicClient } from '@l2studio/picacomic-api' 451 | import tunnel from 'tunnel' 452 | 453 | const picacomic = new PicaComicClient({ 454 | fetch: { 455 | agent: { 456 | https: tunnel.httpsOverHttp({ 457 | // Your http proxy server host and port 458 | proxy: { 459 | host: '127.0.0.1', 460 | port: 10809 461 | } 462 | }) as any 463 | } 464 | }, 465 | ...other 466 | }) 467 | ``` 468 | 469 | ## License 470 | 471 | Apache-2.0 472 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@l2studio/picacomic-api", 3 | "version": "0.2.1", 4 | "description": "A library for PicaComic http web api", 5 | "main": "lib/index.js", 6 | "types": "lib/index.d.ts", 7 | "repository": "https://github.com/l2studio/picacomic-api.git", 8 | "author": "lgou2w ", 9 | "license": "Apache-2.0", 10 | "engines": { 11 | "node": "^14.17.0 || >=16.0.0" 12 | }, 13 | "scripts": { 14 | "clean": "rimraf lib coverage", 15 | "build": "npm run clean && tsc", 16 | "test": "cross-env DEBUG='lgou2w:*' ts-node -T -P tsconfig.json test/index.ts", 17 | "lint": "eslint --ext .js,.ts --ignore-path .gitignore .", 18 | "prepublishOnly": "npm run lint && npm run build" 19 | }, 20 | "files": [ 21 | "lib" 22 | ], 23 | "keywords": [ 24 | "l2studio", 25 | "lgou2w", 26 | "picacomic-api", 27 | "picacomic-client", 28 | "picacomic", 29 | "hentai", 30 | "hentai-cosplay", 31 | "r18", 32 | "r18-cosplay", 33 | "cosplay" 34 | ], 35 | "dependencies": { 36 | "got": "^11.8.6", 37 | "uuid": "^9.0.0" 38 | }, 39 | "devDependencies": { 40 | "@types/node": "^18.16.0", 41 | "@types/tunnel": "^0.0.3", 42 | "@types/uuid": "^9.0.1", 43 | "@typescript-eslint/eslint-plugin": "^5.59.0", 44 | "@typescript-eslint/parser": "^5.59.0", 45 | "cross-env": "^7.0.3", 46 | "eslint": "^8.39.0", 47 | "eslint-config-standard": "^17.0.0", 48 | "eslint-plugin-import": "^2.27.5", 49 | "eslint-plugin-n": "^15.7.0", 50 | "eslint-plugin-promise": "^6.1.1", 51 | "rimraf": "^5.0.0", 52 | "ts-node": "^10.9.1", 53 | "tunnel": "^0.0.6", 54 | "typescript": "^5.0.4" 55 | }, 56 | "peerDependencies": { 57 | "got": "^11.0.0" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '6.0' 2 | 3 | dependencies: 4 | got: 5 | specifier: ^11.8.6 6 | version: 11.8.6 7 | uuid: 8 | specifier: ^9.0.0 9 | version: 9.0.0 10 | 11 | devDependencies: 12 | '@types/node': 13 | specifier: ^18.16.0 14 | version: 18.16.0 15 | '@types/tunnel': 16 | specifier: ^0.0.3 17 | version: 0.0.3 18 | '@types/uuid': 19 | specifier: ^9.0.1 20 | version: 9.0.1 21 | '@typescript-eslint/eslint-plugin': 22 | specifier: ^5.59.0 23 | version: 5.59.0(@typescript-eslint/parser@5.59.0)(eslint@8.39.0)(typescript@5.0.4) 24 | '@typescript-eslint/parser': 25 | specifier: ^5.59.0 26 | version: 5.59.0(eslint@8.39.0)(typescript@5.0.4) 27 | cross-env: 28 | specifier: ^7.0.3 29 | version: 7.0.3 30 | eslint: 31 | specifier: ^8.39.0 32 | version: 8.39.0 33 | eslint-config-standard: 34 | specifier: ^17.0.0 35 | version: 17.0.0(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.39.0) 36 | eslint-plugin-import: 37 | specifier: ^2.27.5 38 | version: 2.27.5(@typescript-eslint/parser@5.59.0)(eslint@8.39.0) 39 | eslint-plugin-n: 40 | specifier: ^15.7.0 41 | version: 15.7.0(eslint@8.39.0) 42 | eslint-plugin-promise: 43 | specifier: ^6.1.1 44 | version: 6.1.1(eslint@8.39.0) 45 | rimraf: 46 | specifier: ^5.0.0 47 | version: 5.0.0 48 | ts-node: 49 | specifier: ^10.9.1 50 | version: 10.9.1(@types/node@18.16.0)(typescript@5.0.4) 51 | tunnel: 52 | specifier: ^0.0.6 53 | version: 0.0.6 54 | typescript: 55 | specifier: ^5.0.4 56 | version: 5.0.4 57 | 58 | packages: 59 | 60 | /@cspotcode/source-map-support@0.8.1: 61 | resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} 62 | engines: {node: '>=12'} 63 | dependencies: 64 | '@jridgewell/trace-mapping': 0.3.9 65 | dev: true 66 | 67 | /@eslint-community/eslint-utils@4.4.0(eslint@8.39.0): 68 | resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} 69 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 70 | peerDependencies: 71 | eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 72 | dependencies: 73 | eslint: 8.39.0 74 | eslint-visitor-keys: 3.4.0 75 | dev: true 76 | 77 | /@eslint-community/regexpp@4.5.0: 78 | resolution: {integrity: sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==} 79 | engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} 80 | dev: true 81 | 82 | /@eslint/eslintrc@2.0.2: 83 | resolution: {integrity: sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==} 84 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 85 | dependencies: 86 | ajv: 6.12.6 87 | debug: 4.3.4 88 | espree: 9.5.1 89 | globals: 13.20.0 90 | ignore: 5.2.4 91 | import-fresh: 3.3.0 92 | js-yaml: 4.1.0 93 | minimatch: 3.1.2 94 | strip-json-comments: 3.1.1 95 | transitivePeerDependencies: 96 | - supports-color 97 | dev: true 98 | 99 | /@eslint/js@8.39.0: 100 | resolution: {integrity: sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng==} 101 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 102 | dev: true 103 | 104 | /@humanwhocodes/config-array@0.11.8: 105 | resolution: {integrity: sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==} 106 | engines: {node: '>=10.10.0'} 107 | dependencies: 108 | '@humanwhocodes/object-schema': 1.2.1 109 | debug: 4.3.4 110 | minimatch: 3.1.2 111 | transitivePeerDependencies: 112 | - supports-color 113 | dev: true 114 | 115 | /@humanwhocodes/module-importer@1.0.1: 116 | resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} 117 | engines: {node: '>=12.22'} 118 | dev: true 119 | 120 | /@humanwhocodes/object-schema@1.2.1: 121 | resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} 122 | dev: true 123 | 124 | /@jridgewell/resolve-uri@3.1.1: 125 | resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} 126 | engines: {node: '>=6.0.0'} 127 | dev: true 128 | 129 | /@jridgewell/sourcemap-codec@1.4.15: 130 | resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} 131 | dev: true 132 | 133 | /@jridgewell/trace-mapping@0.3.9: 134 | resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} 135 | dependencies: 136 | '@jridgewell/resolve-uri': 3.1.1 137 | '@jridgewell/sourcemap-codec': 1.4.15 138 | dev: true 139 | 140 | /@nodelib/fs.scandir@2.1.5: 141 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 142 | engines: {node: '>= 8'} 143 | dependencies: 144 | '@nodelib/fs.stat': 2.0.5 145 | run-parallel: 1.2.0 146 | dev: true 147 | 148 | /@nodelib/fs.stat@2.0.5: 149 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 150 | engines: {node: '>= 8'} 151 | dev: true 152 | 153 | /@nodelib/fs.walk@1.2.8: 154 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 155 | engines: {node: '>= 8'} 156 | dependencies: 157 | '@nodelib/fs.scandir': 2.1.5 158 | fastq: 1.15.0 159 | dev: true 160 | 161 | /@pkgjs/parseargs@0.11.0: 162 | resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} 163 | engines: {node: '>=14'} 164 | requiresBuild: true 165 | dev: true 166 | optional: true 167 | 168 | /@sindresorhus/is@4.6.0: 169 | resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} 170 | engines: {node: '>=10'} 171 | dev: false 172 | 173 | /@szmarczak/http-timer@4.0.6: 174 | resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} 175 | engines: {node: '>=10'} 176 | dependencies: 177 | defer-to-connect: 2.0.1 178 | dev: false 179 | 180 | /@tsconfig/node10@1.0.9: 181 | resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} 182 | dev: true 183 | 184 | /@tsconfig/node12@1.0.11: 185 | resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} 186 | dev: true 187 | 188 | /@tsconfig/node14@1.0.3: 189 | resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} 190 | dev: true 191 | 192 | /@tsconfig/node16@1.0.3: 193 | resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==} 194 | dev: true 195 | 196 | /@types/cacheable-request@6.0.3: 197 | resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} 198 | dependencies: 199 | '@types/http-cache-semantics': 4.0.1 200 | '@types/keyv': 3.1.4 201 | '@types/node': 18.16.0 202 | '@types/responselike': 1.0.0 203 | dev: false 204 | 205 | /@types/http-cache-semantics@4.0.1: 206 | resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==} 207 | dev: false 208 | 209 | /@types/json-schema@7.0.11: 210 | resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} 211 | dev: true 212 | 213 | /@types/json5@0.0.29: 214 | resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} 215 | dev: true 216 | 217 | /@types/keyv@3.1.4: 218 | resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} 219 | dependencies: 220 | '@types/node': 18.16.0 221 | dev: false 222 | 223 | /@types/node@18.16.0: 224 | resolution: {integrity: sha512-BsAaKhB+7X+H4GnSjGhJG9Qi8Tw+inU9nJDwmD5CgOmBLEI6ArdhikpLX7DjbjDRDTbqZzU2LSQNZg8WGPiSZQ==} 225 | 226 | /@types/responselike@1.0.0: 227 | resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} 228 | dependencies: 229 | '@types/node': 18.16.0 230 | dev: false 231 | 232 | /@types/semver@7.3.13: 233 | resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==} 234 | dev: true 235 | 236 | /@types/tunnel@0.0.3: 237 | resolution: {integrity: sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA==} 238 | dependencies: 239 | '@types/node': 18.16.0 240 | dev: true 241 | 242 | /@types/uuid@9.0.1: 243 | resolution: {integrity: sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==} 244 | dev: true 245 | 246 | /@typescript-eslint/eslint-plugin@5.59.0(@typescript-eslint/parser@5.59.0)(eslint@8.39.0)(typescript@5.0.4): 247 | resolution: {integrity: sha512-p0QgrEyrxAWBecR56gyn3wkG15TJdI//eetInP3zYRewDh0XS+DhB3VUAd3QqvziFsfaQIoIuZMxZRB7vXYaYw==} 248 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 249 | peerDependencies: 250 | '@typescript-eslint/parser': ^5.0.0 251 | eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 252 | typescript: '*' 253 | peerDependenciesMeta: 254 | typescript: 255 | optional: true 256 | dependencies: 257 | '@eslint-community/regexpp': 4.5.0 258 | '@typescript-eslint/parser': 5.59.0(eslint@8.39.0)(typescript@5.0.4) 259 | '@typescript-eslint/scope-manager': 5.59.0 260 | '@typescript-eslint/type-utils': 5.59.0(eslint@8.39.0)(typescript@5.0.4) 261 | '@typescript-eslint/utils': 5.59.0(eslint@8.39.0)(typescript@5.0.4) 262 | debug: 4.3.4 263 | eslint: 8.39.0 264 | grapheme-splitter: 1.0.4 265 | ignore: 5.2.4 266 | natural-compare-lite: 1.4.0 267 | semver: 7.5.0 268 | tsutils: 3.21.0(typescript@5.0.4) 269 | typescript: 5.0.4 270 | transitivePeerDependencies: 271 | - supports-color 272 | dev: true 273 | 274 | /@typescript-eslint/parser@5.59.0(eslint@8.39.0)(typescript@5.0.4): 275 | resolution: {integrity: sha512-qK9TZ70eJtjojSUMrrEwA9ZDQ4N0e/AuoOIgXuNBorXYcBDk397D2r5MIe1B3cok/oCtdNC5j+lUUpVB+Dpb+w==} 276 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 277 | peerDependencies: 278 | eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 279 | typescript: '*' 280 | peerDependenciesMeta: 281 | typescript: 282 | optional: true 283 | dependencies: 284 | '@typescript-eslint/scope-manager': 5.59.0 285 | '@typescript-eslint/types': 5.59.0 286 | '@typescript-eslint/typescript-estree': 5.59.0(typescript@5.0.4) 287 | debug: 4.3.4 288 | eslint: 8.39.0 289 | typescript: 5.0.4 290 | transitivePeerDependencies: 291 | - supports-color 292 | dev: true 293 | 294 | /@typescript-eslint/scope-manager@5.59.0: 295 | resolution: {integrity: sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==} 296 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 297 | dependencies: 298 | '@typescript-eslint/types': 5.59.0 299 | '@typescript-eslint/visitor-keys': 5.59.0 300 | dev: true 301 | 302 | /@typescript-eslint/type-utils@5.59.0(eslint@8.39.0)(typescript@5.0.4): 303 | resolution: {integrity: sha512-d/B6VSWnZwu70kcKQSCqjcXpVH+7ABKH8P1KNn4K7j5PXXuycZTPXF44Nui0TEm6rbWGi8kc78xRgOC4n7xFgA==} 304 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 305 | peerDependencies: 306 | eslint: '*' 307 | typescript: '*' 308 | peerDependenciesMeta: 309 | typescript: 310 | optional: true 311 | dependencies: 312 | '@typescript-eslint/typescript-estree': 5.59.0(typescript@5.0.4) 313 | '@typescript-eslint/utils': 5.59.0(eslint@8.39.0)(typescript@5.0.4) 314 | debug: 4.3.4 315 | eslint: 8.39.0 316 | tsutils: 3.21.0(typescript@5.0.4) 317 | typescript: 5.0.4 318 | transitivePeerDependencies: 319 | - supports-color 320 | dev: true 321 | 322 | /@typescript-eslint/types@5.59.0: 323 | resolution: {integrity: sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==} 324 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 325 | dev: true 326 | 327 | /@typescript-eslint/typescript-estree@5.59.0(typescript@5.0.4): 328 | resolution: {integrity: sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==} 329 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 330 | peerDependencies: 331 | typescript: '*' 332 | peerDependenciesMeta: 333 | typescript: 334 | optional: true 335 | dependencies: 336 | '@typescript-eslint/types': 5.59.0 337 | '@typescript-eslint/visitor-keys': 5.59.0 338 | debug: 4.3.4 339 | globby: 11.1.0 340 | is-glob: 4.0.3 341 | semver: 7.5.0 342 | tsutils: 3.21.0(typescript@5.0.4) 343 | typescript: 5.0.4 344 | transitivePeerDependencies: 345 | - supports-color 346 | dev: true 347 | 348 | /@typescript-eslint/utils@5.59.0(eslint@8.39.0)(typescript@5.0.4): 349 | resolution: {integrity: sha512-GGLFd+86drlHSvPgN/el6dRQNYYGOvRSDVydsUaQluwIW3HvbXuxyuD5JETvBt/9qGYe+lOrDk6gRrWOHb/FvA==} 350 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 351 | peerDependencies: 352 | eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 353 | dependencies: 354 | '@eslint-community/eslint-utils': 4.4.0(eslint@8.39.0) 355 | '@types/json-schema': 7.0.11 356 | '@types/semver': 7.3.13 357 | '@typescript-eslint/scope-manager': 5.59.0 358 | '@typescript-eslint/types': 5.59.0 359 | '@typescript-eslint/typescript-estree': 5.59.0(typescript@5.0.4) 360 | eslint: 8.39.0 361 | eslint-scope: 5.1.1 362 | semver: 7.5.0 363 | transitivePeerDependencies: 364 | - supports-color 365 | - typescript 366 | dev: true 367 | 368 | /@typescript-eslint/visitor-keys@5.59.0: 369 | resolution: {integrity: sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==} 370 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 371 | dependencies: 372 | '@typescript-eslint/types': 5.59.0 373 | eslint-visitor-keys: 3.4.0 374 | dev: true 375 | 376 | /acorn-jsx@5.3.2(acorn@8.8.2): 377 | resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} 378 | peerDependencies: 379 | acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 380 | dependencies: 381 | acorn: 8.8.2 382 | dev: true 383 | 384 | /acorn-walk@8.2.0: 385 | resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} 386 | engines: {node: '>=0.4.0'} 387 | dev: true 388 | 389 | /acorn@8.8.2: 390 | resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} 391 | engines: {node: '>=0.4.0'} 392 | hasBin: true 393 | dev: true 394 | 395 | /ajv@6.12.6: 396 | resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} 397 | dependencies: 398 | fast-deep-equal: 3.1.3 399 | fast-json-stable-stringify: 2.1.0 400 | json-schema-traverse: 0.4.1 401 | uri-js: 4.4.1 402 | dev: true 403 | 404 | /ansi-regex@5.0.1: 405 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 406 | engines: {node: '>=8'} 407 | dev: true 408 | 409 | /ansi-styles@4.3.0: 410 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 411 | engines: {node: '>=8'} 412 | dependencies: 413 | color-convert: 2.0.1 414 | dev: true 415 | 416 | /arg@4.1.3: 417 | resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} 418 | dev: true 419 | 420 | /argparse@2.0.1: 421 | resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 422 | dev: true 423 | 424 | /array-buffer-byte-length@1.0.0: 425 | resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} 426 | dependencies: 427 | call-bind: 1.0.2 428 | is-array-buffer: 3.0.2 429 | dev: true 430 | 431 | /array-includes@3.1.6: 432 | resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==} 433 | engines: {node: '>= 0.4'} 434 | dependencies: 435 | call-bind: 1.0.2 436 | define-properties: 1.2.0 437 | es-abstract: 1.21.2 438 | get-intrinsic: 1.2.0 439 | is-string: 1.0.7 440 | dev: true 441 | 442 | /array-union@2.1.0: 443 | resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} 444 | engines: {node: '>=8'} 445 | dev: true 446 | 447 | /array.prototype.flat@1.3.1: 448 | resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==} 449 | engines: {node: '>= 0.4'} 450 | dependencies: 451 | call-bind: 1.0.2 452 | define-properties: 1.2.0 453 | es-abstract: 1.21.2 454 | es-shim-unscopables: 1.0.0 455 | dev: true 456 | 457 | /array.prototype.flatmap@1.3.1: 458 | resolution: {integrity: sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==} 459 | engines: {node: '>= 0.4'} 460 | dependencies: 461 | call-bind: 1.0.2 462 | define-properties: 1.2.0 463 | es-abstract: 1.21.2 464 | es-shim-unscopables: 1.0.0 465 | dev: true 466 | 467 | /available-typed-arrays@1.0.5: 468 | resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} 469 | engines: {node: '>= 0.4'} 470 | dev: true 471 | 472 | /balanced-match@1.0.2: 473 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 474 | dev: true 475 | 476 | /brace-expansion@1.1.11: 477 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 478 | dependencies: 479 | balanced-match: 1.0.2 480 | concat-map: 0.0.1 481 | dev: true 482 | 483 | /brace-expansion@2.0.1: 484 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 485 | dependencies: 486 | balanced-match: 1.0.2 487 | dev: true 488 | 489 | /braces@3.0.2: 490 | resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} 491 | engines: {node: '>=8'} 492 | dependencies: 493 | fill-range: 7.0.1 494 | dev: true 495 | 496 | /builtins@5.0.1: 497 | resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} 498 | dependencies: 499 | semver: 7.5.0 500 | dev: true 501 | 502 | /cacheable-lookup@5.0.4: 503 | resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} 504 | engines: {node: '>=10.6.0'} 505 | dev: false 506 | 507 | /cacheable-request@7.0.2: 508 | resolution: {integrity: sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==} 509 | engines: {node: '>=8'} 510 | dependencies: 511 | clone-response: 1.0.3 512 | get-stream: 5.2.0 513 | http-cache-semantics: 4.1.1 514 | keyv: 4.5.2 515 | lowercase-keys: 2.0.0 516 | normalize-url: 6.1.0 517 | responselike: 2.0.1 518 | dev: false 519 | 520 | /call-bind@1.0.2: 521 | resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} 522 | dependencies: 523 | function-bind: 1.1.1 524 | get-intrinsic: 1.2.0 525 | dev: true 526 | 527 | /callsites@3.1.0: 528 | resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} 529 | engines: {node: '>=6'} 530 | dev: true 531 | 532 | /chalk@4.1.2: 533 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 534 | engines: {node: '>=10'} 535 | dependencies: 536 | ansi-styles: 4.3.0 537 | supports-color: 7.2.0 538 | dev: true 539 | 540 | /cliui@7.0.4: 541 | resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} 542 | dependencies: 543 | string-width: 4.2.3 544 | strip-ansi: 6.0.1 545 | wrap-ansi: 7.0.0 546 | dev: true 547 | 548 | /clone-response@1.0.3: 549 | resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} 550 | dependencies: 551 | mimic-response: 1.0.1 552 | dev: false 553 | 554 | /color-convert@2.0.1: 555 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 556 | engines: {node: '>=7.0.0'} 557 | dependencies: 558 | color-name: 1.1.4 559 | dev: true 560 | 561 | /color-name@1.1.4: 562 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 563 | dev: true 564 | 565 | /concat-map@0.0.1: 566 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 567 | dev: true 568 | 569 | /create-require@1.1.1: 570 | resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} 571 | dev: true 572 | 573 | /cross-env@7.0.3: 574 | resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} 575 | engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} 576 | hasBin: true 577 | dependencies: 578 | cross-spawn: 7.0.3 579 | dev: true 580 | 581 | /cross-spawn@7.0.3: 582 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} 583 | engines: {node: '>= 8'} 584 | dependencies: 585 | path-key: 3.1.1 586 | shebang-command: 2.0.0 587 | which: 2.0.2 588 | dev: true 589 | 590 | /debug@3.2.7: 591 | resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} 592 | peerDependencies: 593 | supports-color: '*' 594 | peerDependenciesMeta: 595 | supports-color: 596 | optional: true 597 | dependencies: 598 | ms: 2.1.3 599 | dev: true 600 | 601 | /debug@4.3.4: 602 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} 603 | engines: {node: '>=6.0'} 604 | peerDependencies: 605 | supports-color: '*' 606 | peerDependenciesMeta: 607 | supports-color: 608 | optional: true 609 | dependencies: 610 | ms: 2.1.2 611 | dev: true 612 | 613 | /decompress-response@6.0.0: 614 | resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} 615 | engines: {node: '>=10'} 616 | dependencies: 617 | mimic-response: 3.1.0 618 | dev: false 619 | 620 | /deep-is@0.1.4: 621 | resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} 622 | dev: true 623 | 624 | /defer-to-connect@2.0.1: 625 | resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} 626 | engines: {node: '>=10'} 627 | dev: false 628 | 629 | /define-properties@1.2.0: 630 | resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} 631 | engines: {node: '>= 0.4'} 632 | dependencies: 633 | has-property-descriptors: 1.0.0 634 | object-keys: 1.1.1 635 | dev: true 636 | 637 | /diff@4.0.2: 638 | resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} 639 | engines: {node: '>=0.3.1'} 640 | dev: true 641 | 642 | /dir-glob@3.0.1: 643 | resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} 644 | engines: {node: '>=8'} 645 | dependencies: 646 | path-type: 4.0.0 647 | dev: true 648 | 649 | /doctrine@2.1.0: 650 | resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} 651 | engines: {node: '>=0.10.0'} 652 | dependencies: 653 | esutils: 2.0.3 654 | dev: true 655 | 656 | /doctrine@3.0.0: 657 | resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} 658 | engines: {node: '>=6.0.0'} 659 | dependencies: 660 | esutils: 2.0.3 661 | dev: true 662 | 663 | /emoji-regex@8.0.0: 664 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 665 | dev: true 666 | 667 | /end-of-stream@1.4.4: 668 | resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} 669 | dependencies: 670 | once: 1.4.0 671 | dev: false 672 | 673 | /es-abstract@1.21.2: 674 | resolution: {integrity: sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==} 675 | engines: {node: '>= 0.4'} 676 | dependencies: 677 | array-buffer-byte-length: 1.0.0 678 | available-typed-arrays: 1.0.5 679 | call-bind: 1.0.2 680 | es-set-tostringtag: 2.0.1 681 | es-to-primitive: 1.2.1 682 | function.prototype.name: 1.1.5 683 | get-intrinsic: 1.2.0 684 | get-symbol-description: 1.0.0 685 | globalthis: 1.0.3 686 | gopd: 1.0.1 687 | has: 1.0.3 688 | has-property-descriptors: 1.0.0 689 | has-proto: 1.0.1 690 | has-symbols: 1.0.3 691 | internal-slot: 1.0.5 692 | is-array-buffer: 3.0.2 693 | is-callable: 1.2.7 694 | is-negative-zero: 2.0.2 695 | is-regex: 1.1.4 696 | is-shared-array-buffer: 1.0.2 697 | is-string: 1.0.7 698 | is-typed-array: 1.1.10 699 | is-weakref: 1.0.2 700 | object-inspect: 1.12.3 701 | object-keys: 1.1.1 702 | object.assign: 4.1.4 703 | regexp.prototype.flags: 1.5.0 704 | safe-regex-test: 1.0.0 705 | string.prototype.trim: 1.2.7 706 | string.prototype.trimend: 1.0.6 707 | string.prototype.trimstart: 1.0.6 708 | typed-array-length: 1.0.4 709 | unbox-primitive: 1.0.2 710 | which-typed-array: 1.1.9 711 | dev: true 712 | 713 | /es-set-tostringtag@2.0.1: 714 | resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} 715 | engines: {node: '>= 0.4'} 716 | dependencies: 717 | get-intrinsic: 1.2.0 718 | has: 1.0.3 719 | has-tostringtag: 1.0.0 720 | dev: true 721 | 722 | /es-shim-unscopables@1.0.0: 723 | resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} 724 | dependencies: 725 | has: 1.0.3 726 | dev: true 727 | 728 | /es-to-primitive@1.2.1: 729 | resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} 730 | engines: {node: '>= 0.4'} 731 | dependencies: 732 | is-callable: 1.2.7 733 | is-date-object: 1.0.5 734 | is-symbol: 1.0.4 735 | dev: true 736 | 737 | /escape-string-regexp@4.0.0: 738 | resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} 739 | engines: {node: '>=10'} 740 | dev: true 741 | 742 | /eslint-config-standard@17.0.0(eslint-plugin-import@2.27.5)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.39.0): 743 | resolution: {integrity: sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==} 744 | peerDependencies: 745 | eslint: ^8.0.1 746 | eslint-plugin-import: ^2.25.2 747 | eslint-plugin-n: ^15.0.0 748 | eslint-plugin-promise: ^6.0.0 749 | dependencies: 750 | eslint: 8.39.0 751 | eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.59.0)(eslint@8.39.0) 752 | eslint-plugin-n: 15.7.0(eslint@8.39.0) 753 | eslint-plugin-promise: 6.1.1(eslint@8.39.0) 754 | dev: true 755 | 756 | /eslint-import-resolver-node@0.3.7: 757 | resolution: {integrity: sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==} 758 | dependencies: 759 | debug: 3.2.7 760 | is-core-module: 2.12.0 761 | resolve: 1.22.2 762 | transitivePeerDependencies: 763 | - supports-color 764 | dev: true 765 | 766 | /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.59.0)(eslint-import-resolver-node@0.3.7)(eslint@8.39.0): 767 | resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} 768 | engines: {node: '>=4'} 769 | peerDependencies: 770 | '@typescript-eslint/parser': '*' 771 | eslint: '*' 772 | eslint-import-resolver-node: '*' 773 | eslint-import-resolver-typescript: '*' 774 | eslint-import-resolver-webpack: '*' 775 | peerDependenciesMeta: 776 | '@typescript-eslint/parser': 777 | optional: true 778 | eslint: 779 | optional: true 780 | eslint-import-resolver-node: 781 | optional: true 782 | eslint-import-resolver-typescript: 783 | optional: true 784 | eslint-import-resolver-webpack: 785 | optional: true 786 | dependencies: 787 | '@typescript-eslint/parser': 5.59.0(eslint@8.39.0)(typescript@5.0.4) 788 | debug: 3.2.7 789 | eslint: 8.39.0 790 | eslint-import-resolver-node: 0.3.7 791 | transitivePeerDependencies: 792 | - supports-color 793 | dev: true 794 | 795 | /eslint-plugin-es@4.1.0(eslint@8.39.0): 796 | resolution: {integrity: sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==} 797 | engines: {node: '>=8.10.0'} 798 | peerDependencies: 799 | eslint: '>=4.19.1' 800 | dependencies: 801 | eslint: 8.39.0 802 | eslint-utils: 2.1.0 803 | regexpp: 3.2.0 804 | dev: true 805 | 806 | /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.59.0)(eslint@8.39.0): 807 | resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} 808 | engines: {node: '>=4'} 809 | peerDependencies: 810 | '@typescript-eslint/parser': '*' 811 | eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 812 | peerDependenciesMeta: 813 | '@typescript-eslint/parser': 814 | optional: true 815 | dependencies: 816 | '@typescript-eslint/parser': 5.59.0(eslint@8.39.0)(typescript@5.0.4) 817 | array-includes: 3.1.6 818 | array.prototype.flat: 1.3.1 819 | array.prototype.flatmap: 1.3.1 820 | debug: 3.2.7 821 | doctrine: 2.1.0 822 | eslint: 8.39.0 823 | eslint-import-resolver-node: 0.3.7 824 | eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.59.0)(eslint-import-resolver-node@0.3.7)(eslint@8.39.0) 825 | has: 1.0.3 826 | is-core-module: 2.12.0 827 | is-glob: 4.0.3 828 | minimatch: 3.1.2 829 | object.values: 1.1.6 830 | resolve: 1.22.2 831 | semver: 6.3.0 832 | tsconfig-paths: 3.14.2 833 | transitivePeerDependencies: 834 | - eslint-import-resolver-typescript 835 | - eslint-import-resolver-webpack 836 | - supports-color 837 | dev: true 838 | 839 | /eslint-plugin-n@15.7.0(eslint@8.39.0): 840 | resolution: {integrity: sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==} 841 | engines: {node: '>=12.22.0'} 842 | peerDependencies: 843 | eslint: '>=7.0.0' 844 | dependencies: 845 | builtins: 5.0.1 846 | eslint: 8.39.0 847 | eslint-plugin-es: 4.1.0(eslint@8.39.0) 848 | eslint-utils: 3.0.0(eslint@8.39.0) 849 | ignore: 5.2.4 850 | is-core-module: 2.12.0 851 | minimatch: 3.1.2 852 | resolve: 1.22.2 853 | semver: 7.5.0 854 | dev: true 855 | 856 | /eslint-plugin-promise@6.1.1(eslint@8.39.0): 857 | resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} 858 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 859 | peerDependencies: 860 | eslint: ^7.0.0 || ^8.0.0 861 | dependencies: 862 | eslint: 8.39.0 863 | dev: true 864 | 865 | /eslint-scope@5.1.1: 866 | resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} 867 | engines: {node: '>=8.0.0'} 868 | dependencies: 869 | esrecurse: 4.3.0 870 | estraverse: 4.3.0 871 | dev: true 872 | 873 | /eslint-scope@7.2.0: 874 | resolution: {integrity: sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==} 875 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 876 | dependencies: 877 | esrecurse: 4.3.0 878 | estraverse: 5.3.0 879 | dev: true 880 | 881 | /eslint-utils@2.1.0: 882 | resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} 883 | engines: {node: '>=6'} 884 | dependencies: 885 | eslint-visitor-keys: 1.3.0 886 | dev: true 887 | 888 | /eslint-utils@3.0.0(eslint@8.39.0): 889 | resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} 890 | engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} 891 | peerDependencies: 892 | eslint: '>=5' 893 | dependencies: 894 | eslint: 8.39.0 895 | eslint-visitor-keys: 2.1.0 896 | dev: true 897 | 898 | /eslint-visitor-keys@1.3.0: 899 | resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} 900 | engines: {node: '>=4'} 901 | dev: true 902 | 903 | /eslint-visitor-keys@2.1.0: 904 | resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} 905 | engines: {node: '>=10'} 906 | dev: true 907 | 908 | /eslint-visitor-keys@3.4.0: 909 | resolution: {integrity: sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==} 910 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 911 | dev: true 912 | 913 | /eslint@8.39.0: 914 | resolution: {integrity: sha512-mwiok6cy7KTW7rBpo05k6+p4YVZByLNjAZ/ACB9DRCu4YDRwjXI01tWHp6KAUWelsBetTxKK/2sHB0vdS8Z2Og==} 915 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 916 | hasBin: true 917 | dependencies: 918 | '@eslint-community/eslint-utils': 4.4.0(eslint@8.39.0) 919 | '@eslint-community/regexpp': 4.5.0 920 | '@eslint/eslintrc': 2.0.2 921 | '@eslint/js': 8.39.0 922 | '@humanwhocodes/config-array': 0.11.8 923 | '@humanwhocodes/module-importer': 1.0.1 924 | '@nodelib/fs.walk': 1.2.8 925 | ajv: 6.12.6 926 | chalk: 4.1.2 927 | cross-spawn: 7.0.3 928 | debug: 4.3.4 929 | doctrine: 3.0.0 930 | escape-string-regexp: 4.0.0 931 | eslint-scope: 7.2.0 932 | eslint-visitor-keys: 3.4.0 933 | espree: 9.5.1 934 | esquery: 1.5.0 935 | esutils: 2.0.3 936 | fast-deep-equal: 3.1.3 937 | file-entry-cache: 6.0.1 938 | find-up: 5.0.0 939 | glob-parent: 6.0.2 940 | globals: 13.20.0 941 | grapheme-splitter: 1.0.4 942 | ignore: 5.2.4 943 | import-fresh: 3.3.0 944 | imurmurhash: 0.1.4 945 | is-glob: 4.0.3 946 | is-path-inside: 3.0.3 947 | js-sdsl: 4.4.0 948 | js-yaml: 4.1.0 949 | json-stable-stringify-without-jsonify: 1.0.1 950 | levn: 0.4.1 951 | lodash.merge: 4.6.2 952 | minimatch: 3.1.2 953 | natural-compare: 1.4.0 954 | optionator: 0.9.1 955 | strip-ansi: 6.0.1 956 | strip-json-comments: 3.1.1 957 | text-table: 0.2.0 958 | transitivePeerDependencies: 959 | - supports-color 960 | dev: true 961 | 962 | /espree@9.5.1: 963 | resolution: {integrity: sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==} 964 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 965 | dependencies: 966 | acorn: 8.8.2 967 | acorn-jsx: 5.3.2(acorn@8.8.2) 968 | eslint-visitor-keys: 3.4.0 969 | dev: true 970 | 971 | /esquery@1.5.0: 972 | resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} 973 | engines: {node: '>=0.10'} 974 | dependencies: 975 | estraverse: 5.3.0 976 | dev: true 977 | 978 | /esrecurse@4.3.0: 979 | resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} 980 | engines: {node: '>=4.0'} 981 | dependencies: 982 | estraverse: 5.3.0 983 | dev: true 984 | 985 | /estraverse@4.3.0: 986 | resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} 987 | engines: {node: '>=4.0'} 988 | dev: true 989 | 990 | /estraverse@5.3.0: 991 | resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} 992 | engines: {node: '>=4.0'} 993 | dev: true 994 | 995 | /esutils@2.0.3: 996 | resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} 997 | engines: {node: '>=0.10.0'} 998 | dev: true 999 | 1000 | /fast-deep-equal@3.1.3: 1001 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 1002 | dev: true 1003 | 1004 | /fast-glob@3.2.12: 1005 | resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} 1006 | engines: {node: '>=8.6.0'} 1007 | dependencies: 1008 | '@nodelib/fs.stat': 2.0.5 1009 | '@nodelib/fs.walk': 1.2.8 1010 | glob-parent: 5.1.2 1011 | merge2: 1.4.1 1012 | micromatch: 4.0.5 1013 | dev: true 1014 | 1015 | /fast-json-stable-stringify@2.1.0: 1016 | resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} 1017 | dev: true 1018 | 1019 | /fast-levenshtein@2.0.6: 1020 | resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} 1021 | dev: true 1022 | 1023 | /fastq@1.15.0: 1024 | resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} 1025 | dependencies: 1026 | reusify: 1.0.4 1027 | dev: true 1028 | 1029 | /file-entry-cache@6.0.1: 1030 | resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} 1031 | engines: {node: ^10.12.0 || >=12.0.0} 1032 | dependencies: 1033 | flat-cache: 3.0.4 1034 | dev: true 1035 | 1036 | /fill-range@7.0.1: 1037 | resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} 1038 | engines: {node: '>=8'} 1039 | dependencies: 1040 | to-regex-range: 5.0.1 1041 | dev: true 1042 | 1043 | /find-up@5.0.0: 1044 | resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} 1045 | engines: {node: '>=10'} 1046 | dependencies: 1047 | locate-path: 6.0.0 1048 | path-exists: 4.0.0 1049 | dev: true 1050 | 1051 | /flat-cache@3.0.4: 1052 | resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} 1053 | engines: {node: ^10.12.0 || >=12.0.0} 1054 | dependencies: 1055 | flatted: 3.2.7 1056 | rimraf: 3.0.2 1057 | dev: true 1058 | 1059 | /flatted@3.2.7: 1060 | resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} 1061 | dev: true 1062 | 1063 | /for-each@0.3.3: 1064 | resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} 1065 | dependencies: 1066 | is-callable: 1.2.7 1067 | dev: true 1068 | 1069 | /foreground-child@3.1.1: 1070 | resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} 1071 | engines: {node: '>=14'} 1072 | dependencies: 1073 | cross-spawn: 7.0.3 1074 | signal-exit: 4.0.1 1075 | dev: true 1076 | 1077 | /fs.realpath@1.0.0: 1078 | resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} 1079 | dev: true 1080 | 1081 | /function-bind@1.1.1: 1082 | resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} 1083 | dev: true 1084 | 1085 | /function.prototype.name@1.1.5: 1086 | resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} 1087 | engines: {node: '>= 0.4'} 1088 | dependencies: 1089 | call-bind: 1.0.2 1090 | define-properties: 1.2.0 1091 | es-abstract: 1.21.2 1092 | functions-have-names: 1.2.3 1093 | dev: true 1094 | 1095 | /functions-have-names@1.2.3: 1096 | resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} 1097 | dev: true 1098 | 1099 | /get-intrinsic@1.2.0: 1100 | resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==} 1101 | dependencies: 1102 | function-bind: 1.1.1 1103 | has: 1.0.3 1104 | has-symbols: 1.0.3 1105 | dev: true 1106 | 1107 | /get-stream@5.2.0: 1108 | resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} 1109 | engines: {node: '>=8'} 1110 | dependencies: 1111 | pump: 3.0.0 1112 | dev: false 1113 | 1114 | /get-symbol-description@1.0.0: 1115 | resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} 1116 | engines: {node: '>= 0.4'} 1117 | dependencies: 1118 | call-bind: 1.0.2 1119 | get-intrinsic: 1.2.0 1120 | dev: true 1121 | 1122 | /glob-parent@5.1.2: 1123 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 1124 | engines: {node: '>= 6'} 1125 | dependencies: 1126 | is-glob: 4.0.3 1127 | dev: true 1128 | 1129 | /glob-parent@6.0.2: 1130 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} 1131 | engines: {node: '>=10.13.0'} 1132 | dependencies: 1133 | is-glob: 4.0.3 1134 | dev: true 1135 | 1136 | /glob@10.2.2: 1137 | resolution: {integrity: sha512-Xsa0BcxIC6th9UwNjZkhrMtNo/MnyRL8jGCP+uEwhA5oFOCY1f2s1/oNKY47xQ0Bg5nkjsfAEIej1VeH62bDDQ==} 1138 | engines: {node: '>=16 || 14 >=14.17'} 1139 | hasBin: true 1140 | dependencies: 1141 | foreground-child: 3.1.1 1142 | jackspeak: 2.1.0 1143 | minimatch: 9.0.0 1144 | minipass: 5.0.0 1145 | path-scurry: 1.7.0 1146 | dev: true 1147 | 1148 | /glob@7.2.3: 1149 | resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} 1150 | dependencies: 1151 | fs.realpath: 1.0.0 1152 | inflight: 1.0.6 1153 | inherits: 2.0.4 1154 | minimatch: 3.1.2 1155 | once: 1.4.0 1156 | path-is-absolute: 1.0.1 1157 | dev: true 1158 | 1159 | /globals@13.20.0: 1160 | resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} 1161 | engines: {node: '>=8'} 1162 | dependencies: 1163 | type-fest: 0.20.2 1164 | dev: true 1165 | 1166 | /globalthis@1.0.3: 1167 | resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} 1168 | engines: {node: '>= 0.4'} 1169 | dependencies: 1170 | define-properties: 1.2.0 1171 | dev: true 1172 | 1173 | /globby@11.1.0: 1174 | resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} 1175 | engines: {node: '>=10'} 1176 | dependencies: 1177 | array-union: 2.1.0 1178 | dir-glob: 3.0.1 1179 | fast-glob: 3.2.12 1180 | ignore: 5.2.4 1181 | merge2: 1.4.1 1182 | slash: 3.0.0 1183 | dev: true 1184 | 1185 | /gopd@1.0.1: 1186 | resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} 1187 | dependencies: 1188 | get-intrinsic: 1.2.0 1189 | dev: true 1190 | 1191 | /got@11.8.6: 1192 | resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} 1193 | engines: {node: '>=10.19.0'} 1194 | dependencies: 1195 | '@sindresorhus/is': 4.6.0 1196 | '@szmarczak/http-timer': 4.0.6 1197 | '@types/cacheable-request': 6.0.3 1198 | '@types/responselike': 1.0.0 1199 | cacheable-lookup: 5.0.4 1200 | cacheable-request: 7.0.2 1201 | decompress-response: 6.0.0 1202 | http2-wrapper: 1.0.3 1203 | lowercase-keys: 2.0.0 1204 | p-cancelable: 2.1.1 1205 | responselike: 2.0.1 1206 | dev: false 1207 | 1208 | /grapheme-splitter@1.0.4: 1209 | resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} 1210 | dev: true 1211 | 1212 | /has-bigints@1.0.2: 1213 | resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} 1214 | dev: true 1215 | 1216 | /has-flag@4.0.0: 1217 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 1218 | engines: {node: '>=8'} 1219 | dev: true 1220 | 1221 | /has-property-descriptors@1.0.0: 1222 | resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} 1223 | dependencies: 1224 | get-intrinsic: 1.2.0 1225 | dev: true 1226 | 1227 | /has-proto@1.0.1: 1228 | resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} 1229 | engines: {node: '>= 0.4'} 1230 | dev: true 1231 | 1232 | /has-symbols@1.0.3: 1233 | resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} 1234 | engines: {node: '>= 0.4'} 1235 | dev: true 1236 | 1237 | /has-tostringtag@1.0.0: 1238 | resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} 1239 | engines: {node: '>= 0.4'} 1240 | dependencies: 1241 | has-symbols: 1.0.3 1242 | dev: true 1243 | 1244 | /has@1.0.3: 1245 | resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} 1246 | engines: {node: '>= 0.4.0'} 1247 | dependencies: 1248 | function-bind: 1.1.1 1249 | dev: true 1250 | 1251 | /http-cache-semantics@4.1.1: 1252 | resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} 1253 | dev: false 1254 | 1255 | /http2-wrapper@1.0.3: 1256 | resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} 1257 | engines: {node: '>=10.19.0'} 1258 | dependencies: 1259 | quick-lru: 5.1.1 1260 | resolve-alpn: 1.2.1 1261 | dev: false 1262 | 1263 | /ignore@5.2.4: 1264 | resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} 1265 | engines: {node: '>= 4'} 1266 | dev: true 1267 | 1268 | /import-fresh@3.3.0: 1269 | resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} 1270 | engines: {node: '>=6'} 1271 | dependencies: 1272 | parent-module: 1.0.1 1273 | resolve-from: 4.0.0 1274 | dev: true 1275 | 1276 | /imurmurhash@0.1.4: 1277 | resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} 1278 | engines: {node: '>=0.8.19'} 1279 | dev: true 1280 | 1281 | /inflight@1.0.6: 1282 | resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} 1283 | dependencies: 1284 | once: 1.4.0 1285 | wrappy: 1.0.2 1286 | dev: true 1287 | 1288 | /inherits@2.0.4: 1289 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 1290 | dev: true 1291 | 1292 | /internal-slot@1.0.5: 1293 | resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} 1294 | engines: {node: '>= 0.4'} 1295 | dependencies: 1296 | get-intrinsic: 1.2.0 1297 | has: 1.0.3 1298 | side-channel: 1.0.4 1299 | dev: true 1300 | 1301 | /is-array-buffer@3.0.2: 1302 | resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} 1303 | dependencies: 1304 | call-bind: 1.0.2 1305 | get-intrinsic: 1.2.0 1306 | is-typed-array: 1.1.10 1307 | dev: true 1308 | 1309 | /is-bigint@1.0.4: 1310 | resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} 1311 | dependencies: 1312 | has-bigints: 1.0.2 1313 | dev: true 1314 | 1315 | /is-boolean-object@1.1.2: 1316 | resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} 1317 | engines: {node: '>= 0.4'} 1318 | dependencies: 1319 | call-bind: 1.0.2 1320 | has-tostringtag: 1.0.0 1321 | dev: true 1322 | 1323 | /is-callable@1.2.7: 1324 | resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} 1325 | engines: {node: '>= 0.4'} 1326 | dev: true 1327 | 1328 | /is-core-module@2.12.0: 1329 | resolution: {integrity: sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==} 1330 | dependencies: 1331 | has: 1.0.3 1332 | dev: true 1333 | 1334 | /is-date-object@1.0.5: 1335 | resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} 1336 | engines: {node: '>= 0.4'} 1337 | dependencies: 1338 | has-tostringtag: 1.0.0 1339 | dev: true 1340 | 1341 | /is-extglob@2.1.1: 1342 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 1343 | engines: {node: '>=0.10.0'} 1344 | dev: true 1345 | 1346 | /is-fullwidth-code-point@3.0.0: 1347 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 1348 | engines: {node: '>=8'} 1349 | dev: true 1350 | 1351 | /is-glob@4.0.3: 1352 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 1353 | engines: {node: '>=0.10.0'} 1354 | dependencies: 1355 | is-extglob: 2.1.1 1356 | dev: true 1357 | 1358 | /is-negative-zero@2.0.2: 1359 | resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} 1360 | engines: {node: '>= 0.4'} 1361 | dev: true 1362 | 1363 | /is-number-object@1.0.7: 1364 | resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} 1365 | engines: {node: '>= 0.4'} 1366 | dependencies: 1367 | has-tostringtag: 1.0.0 1368 | dev: true 1369 | 1370 | /is-number@7.0.0: 1371 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 1372 | engines: {node: '>=0.12.0'} 1373 | dev: true 1374 | 1375 | /is-path-inside@3.0.3: 1376 | resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} 1377 | engines: {node: '>=8'} 1378 | dev: true 1379 | 1380 | /is-regex@1.1.4: 1381 | resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} 1382 | engines: {node: '>= 0.4'} 1383 | dependencies: 1384 | call-bind: 1.0.2 1385 | has-tostringtag: 1.0.0 1386 | dev: true 1387 | 1388 | /is-shared-array-buffer@1.0.2: 1389 | resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} 1390 | dependencies: 1391 | call-bind: 1.0.2 1392 | dev: true 1393 | 1394 | /is-string@1.0.7: 1395 | resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} 1396 | engines: {node: '>= 0.4'} 1397 | dependencies: 1398 | has-tostringtag: 1.0.0 1399 | dev: true 1400 | 1401 | /is-symbol@1.0.4: 1402 | resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} 1403 | engines: {node: '>= 0.4'} 1404 | dependencies: 1405 | has-symbols: 1.0.3 1406 | dev: true 1407 | 1408 | /is-typed-array@1.1.10: 1409 | resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==} 1410 | engines: {node: '>= 0.4'} 1411 | dependencies: 1412 | available-typed-arrays: 1.0.5 1413 | call-bind: 1.0.2 1414 | for-each: 0.3.3 1415 | gopd: 1.0.1 1416 | has-tostringtag: 1.0.0 1417 | dev: true 1418 | 1419 | /is-weakref@1.0.2: 1420 | resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} 1421 | dependencies: 1422 | call-bind: 1.0.2 1423 | dev: true 1424 | 1425 | /isexe@2.0.0: 1426 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 1427 | dev: true 1428 | 1429 | /jackspeak@2.1.0: 1430 | resolution: {integrity: sha512-DiEwVPqsieUzZBNxQ2cxznmFzfg/AMgJUjYw5xl6rSmCxAQXECcbSdwcLM6Ds6T09+SBfSNCGPhYUoQ96P4h7A==} 1431 | engines: {node: '>=14'} 1432 | dependencies: 1433 | cliui: 7.0.4 1434 | optionalDependencies: 1435 | '@pkgjs/parseargs': 0.11.0 1436 | dev: true 1437 | 1438 | /js-sdsl@4.4.0: 1439 | resolution: {integrity: sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==} 1440 | dev: true 1441 | 1442 | /js-yaml@4.1.0: 1443 | resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} 1444 | hasBin: true 1445 | dependencies: 1446 | argparse: 2.0.1 1447 | dev: true 1448 | 1449 | /json-buffer@3.0.1: 1450 | resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} 1451 | dev: false 1452 | 1453 | /json-schema-traverse@0.4.1: 1454 | resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} 1455 | dev: true 1456 | 1457 | /json-stable-stringify-without-jsonify@1.0.1: 1458 | resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} 1459 | dev: true 1460 | 1461 | /json5@1.0.2: 1462 | resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} 1463 | hasBin: true 1464 | dependencies: 1465 | minimist: 1.2.8 1466 | dev: true 1467 | 1468 | /keyv@4.5.2: 1469 | resolution: {integrity: sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==} 1470 | dependencies: 1471 | json-buffer: 3.0.1 1472 | dev: false 1473 | 1474 | /levn@0.4.1: 1475 | resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} 1476 | engines: {node: '>= 0.8.0'} 1477 | dependencies: 1478 | prelude-ls: 1.2.1 1479 | type-check: 0.4.0 1480 | dev: true 1481 | 1482 | /locate-path@6.0.0: 1483 | resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} 1484 | engines: {node: '>=10'} 1485 | dependencies: 1486 | p-locate: 5.0.0 1487 | dev: true 1488 | 1489 | /lodash.merge@4.6.2: 1490 | resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} 1491 | dev: true 1492 | 1493 | /lowercase-keys@2.0.0: 1494 | resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} 1495 | engines: {node: '>=8'} 1496 | dev: false 1497 | 1498 | /lru-cache@6.0.0: 1499 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} 1500 | engines: {node: '>=10'} 1501 | dependencies: 1502 | yallist: 4.0.0 1503 | dev: true 1504 | 1505 | /lru-cache@9.1.1: 1506 | resolution: {integrity: sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==} 1507 | engines: {node: 14 || >=16.14} 1508 | dev: true 1509 | 1510 | /make-error@1.3.6: 1511 | resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} 1512 | dev: true 1513 | 1514 | /merge2@1.4.1: 1515 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 1516 | engines: {node: '>= 8'} 1517 | dev: true 1518 | 1519 | /micromatch@4.0.5: 1520 | resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} 1521 | engines: {node: '>=8.6'} 1522 | dependencies: 1523 | braces: 3.0.2 1524 | picomatch: 2.3.1 1525 | dev: true 1526 | 1527 | /mimic-response@1.0.1: 1528 | resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} 1529 | engines: {node: '>=4'} 1530 | dev: false 1531 | 1532 | /mimic-response@3.1.0: 1533 | resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} 1534 | engines: {node: '>=10'} 1535 | dev: false 1536 | 1537 | /minimatch@3.1.2: 1538 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 1539 | dependencies: 1540 | brace-expansion: 1.1.11 1541 | dev: true 1542 | 1543 | /minimatch@9.0.0: 1544 | resolution: {integrity: sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==} 1545 | engines: {node: '>=16 || 14 >=14.17'} 1546 | dependencies: 1547 | brace-expansion: 2.0.1 1548 | dev: true 1549 | 1550 | /minimist@1.2.8: 1551 | resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} 1552 | dev: true 1553 | 1554 | /minipass@5.0.0: 1555 | resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} 1556 | engines: {node: '>=8'} 1557 | dev: true 1558 | 1559 | /ms@2.1.2: 1560 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 1561 | dev: true 1562 | 1563 | /ms@2.1.3: 1564 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 1565 | dev: true 1566 | 1567 | /natural-compare-lite@1.4.0: 1568 | resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} 1569 | dev: true 1570 | 1571 | /natural-compare@1.4.0: 1572 | resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} 1573 | dev: true 1574 | 1575 | /normalize-url@6.1.0: 1576 | resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} 1577 | engines: {node: '>=10'} 1578 | dev: false 1579 | 1580 | /object-inspect@1.12.3: 1581 | resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} 1582 | dev: true 1583 | 1584 | /object-keys@1.1.1: 1585 | resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} 1586 | engines: {node: '>= 0.4'} 1587 | dev: true 1588 | 1589 | /object.assign@4.1.4: 1590 | resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} 1591 | engines: {node: '>= 0.4'} 1592 | dependencies: 1593 | call-bind: 1.0.2 1594 | define-properties: 1.2.0 1595 | has-symbols: 1.0.3 1596 | object-keys: 1.1.1 1597 | dev: true 1598 | 1599 | /object.values@1.1.6: 1600 | resolution: {integrity: sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==} 1601 | engines: {node: '>= 0.4'} 1602 | dependencies: 1603 | call-bind: 1.0.2 1604 | define-properties: 1.2.0 1605 | es-abstract: 1.21.2 1606 | dev: true 1607 | 1608 | /once@1.4.0: 1609 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 1610 | dependencies: 1611 | wrappy: 1.0.2 1612 | 1613 | /optionator@0.9.1: 1614 | resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} 1615 | engines: {node: '>= 0.8.0'} 1616 | dependencies: 1617 | deep-is: 0.1.4 1618 | fast-levenshtein: 2.0.6 1619 | levn: 0.4.1 1620 | prelude-ls: 1.2.1 1621 | type-check: 0.4.0 1622 | word-wrap: 1.2.3 1623 | dev: true 1624 | 1625 | /p-cancelable@2.1.1: 1626 | resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} 1627 | engines: {node: '>=8'} 1628 | dev: false 1629 | 1630 | /p-limit@3.1.0: 1631 | resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} 1632 | engines: {node: '>=10'} 1633 | dependencies: 1634 | yocto-queue: 0.1.0 1635 | dev: true 1636 | 1637 | /p-locate@5.0.0: 1638 | resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} 1639 | engines: {node: '>=10'} 1640 | dependencies: 1641 | p-limit: 3.1.0 1642 | dev: true 1643 | 1644 | /parent-module@1.0.1: 1645 | resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} 1646 | engines: {node: '>=6'} 1647 | dependencies: 1648 | callsites: 3.1.0 1649 | dev: true 1650 | 1651 | /path-exists@4.0.0: 1652 | resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 1653 | engines: {node: '>=8'} 1654 | dev: true 1655 | 1656 | /path-is-absolute@1.0.1: 1657 | resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} 1658 | engines: {node: '>=0.10.0'} 1659 | dev: true 1660 | 1661 | /path-key@3.1.1: 1662 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1663 | engines: {node: '>=8'} 1664 | dev: true 1665 | 1666 | /path-parse@1.0.7: 1667 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 1668 | dev: true 1669 | 1670 | /path-scurry@1.7.0: 1671 | resolution: {integrity: sha512-UkZUeDjczjYRE495+9thsgcVgsaCPkaw80slmfVFgllxY+IO8ubTsOpFVjDPROBqJdHfVPUFRHPBV/WciOVfWg==} 1672 | engines: {node: '>=16 || 14 >=14.17'} 1673 | dependencies: 1674 | lru-cache: 9.1.1 1675 | minipass: 5.0.0 1676 | dev: true 1677 | 1678 | /path-type@4.0.0: 1679 | resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} 1680 | engines: {node: '>=8'} 1681 | dev: true 1682 | 1683 | /picomatch@2.3.1: 1684 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1685 | engines: {node: '>=8.6'} 1686 | dev: true 1687 | 1688 | /prelude-ls@1.2.1: 1689 | resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} 1690 | engines: {node: '>= 0.8.0'} 1691 | dev: true 1692 | 1693 | /pump@3.0.0: 1694 | resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} 1695 | dependencies: 1696 | end-of-stream: 1.4.4 1697 | once: 1.4.0 1698 | dev: false 1699 | 1700 | /punycode@2.3.0: 1701 | resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} 1702 | engines: {node: '>=6'} 1703 | dev: true 1704 | 1705 | /queue-microtask@1.2.3: 1706 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1707 | dev: true 1708 | 1709 | /quick-lru@5.1.1: 1710 | resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} 1711 | engines: {node: '>=10'} 1712 | dev: false 1713 | 1714 | /regexp.prototype.flags@1.5.0: 1715 | resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==} 1716 | engines: {node: '>= 0.4'} 1717 | dependencies: 1718 | call-bind: 1.0.2 1719 | define-properties: 1.2.0 1720 | functions-have-names: 1.2.3 1721 | dev: true 1722 | 1723 | /regexpp@3.2.0: 1724 | resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} 1725 | engines: {node: '>=8'} 1726 | dev: true 1727 | 1728 | /resolve-alpn@1.2.1: 1729 | resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} 1730 | dev: false 1731 | 1732 | /resolve-from@4.0.0: 1733 | resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} 1734 | engines: {node: '>=4'} 1735 | dev: true 1736 | 1737 | /resolve@1.22.2: 1738 | resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} 1739 | hasBin: true 1740 | dependencies: 1741 | is-core-module: 2.12.0 1742 | path-parse: 1.0.7 1743 | supports-preserve-symlinks-flag: 1.0.0 1744 | dev: true 1745 | 1746 | /responselike@2.0.1: 1747 | resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} 1748 | dependencies: 1749 | lowercase-keys: 2.0.0 1750 | dev: false 1751 | 1752 | /reusify@1.0.4: 1753 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 1754 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 1755 | dev: true 1756 | 1757 | /rimraf@3.0.2: 1758 | resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} 1759 | hasBin: true 1760 | dependencies: 1761 | glob: 7.2.3 1762 | dev: true 1763 | 1764 | /rimraf@5.0.0: 1765 | resolution: {integrity: sha512-Jf9llaP+RvaEVS5nPShYFhtXIrb3LRKP281ib3So0KkeZKo2wIKyq0Re7TOSwanasA423PSr6CCIL4bP6T040g==} 1766 | engines: {node: '>=14'} 1767 | hasBin: true 1768 | dependencies: 1769 | glob: 10.2.2 1770 | dev: true 1771 | 1772 | /run-parallel@1.2.0: 1773 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1774 | dependencies: 1775 | queue-microtask: 1.2.3 1776 | dev: true 1777 | 1778 | /safe-regex-test@1.0.0: 1779 | resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} 1780 | dependencies: 1781 | call-bind: 1.0.2 1782 | get-intrinsic: 1.2.0 1783 | is-regex: 1.1.4 1784 | dev: true 1785 | 1786 | /semver@6.3.0: 1787 | resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} 1788 | hasBin: true 1789 | dev: true 1790 | 1791 | /semver@7.5.0: 1792 | resolution: {integrity: sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==} 1793 | engines: {node: '>=10'} 1794 | hasBin: true 1795 | dependencies: 1796 | lru-cache: 6.0.0 1797 | dev: true 1798 | 1799 | /shebang-command@2.0.0: 1800 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1801 | engines: {node: '>=8'} 1802 | dependencies: 1803 | shebang-regex: 3.0.0 1804 | dev: true 1805 | 1806 | /shebang-regex@3.0.0: 1807 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1808 | engines: {node: '>=8'} 1809 | dev: true 1810 | 1811 | /side-channel@1.0.4: 1812 | resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} 1813 | dependencies: 1814 | call-bind: 1.0.2 1815 | get-intrinsic: 1.2.0 1816 | object-inspect: 1.12.3 1817 | dev: true 1818 | 1819 | /signal-exit@4.0.1: 1820 | resolution: {integrity: sha512-uUWsN4aOxJAS8KOuf3QMyFtgm1pkb6I+KRZbRF/ghdf5T7sM+B1lLLzPDxswUjkmHyxQAVzEgG35E3NzDM9GVw==} 1821 | engines: {node: '>=14'} 1822 | dev: true 1823 | 1824 | /slash@3.0.0: 1825 | resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} 1826 | engines: {node: '>=8'} 1827 | dev: true 1828 | 1829 | /string-width@4.2.3: 1830 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 1831 | engines: {node: '>=8'} 1832 | dependencies: 1833 | emoji-regex: 8.0.0 1834 | is-fullwidth-code-point: 3.0.0 1835 | strip-ansi: 6.0.1 1836 | dev: true 1837 | 1838 | /string.prototype.trim@1.2.7: 1839 | resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} 1840 | engines: {node: '>= 0.4'} 1841 | dependencies: 1842 | call-bind: 1.0.2 1843 | define-properties: 1.2.0 1844 | es-abstract: 1.21.2 1845 | dev: true 1846 | 1847 | /string.prototype.trimend@1.0.6: 1848 | resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} 1849 | dependencies: 1850 | call-bind: 1.0.2 1851 | define-properties: 1.2.0 1852 | es-abstract: 1.21.2 1853 | dev: true 1854 | 1855 | /string.prototype.trimstart@1.0.6: 1856 | resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} 1857 | dependencies: 1858 | call-bind: 1.0.2 1859 | define-properties: 1.2.0 1860 | es-abstract: 1.21.2 1861 | dev: true 1862 | 1863 | /strip-ansi@6.0.1: 1864 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 1865 | engines: {node: '>=8'} 1866 | dependencies: 1867 | ansi-regex: 5.0.1 1868 | dev: true 1869 | 1870 | /strip-bom@3.0.0: 1871 | resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} 1872 | engines: {node: '>=4'} 1873 | dev: true 1874 | 1875 | /strip-json-comments@3.1.1: 1876 | resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} 1877 | engines: {node: '>=8'} 1878 | dev: true 1879 | 1880 | /supports-color@7.2.0: 1881 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 1882 | engines: {node: '>=8'} 1883 | dependencies: 1884 | has-flag: 4.0.0 1885 | dev: true 1886 | 1887 | /supports-preserve-symlinks-flag@1.0.0: 1888 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 1889 | engines: {node: '>= 0.4'} 1890 | dev: true 1891 | 1892 | /text-table@0.2.0: 1893 | resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} 1894 | dev: true 1895 | 1896 | /to-regex-range@5.0.1: 1897 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1898 | engines: {node: '>=8.0'} 1899 | dependencies: 1900 | is-number: 7.0.0 1901 | dev: true 1902 | 1903 | /ts-node@10.9.1(@types/node@18.16.0)(typescript@5.0.4): 1904 | resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} 1905 | hasBin: true 1906 | peerDependencies: 1907 | '@swc/core': '>=1.2.50' 1908 | '@swc/wasm': '>=1.2.50' 1909 | '@types/node': '*' 1910 | typescript: '>=2.7' 1911 | peerDependenciesMeta: 1912 | '@swc/core': 1913 | optional: true 1914 | '@swc/wasm': 1915 | optional: true 1916 | dependencies: 1917 | '@cspotcode/source-map-support': 0.8.1 1918 | '@tsconfig/node10': 1.0.9 1919 | '@tsconfig/node12': 1.0.11 1920 | '@tsconfig/node14': 1.0.3 1921 | '@tsconfig/node16': 1.0.3 1922 | '@types/node': 18.16.0 1923 | acorn: 8.8.2 1924 | acorn-walk: 8.2.0 1925 | arg: 4.1.3 1926 | create-require: 1.1.1 1927 | diff: 4.0.2 1928 | make-error: 1.3.6 1929 | typescript: 5.0.4 1930 | v8-compile-cache-lib: 3.0.1 1931 | yn: 3.1.1 1932 | dev: true 1933 | 1934 | /tsconfig-paths@3.14.2: 1935 | resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} 1936 | dependencies: 1937 | '@types/json5': 0.0.29 1938 | json5: 1.0.2 1939 | minimist: 1.2.8 1940 | strip-bom: 3.0.0 1941 | dev: true 1942 | 1943 | /tslib@1.14.1: 1944 | resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} 1945 | dev: true 1946 | 1947 | /tsutils@3.21.0(typescript@5.0.4): 1948 | resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} 1949 | engines: {node: '>= 6'} 1950 | peerDependencies: 1951 | typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' 1952 | dependencies: 1953 | tslib: 1.14.1 1954 | typescript: 5.0.4 1955 | dev: true 1956 | 1957 | /tunnel@0.0.6: 1958 | resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} 1959 | engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} 1960 | dev: true 1961 | 1962 | /type-check@0.4.0: 1963 | resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 1964 | engines: {node: '>= 0.8.0'} 1965 | dependencies: 1966 | prelude-ls: 1.2.1 1967 | dev: true 1968 | 1969 | /type-fest@0.20.2: 1970 | resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} 1971 | engines: {node: '>=10'} 1972 | dev: true 1973 | 1974 | /typed-array-length@1.0.4: 1975 | resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} 1976 | dependencies: 1977 | call-bind: 1.0.2 1978 | for-each: 0.3.3 1979 | is-typed-array: 1.1.10 1980 | dev: true 1981 | 1982 | /typescript@5.0.4: 1983 | resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} 1984 | engines: {node: '>=12.20'} 1985 | hasBin: true 1986 | dev: true 1987 | 1988 | /unbox-primitive@1.0.2: 1989 | resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} 1990 | dependencies: 1991 | call-bind: 1.0.2 1992 | has-bigints: 1.0.2 1993 | has-symbols: 1.0.3 1994 | which-boxed-primitive: 1.0.2 1995 | dev: true 1996 | 1997 | /uri-js@4.4.1: 1998 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 1999 | dependencies: 2000 | punycode: 2.3.0 2001 | dev: true 2002 | 2003 | /uuid@9.0.0: 2004 | resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} 2005 | hasBin: true 2006 | dev: false 2007 | 2008 | /v8-compile-cache-lib@3.0.1: 2009 | resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} 2010 | dev: true 2011 | 2012 | /which-boxed-primitive@1.0.2: 2013 | resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} 2014 | dependencies: 2015 | is-bigint: 1.0.4 2016 | is-boolean-object: 1.1.2 2017 | is-number-object: 1.0.7 2018 | is-string: 1.0.7 2019 | is-symbol: 1.0.4 2020 | dev: true 2021 | 2022 | /which-typed-array@1.1.9: 2023 | resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==} 2024 | engines: {node: '>= 0.4'} 2025 | dependencies: 2026 | available-typed-arrays: 1.0.5 2027 | call-bind: 1.0.2 2028 | for-each: 0.3.3 2029 | gopd: 1.0.1 2030 | has-tostringtag: 1.0.0 2031 | is-typed-array: 1.1.10 2032 | dev: true 2033 | 2034 | /which@2.0.2: 2035 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 2036 | engines: {node: '>= 8'} 2037 | hasBin: true 2038 | dependencies: 2039 | isexe: 2.0.0 2040 | dev: true 2041 | 2042 | /word-wrap@1.2.3: 2043 | resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} 2044 | engines: {node: '>=0.10.0'} 2045 | dev: true 2046 | 2047 | /wrap-ansi@7.0.0: 2048 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} 2049 | engines: {node: '>=10'} 2050 | dependencies: 2051 | ansi-styles: 4.3.0 2052 | string-width: 4.2.3 2053 | strip-ansi: 6.0.1 2054 | dev: true 2055 | 2056 | /wrappy@1.0.2: 2057 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 2058 | 2059 | /yallist@4.0.0: 2060 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} 2061 | dev: true 2062 | 2063 | /yn@3.1.1: 2064 | resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} 2065 | engines: {node: '>=6'} 2066 | dev: true 2067 | 2068 | /yocto-queue@0.1.0: 2069 | resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} 2070 | engines: {node: '>=10'} 2071 | dev: true 2072 | -------------------------------------------------------------------------------- /src/api.ts: -------------------------------------------------------------------------------- 1 | import got, { Got, Options, ExtendOptions, Response } from 'got' 2 | import { 3 | BaseResponse, 4 | RegisterPayload, 5 | SignInPayload, 6 | SignInResponse, 7 | AuthorizationPayload, 8 | PunchInResponse, 9 | UserProfileResponse, 10 | ComicSort, 11 | UserFavouritePayload, 12 | UserFavouriteResponse, 13 | CategoriesResponse, 14 | ComicsPayload, 15 | ComicsResponse, 16 | ComicIdPayload, 17 | ComicDetailPayload, 18 | ComicDetailResponse, 19 | ComicEpisodesPayload, 20 | ComicEpisodesResponse, 21 | ComicEpisodePagesPayload, 22 | ComicEpisodePagesResponse, 23 | ComicCommentsPayload, 24 | ComicCommentsResponse, 25 | SearchComicsPayload, 26 | SearchComicsResponse, 27 | SwitchComicLikeResponse, 28 | SwitchComicFavouriteResponse, 29 | UserProfileSloganPayload, 30 | ImageMediaPayload 31 | } from './type' 32 | import { v4 as uuidv4 } from 'uuid' 33 | import { createHmac } from 'crypto' 34 | import assert from 'assert' 35 | 36 | export interface PicaComicOptions { 37 | api: string 38 | apiKey: string 39 | signatureKey: string 40 | accept: string 41 | channel: '1' | '2' | '3' 42 | version: string 43 | uuid: string 44 | platform: string 45 | buildVersion: string 46 | userAgent: string 47 | imageQuality: 'original' | 'low' | 'medium' | 'high' 48 | } 49 | 50 | interface FetcherInstanceHolder { 51 | fetch: Got 52 | appOptions?: Partial 53 | } 54 | 55 | type EndpointPayloadTransformer = (payload: T) => Options | undefined 56 | type DeclaredEndpoint = (payload: T) => Promise 57 | type DeclaredEndpointWithFetcher = (fetcher: FetcherInstanceHolder, payload: T) => Promise 58 | 59 | type PickDeclaredEndpointFromInstance = 60 | Instance extends DeclaredEndpointWithFetcher 61 | ? DeclaredEndpoint 62 | : never 63 | 64 | const defaultPicaComicOptions: PicaComicOptions = { 65 | api: 'https://picaapi.picacomic.com/', 66 | apiKey: 'C69BAF41DA5ABD1FFEDC6D2FEA56B', 67 | signatureKey: '~d}$Q7$eIni=V)9\\RK/P.RM4;9[7|@/CA}b~OW!3?EV`:<>M7pddUBL5n|0/*Cn', 68 | accept: 'application/vnd.picacomic.com.v1+json', 69 | channel: '2', 70 | version: '2.2.1.2.3.3', 71 | uuid: 'defaultUuid', 72 | platform: 'android', 73 | buildVersion: '44', 74 | userAgent: 'okhttp/3.8.1', 75 | imageQuality: 'original' 76 | } 77 | 78 | function fixedSearchParams (searchParams?: Options['searchParams']): string { 79 | if (typeof searchParams === 'string') { 80 | return searchParams[0] === '?' ? searchParams : '?' + searchParams 81 | } else if (searchParams instanceof URLSearchParams) { 82 | return `?${searchParams.toString()}` 83 | } else if (typeof searchParams === 'object') { 84 | const params = Object.entries(searchParams).map(([key, value]) => `${key}=${value}`) 85 | return `?${params.join('&')}` 86 | } else { 87 | return '' 88 | } 89 | } 90 | 91 | function getBeforeRequestOptions (transformedOptions: Options, appOptions?: Partial): Options { 92 | assert(transformedOptions.url && typeof transformedOptions.url === 'string', 'endpoint must be a string') 93 | assert(transformedOptions.method, 'method is required') 94 | 95 | const method = transformedOptions.method 96 | const endpoint = transformedOptions.url + fixedSearchParams(transformedOptions.searchParams) 97 | const fixedEndpoint = endpoint[0] === '/' ? endpoint.substring(1) : endpoint 98 | delete transformedOptions.url // must override prefix url and endpoint 99 | 100 | const mergedPicaComicOptions = { ...defaultPicaComicOptions, ...appOptions } 101 | const timestamp = (Date.now() / 1000).toFixed(0) 102 | const nonce = uuidv4().replace(/-/g, '') 103 | const con = (fixedEndpoint + timestamp + nonce + method + mergedPicaComicOptions.apiKey).toLowerCase() 104 | const signature = createHmac('sha256', mergedPicaComicOptions.signatureKey).update(con).digest().toString('hex') 105 | 106 | const headers: Options['headers'] = {} 107 | headers.time = timestamp 108 | headers.nonce = nonce 109 | headers.signature = signature 110 | headers.accept = mergedPicaComicOptions.accept 111 | headers['api-key'] = mergedPicaComicOptions.apiKey 112 | headers['app-channel'] = mergedPicaComicOptions.channel 113 | headers['app-version'] = mergedPicaComicOptions.version 114 | headers['app-uuid'] = mergedPicaComicOptions.uuid 115 | headers['app-platform'] = mergedPicaComicOptions.platform 116 | headers['app-build-version'] = mergedPicaComicOptions.buildVersion 117 | headers['image-quality'] = mergedPicaComicOptions.imageQuality 118 | headers['user-agent'] = mergedPicaComicOptions.userAgent 119 | headers['content-type'] = 'application/json; charset=UTF-8' 120 | 121 | return { 122 | prefixUrl: mergedPicaComicOptions.api, 123 | url: fixedEndpoint, 124 | headers, 125 | throwHttpErrors: false, 126 | responseType: 'json' 127 | } 128 | } 129 | 130 | function declareEndpoint ( 131 | transformer: EndpointPayloadTransformer, 132 | bodyHandler?: (body: BaseResponse) => R 133 | ): DeclaredEndpointWithFetcher { 134 | return async function declaredEndpoint (fetcher, payload) { 135 | const transformedOptions = transformer(payload) || {} 136 | const beforeRequestOptions = getBeforeRequestOptions(transformedOptions, fetcher.appOptions) 137 | const mergedOptions = fetcher.fetch.mergeOptions(transformedOptions, beforeRequestOptions) 138 | const response = await fetcher.fetch(mergedOptions) as Response 139 | const body = await response.body as R | PicaComicError 140 | if ('error' in body && typeof body.error === 'string') { 141 | throw new PicaComicError(body.code, body.error, body.message, body.detail) 142 | } else { 143 | return typeof bodyHandler === 'function' 144 | ? bodyHandler(body as BaseResponse) 145 | : body as R 146 | } 147 | } 148 | } 149 | 150 | export class PicaComicError extends Error { 151 | readonly code: number 152 | readonly error: string 153 | readonly detail?: string 154 | constructor (code: number, error: string, message: string, detail?: string) { 155 | super(message) 156 | this.name = 'PicaComicError' 157 | this.code = code 158 | this.error = error 159 | this.detail = detail 160 | } 161 | } 162 | 163 | /* Endpoints */ 164 | 165 | export const Endpoints = { 166 | register: declareEndpoint, RegisterPayload>(payload => { 167 | if (payload.birthday instanceof Date) { 168 | payload.birthday = payload.birthday.valueOf() 169 | } 170 | return { 171 | url: '/auth/register', 172 | method: 'POST', 173 | json: payload 174 | } 175 | }), 176 | signIn: declareEndpoint(payload => ({ 177 | url: '/auth/sign-in', 178 | method: 'POST', 179 | json: { 180 | email: payload.email, 181 | password: payload.password 182 | } 183 | })), 184 | punchIn: declareEndpoint(payload => ({ 185 | url: '/users/punch-in', 186 | method: 'POST', 187 | headers: { authorization: payload.token } 188 | })), 189 | fetchUserProfile: declareEndpoint(payload => ({ 190 | url: '/users/profile', 191 | method: 'GET', 192 | headers: { authorization: payload.token } 193 | })), 194 | fetchUserFavourite: declareEndpoint(payload => ({ 195 | url: '/users/favourite', 196 | method: 'GET', 197 | headers: { authorization: payload.token }, 198 | searchParams: { 199 | page: payload.page || 1, 200 | s: payload.sort || ComicSort.Default 201 | } 202 | })), 203 | fetchCategories: declareEndpoint(payload => ({ 204 | url: '/categories', 205 | method: 'GET', 206 | headers: { authorization: payload.token } 207 | })), 208 | fetchComics: declareEndpoint(payload => ({ 209 | url: '/comics', 210 | method: 'GET', 211 | headers: { authorization: payload.token }, 212 | searchParams: { 213 | c: payload.category, 214 | page: payload.page || 1, 215 | s: payload.sort || ComicSort.Default 216 | } 217 | })), 218 | fetchComicDetail: declareEndpoint(payload => ({ 219 | url: `/comics/${payload.comicId}`, 220 | method: 'GET', 221 | headers: { authorization: payload.token } 222 | })), 223 | fetchComicEpisodes: declareEndpoint(payload => ({ 224 | url: `/comics/${payload.comicId}/eps`, 225 | method: 'GET', 226 | headers: { authorization: payload.token }, 227 | searchParams: { page: payload.page || 1 } 228 | })), 229 | fetchComicEpisodePages: declareEndpoint(payload => ({ 230 | url: `/comics/${payload.comicId}/order/${payload.order}/pages`, 231 | method: 'GET', 232 | headers: { authorization: payload.token }, 233 | searchParams: { page: payload.page || 1 } 234 | })), 235 | fetchComicComments: declareEndpoint(payload => ({ 236 | url: `/comics/${payload.comicId}/comments`, 237 | method: 'GET', 238 | headers: { authorization: payload.token }, 239 | searchParams: { page: payload.page || 1 } 240 | }), (body) => { 241 | // Fixed page type problem 242 | if (body.data !== null && typeof body.data === 'object' && 'comments' in body.data) { 243 | const comments = (body.data as ComicCommentsResponse['data']).comments 244 | if (comments && typeof comments.page === 'string') { 245 | comments.page = parseInt(comments.page) 246 | } 247 | } return body as ComicCommentsResponse 248 | }), 249 | searchComics: declareEndpoint(payload => ({ 250 | url: '/comics/advanced-search', 251 | method: 'POST', 252 | headers: { authorization: payload.token }, 253 | searchParams: { page: payload.page || 1 }, 254 | json: { 255 | keyword: payload.keyword, 256 | categories: payload.categories, 257 | s: payload.sort || ComicSort.Default 258 | } 259 | })), 260 | switchComicLike: declareEndpoint(payload => ({ 261 | url: `/comics/${payload.comicId}/like`, 262 | method: 'POST', 263 | headers: { authorization: payload.token } 264 | })), 265 | switchComicFavourite: declareEndpoint(payload => ({ 266 | url: `/comics/${payload.comicId}/favourite`, 267 | method: 'POST', 268 | headers: { authorization: payload.token } 269 | })), 270 | setUserProfileSlogan: declareEndpoint, AuthorizationPayload & UserProfileSloganPayload>(payload => ({ 271 | url: '/users/profile', 272 | method: 'PUT', 273 | headers: { authorization: payload.token }, 274 | json: { slogan: payload.slogan } 275 | })) 276 | } 277 | 278 | export interface PicaComicAPIOptions { 279 | fetch?: Got | ExtendOptions 280 | appOptions?: Partial 281 | // eslint-disable-next-line no-use-before-define 282 | reauthorizationTokenCallback?: (self: PicaComicAPI) => string | undefined | Promise 283 | } 284 | 285 | function createReauthorizationTokenHook (self: PicaComicAPI): ExtendOptions { 286 | return { 287 | hooks: { 288 | afterResponse: [async (response, retryWithMergedOptions) => { 289 | if (response.statusCode !== 401) return response 290 | if (typeof self.reauthorizationTokenCallback !== 'function') return response 291 | 292 | const token = await self.reauthorizationTokenCallback(self) 293 | if (!token) return response 294 | 295 | const updatedOptions = { headers: { authorization: token } } 296 | return retryWithMergedOptions(updatedOptions) 297 | }] 298 | } 299 | } 300 | } 301 | 302 | const ImageToBeImg = 'https://img.picacomic.com' 303 | const ImageToBs = 'https://storage-b.picacomic.com' 304 | const ImageDefault = 'https://storage1.picacomic.com' 305 | 306 | function decodeImageTobeImgPath (path: string): string { 307 | if (!path.startsWith('tobeimg/')) return path 308 | const filename = path.substring(path.lastIndexOf('/') + 1) 309 | const encoded = filename.substring(0, filename.lastIndexOf('.')) 310 | const absoluteUrl = Buffer.from(encoded, 'base64').toString('utf-8') 311 | return absoluteUrl 312 | } 313 | 314 | export class PicaComicAPI implements FetcherInstanceHolder { 315 | public readonly fetch: Got 316 | public readonly appOptions?: Partial 317 | public readonly reauthorizationTokenCallback?: (self: this) => string | undefined | Promise 318 | 319 | constructor (options?: PicaComicAPIOptions) { 320 | this.appOptions = options?.appOptions 321 | this.reauthorizationTokenCallback = options?.reauthorizationTokenCallback 322 | 323 | const reauthorizationTokenHook = createReauthorizationTokenHook(this) 324 | this.fetch = options?.fetch && typeof options.fetch === 'object' 325 | ? got.extend(options.fetch, reauthorizationTokenHook) 326 | : got.extend(reauthorizationTokenHook) 327 | 328 | // create endpoint bindings 329 | Object.entries(Endpoints).forEach(([key, value]) => { 330 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment 331 | // @ts-ignore 332 | this[key] = value.bind(this, this) 333 | }) 334 | } 335 | 336 | readonly declare register: PickDeclaredEndpointFromInstance 337 | readonly declare signIn: PickDeclaredEndpointFromInstance 338 | readonly declare punchIn: PickDeclaredEndpointFromInstance 339 | readonly declare fetchUserProfile: PickDeclaredEndpointFromInstance 340 | readonly declare fetchUserFavourite: PickDeclaredEndpointFromInstance 341 | readonly declare fetchCategories: PickDeclaredEndpointFromInstance 342 | readonly declare fetchComics: PickDeclaredEndpointFromInstance 343 | readonly declare fetchComicDetail: PickDeclaredEndpointFromInstance 344 | readonly declare fetchComicEpisodes: PickDeclaredEndpointFromInstance 345 | readonly declare fetchComicEpisodePages: PickDeclaredEndpointFromInstance 346 | readonly declare fetchComicComments: PickDeclaredEndpointFromInstance 347 | readonly declare searchComics: PickDeclaredEndpointFromInstance 348 | readonly declare switchComicLike: PickDeclaredEndpointFromInstance 349 | readonly declare switchComicFavourite: PickDeclaredEndpointFromInstance 350 | readonly declare setUserProfileSlogan: PickDeclaredEndpointFromInstance 351 | 352 | readonly stringifyImageUrl = (payload: ImageMediaPayload): string => { 353 | let { path, fileServer } = payload 354 | 355 | if (path.startsWith('tobeimg/')) { 356 | if (fileServer === ImageDefault || fileServer === ImageToBs) { 357 | // See above 358 | return decodeImageTobeImgPath(path) 359 | } else { 360 | fileServer ||= ImageToBeImg 361 | path = '/' + path.substring(8) 362 | } 363 | } else if (path.startsWith('tobs/')) { 364 | fileServer ||= ImageToBs 365 | path = '/static/' + path.substring(5) 366 | } else { 367 | fileServer ||= ImageDefault 368 | path = '/static/' + path 369 | } 370 | 371 | return fileServer.replace(/\/$/, '') + path 372 | } 373 | 374 | readonly createImageRequest = (payload: ImageMediaPayload) => { 375 | const url = this.stringifyImageUrl(payload) 376 | return this.fetch.stream({ 377 | prefixUrl: '', 378 | url 379 | }) 380 | } 381 | 382 | readonly createImageRequestAsBuffer = (payload: ImageMediaPayload): Promise => { 383 | return new Promise((resolve, reject) => { 384 | try { 385 | const request = this.createImageRequest(payload) 386 | const buf: Buffer[] = [] 387 | request.once('error', reject) 388 | request.on('data', (chunk: Buffer) => { buf.push(chunk) }) 389 | request.once('end', () => { 390 | resolve(Buffer.concat(buf)) 391 | }) 392 | } catch (e) { 393 | reject(e) 394 | } 395 | }) 396 | } 397 | } 398 | -------------------------------------------------------------------------------- /src/client.ts: -------------------------------------------------------------------------------- 1 | import { PicaComicAPI, PicaComicAPIOptions } from './api' 2 | import * as types from './type' 3 | 4 | export interface PicaComicClientOptions extends Omit { 5 | email: string 6 | password: string 7 | token?: string 8 | onTokenIssued?: (token: string) => void | Promise 9 | } 10 | 11 | export class PicaComicClient { 12 | public readonly email: string 13 | public readonly password: string 14 | public readonly api: PicaComicAPI 15 | public readonly onTokenIssued?: (token: string) => void | Promise 16 | public token: string 17 | 18 | constructor (options: PicaComicClientOptions) { 19 | this.email = options.email 20 | this.password = options.password 21 | this.token = options.token || '' 22 | this.onTokenIssued = options.onTokenIssued 23 | this.api = new PicaComicAPI({ 24 | appOptions: options.appOptions, 25 | fetch: options.fetch, 26 | reauthorizationTokenCallback: PicaComicClient.reauthorizationTokenCallback.bind(this) 27 | }) 28 | } 29 | 30 | private static async reauthorizationTokenCallback (this: PicaComicClient, api: PicaComicAPI): Promise { 31 | const response = await api.signIn({ email: this.email, password: this.password }) 32 | const newToken = response.data.token 33 | this.token = newToken 34 | await this.onTokenIssued?.(newToken) 35 | return newToken 36 | } 37 | 38 | punchIn (): Promise { 39 | return this.api.punchIn({ token: this.token }) 40 | } 41 | 42 | fetchUserProfile (): Promise { 43 | return this.api.fetchUserProfile({ token: this.token }) 44 | } 45 | 46 | fetchUserFavourite (payload: types.UserFavouritePayload): Promise { 47 | return this.api.fetchUserFavourite({ token: this.token, ...payload }) 48 | } 49 | 50 | fetchCategories (): Promise { 51 | return this.api.fetchCategories({ token: this.token }) 52 | } 53 | 54 | fetchComics (payload: types.ComicsPayload): Promise { 55 | return this.api.fetchComics({ token: this.token, ...payload }) 56 | } 57 | 58 | fetchComicDetail (payload: types.ComicDetailPayload): Promise { 59 | return this.api.fetchComicDetail({ token: this.token, ...payload }) 60 | } 61 | 62 | fetchComicEpisodes (payload: types.ComicEpisodesPayload): Promise { 63 | return this.api.fetchComicEpisodes({ token: this.token, ...payload }) 64 | } 65 | 66 | fetchComicEpisodePages (payload: types.ComicEpisodePagesPayload): Promise { 67 | return this.api.fetchComicEpisodePages({ token: this.token, ...payload }) 68 | } 69 | 70 | fetchComicComments (payload: types.ComicCommentsPayload): Promise { 71 | return this.api.fetchComicComments({ token: this.token, ...payload }) 72 | } 73 | 74 | searchComics (payload: types.SearchComicsPayload): Promise { 75 | return this.api.searchComics({ token: this.token, ...payload }) 76 | } 77 | 78 | switchComicLike (payload: types.ComicIdPayload): Promise { 79 | return this.api.switchComicLike({ token: this.token, ...payload }) 80 | } 81 | 82 | switchComicFavourite (payload: types.ComicIdPayload): Promise { 83 | return this.api.switchComicFavourite({ token: this.token, ...payload }) 84 | } 85 | 86 | setUserProfileSlogan (payload: types.UserProfileSloganPayload): Promise> { 87 | return this.api.setUserProfileSlogan({ token: this.token, ...payload }) 88 | } 89 | 90 | stringifyImageUrl (payload: types.ImageMediaPayload): string { 91 | return this.api.stringifyImageUrl(payload) 92 | } 93 | 94 | createImageRequest (payload: types.ImageMediaPayload): ReturnType { 95 | return this.api.createImageRequest(payload) 96 | } 97 | 98 | createImageRequestAsBuffer (payload: types.ImageMediaPayload): Promise { 99 | return this.api.createImageRequestAsBuffer(payload) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './type' 2 | export * from './api' 3 | export * from './client' 4 | -------------------------------------------------------------------------------- /src/type.ts: -------------------------------------------------------------------------------- 1 | export interface BaseResponse { 2 | code: number 3 | message: string 4 | data: T 5 | } 6 | 7 | export interface RegisterPayload { 8 | name: string 9 | email: string 10 | password: string 11 | question1: string 12 | question2: string 13 | question3: string 14 | answer1: string 15 | answer2: string 16 | answer3: string 17 | birthday: string | Date | number 18 | gender: 'm' | 'f' | 'bot' 19 | } 20 | 21 | export interface SignInPayload { 22 | email: string 23 | password: string 24 | } 25 | 26 | export type SignInResponse = BaseResponse<{ token: string }> 27 | 28 | export interface AuthorizationPayload { 29 | token: string 30 | } 31 | 32 | export type PunchInResponse = BaseResponse<{ res: { status: 'ok' | 'fail', punchInLastDay?: string } }> 33 | 34 | export interface ImageMedia { 35 | originalName: string 36 | path: string 37 | fileServer: string 38 | } 39 | 40 | export type ImageMediaPayload = ImageMedia | { path: string, fileServer?: string } 41 | 42 | export interface User { 43 | _id: string 44 | birthday: string 45 | email: string 46 | gender: 'm' | 'f' | 'bot' 47 | name: string 48 | slogan?: string 49 | title: string 50 | verified: boolean 51 | exp: number 52 | level: number 53 | characters: string[] 54 | character?: string 55 | role?: string 56 | created_at: string 57 | avatar?: ImageMedia 58 | isPunched: boolean 59 | } 60 | 61 | export type UserProfileResponse = BaseResponse<{ user: User }> 62 | 63 | export enum ComicSort { 64 | Default = 'ua', 65 | NewToOld = 'dd', 66 | OldToNew = 'da', 67 | Like = 'ld', 68 | View = 'vd' 69 | } 70 | 71 | export interface UserFavouritePayload { 72 | page?: number 73 | sort?: ComicSort 74 | } 75 | 76 | export interface Comic { 77 | _id: string 78 | title: string 79 | author?: string 80 | totalViews: number 81 | totalLikes: number 82 | pagesCount: number 83 | epsCount: number 84 | finished: boolean 85 | categories: string[] 86 | thumb: ImageMedia 87 | likesCount: number 88 | id?: string 89 | } 90 | 91 | export type UserFavouriteResponse = BaseResponse<{ 92 | comics: { 93 | docs: Comic[] 94 | total: number 95 | limit: number 96 | page: number 97 | pages: number 98 | } 99 | }> 100 | 101 | export interface Category { 102 | _id?: string 103 | title: string 104 | thumb: ImageMedia 105 | isWeb?: boolean 106 | active?: boolean 107 | link?: string 108 | description?: string 109 | } 110 | 111 | export type CategoriesResponse = BaseResponse<{ categories: Category[] }> 112 | 113 | export interface ComicsPayload { 114 | /** Category title */ 115 | category: string 116 | page?: number 117 | sort?: ComicSort 118 | } 119 | 120 | export type ComicsResponse = BaseResponse<{ 121 | comics: { 122 | docs: Comic[] 123 | total: number 124 | limit: number 125 | page: number 126 | pages: number 127 | } 128 | }> 129 | 130 | export interface Creator { 131 | _id: string 132 | gender: string 133 | name: string 134 | slogan?: string 135 | title?: string 136 | verified?: boolean 137 | exp: number 138 | level: number 139 | characters: string[] 140 | character?: string 141 | role?: string 142 | avatar?: ImageMedia 143 | } 144 | 145 | export interface ComicDetail extends Comic { 146 | _creator: Creator 147 | chineseTeam: string 148 | description?: string 149 | tags: string[] 150 | updated_at: string 151 | created_at: string 152 | allowDownload: boolean 153 | allowComment: boolean 154 | viewsCount: number 155 | commentsCount: number 156 | isFavourite: boolean 157 | isLiked: boolean 158 | } 159 | 160 | export interface ComicIdPayload { 161 | comicId: string 162 | } 163 | 164 | export type ComicDetailPayload = ComicIdPayload 165 | 166 | export type ComicDetailResponse = BaseResponse<{ comic: ComicDetail }> 167 | 168 | export interface ComicEpisode { 169 | _id: string 170 | title: string 171 | order: number 172 | updated_at: string 173 | id: string 174 | } 175 | 176 | export interface ComicEpisodesPayload extends ComicIdPayload { 177 | page?: number 178 | } 179 | 180 | export type ComicEpisodesResponse = BaseResponse<{ 181 | eps: { 182 | docs: ComicEpisode[] 183 | total: number 184 | limit: number 185 | page: number 186 | pages: number 187 | } 188 | }> 189 | 190 | export interface ComicEpisodePage { 191 | _id: string 192 | media: ImageMedia 193 | id: string 194 | } 195 | 196 | export interface ComicEpisodePagesPayload extends ComicIdPayload { 197 | order: number 198 | page?: number 199 | } 200 | 201 | export type ComicEpisodePagesResponse = BaseResponse<{ 202 | pages: { 203 | docs: ComicEpisodePage[] 204 | total: number 205 | limit: number 206 | page: number 207 | pages: number 208 | }, 209 | ep: Pick 210 | }> 211 | 212 | export interface ComicCommentsPayload extends ComicIdPayload { 213 | page?: number 214 | } 215 | 216 | export interface ComicComment { 217 | _id: string 218 | _user: Creator 219 | _comic: string 220 | content: string 221 | isTop: boolean 222 | hide: boolean 223 | created_at: string 224 | likesCount: number 225 | commentsCount: number 226 | isLiked: boolean 227 | id: string 228 | } 229 | 230 | export type ComicCommentsResponse = BaseResponse<{ 231 | comments: { 232 | docs: ComicComment[] 233 | total: number 234 | limit: number 235 | page: number 236 | pages: number 237 | } 238 | topComments: ComicComment[] 239 | }> 240 | 241 | export interface SearchedComic { 242 | _id: string 243 | title: string 244 | author?: string 245 | totalViews?: number 246 | totalLikes?: number 247 | likesCount: number 248 | finished: boolean 249 | categories: string[] 250 | thumb: ImageMedia 251 | chineseTeam?: string 252 | description?: string 253 | tags: string[] 254 | updated_at: string 255 | created_at: string 256 | } 257 | 258 | export interface SearchComicsPayload { 259 | keyword: string 260 | categories?: string[] 261 | page?: number 262 | sort?: ComicSort 263 | } 264 | 265 | export type SearchComicsResponse = BaseResponse<{ 266 | comics: { 267 | docs: SearchedComic[] 268 | total: number 269 | limit: number 270 | page: number 271 | pages: number 272 | } 273 | }> 274 | 275 | export type SwitchComicLikeResponse = BaseResponse<{ action: 'like' | 'unlike' }> 276 | 277 | export type SwitchComicFavouriteResponse = BaseResponse<{ action: 'favourite' | 'un_favourite' }> 278 | 279 | export interface UserProfileSloganPayload { 280 | slogan: string 281 | } 282 | -------------------------------------------------------------------------------- /test/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l2studio/picacomic-api/e601fee0bf77f8ce7fa757adf186f79b342d0b2b/test/index.ts -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Enable incremental compilation */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es2018", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ 22 | // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | 26 | /* Modules */ 27 | "module": "commonjs", /* Specify what module code is generated. */ 28 | // "rootDir": "./", /* Specify the root folder within your source files. */ 29 | // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ 30 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 31 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 32 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 33 | // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ 34 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 35 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 36 | // "resolveJsonModule": true, /* Enable importing .json files */ 37 | // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ 38 | 39 | /* JavaScript Support */ 40 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ 41 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 42 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ 43 | 44 | /* Emit */ 45 | "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 46 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 47 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 48 | "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 49 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ 50 | "outDir": "lib", /* Specify an output folder for all emitted files. */ 51 | "removeComments": true, /* Disable emitting comments. */ 52 | // "noEmit": true, /* Disable emitting files from a compilation. */ 53 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 54 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ 55 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 56 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 58 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 59 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 60 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 61 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 62 | // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ 63 | // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ 64 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 65 | // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ 66 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 67 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 68 | 69 | /* Interop Constraints */ 70 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 71 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 72 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */ 73 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 74 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 75 | 76 | /* Type Checking */ 77 | "strict": true, /* Enable all strict type-checking options. */ 78 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ 79 | // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ 80 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 81 | // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ 82 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 83 | // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ 84 | // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ 85 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 86 | // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ 87 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ 88 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 89 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 90 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 91 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ 92 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 93 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ 94 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 95 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 96 | 97 | /* Completeness */ 98 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 99 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 100 | }, 101 | "exclude": [ 102 | "node_modules" 103 | ], 104 | "include": [ 105 | "src" 106 | ] 107 | } 108 | --------------------------------------------------------------------------------