├── .editorconfig ├── .github └── workflows │ └── test.yml ├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── bin.js ├── configs ├── .dockerignore ├── Dockerfile ├── close.yml ├── deploy.yml ├── nginx-template.conf └── preview.yml ├── example.png ├── lib ├── build.js ├── call-cloudflare.js ├── changed.js ├── debug.js ├── deploy.js ├── detect-docker.js ├── dirs.js ├── find-package-up.js ├── init.js ├── purge.js ├── run-image.js ├── show-error.js ├── show-help.js ├── show-spinner.js ├── show-version.js └── sign.js ├── package.json ├── pnpm-lock.yaml └── purge.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | permissions: 8 | contents: read 9 | jobs: 10 | test: 11 | name: Test 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout the repository 15 | uses: actions/checkout@v3 16 | - name: Install pnpm 17 | uses: pnpm/action-setup@v2 18 | with: 19 | version: 7.29.3 20 | - name: Install Node.js 21 | uses: actions/setup-node@v3 22 | with: 23 | node-version: 18 24 | cache: pnpm 25 | - name: Install all dependencies 26 | run: pnpm install --frozen-lockfile 27 | - name: Run tests 28 | run: pnpm test 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | pnpm-lock.yaml 2 | 3 | example.png 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | This project adheres to [Semantic Versioning](http://semver.org/). 3 | 4 | ## 0.9.3 5 | * Move to the new Github Actions output API. 6 | 7 | ## 0.9.2 8 | * Fixed sending all traffic to latest revision. 9 | 10 | ## 0.9.1 11 | * Fixed `run` command for server with custom `Dockerfile` and without `dist`. 12 | 13 | ## 0.9 14 | * Added `preview` command. 15 | * Added `close` preview. 16 | * Added GitHub Deployment to CI. 17 | * Added workflows for preview pull requests. 18 | 19 | ## 0.8.1 20 | * Updated `dotenv`. 21 | * Updated GitHub Actions config example. 22 | 23 | ## 0.8 24 | * Added `pnpm` support. 25 | 26 | ## 0.7.2 27 | * Replaced `nanocolors` with `piococolors`. 28 | * Reduced package size. 29 | 30 | ## 0.7.1 31 | * Replaced `colorette` with `nanocolors`. 32 | 33 | ## 0.7 34 | * Dropped Node.js 13 support. 35 | * Reduced dependencies. 36 | 37 | ## 0.6.21 38 | * Speed-up Docker build. 39 | 40 | ## 0.6.20 41 | * Updated workflow config. 42 | * Removed `ora`. 43 | 44 | ## 0.6.19 45 | * Update deploy workflow example. 46 | 47 | ## 0.6.18 48 | * Fix `sign` command. 49 | 50 | ## 0.6.17 51 | * Added color output to CI on deploy. 52 | 53 | ## 0.6.16 54 | * Fixed `.avif` support. 55 | 56 | ## 0.6.15 57 | * Fixed `colorette` imports. 58 | 59 | ## 0.6.14 60 | * Replace color output library. 61 | 62 | ## 0.6.13 63 | * Reduce dependencies. 64 | 65 | ## 0.6.12 66 | * Fix Node.js 14 support. 67 | 68 | ## 0.6.11 69 | * Improve image downloading output. 70 | 71 | ## 0.6.10 72 | * Use `stderr` for debug messages. 73 | 74 | ## 0.6.9 75 | * Remove color from GitHub Actions output variable. 76 | 77 | ## 0.6.8 78 | * Fix GitHub Actions output variable. 79 | 80 | ## 0.6.7 81 | * Fix mark to check `ssdeploy changed` hash. 82 | 83 | ## 0.6.6 84 | * Use configs in `ssdeploy changed` hash. 85 | * Remove white spaces from `WEBSITE_URL` environment variable too. 86 | * Fix GitHub Actions output variable. 87 | * Fix text in `ssdeploy changed`. 88 | 89 | ## 0.6.5 90 | * Fix error message. 91 | 92 | ## 0.6.4 93 | * Fix loading previous hash in `ssdeploy changed`. 94 | 95 | ## 0.6.3 96 | * Fix syntax error in GitHub Actions workflow. 97 | 98 | ## 0.6.2 99 | * Clean up GitHub Actions workflow. 100 | 101 | ## 0.6.1 102 | * Fix GitHub Actions workflow for `ssdeploy changed`. 103 | 104 | ## 0.6 105 | * Do not spend resources to deploy website if files were not changed. 106 | * Fix colors on GitHub Actions. 107 | 108 | ## 0.5.1 109 | * Fix `trim()` error on default region environment variable. 110 | 111 | ## 0.5 112 | * Add `npm` support. 113 | * Add `--verbose` by default to deploy workflow. 114 | * Fix error on new line and spaces in environment variables. 115 | 116 | ## 0.4.2 117 | * Fix deploy without previous images to clean. 118 | 119 | ## 0.4.1 120 | * Show step number during the build. 121 | 122 | ## 0.4 123 | * Rename `node_modules/ssdeploy/purge` to `node_modules/ssdeploy/purge.js`. 124 | * Move configs to `node_modules/ssdeploy/configs`. 125 | 126 | ## 0.3.1 127 | * Fix cleaned images count. 128 | 129 | ## 0.3 130 | * Show the size of the image after build. 131 | 132 | ## 0.2.4 133 | * Fix first deploy. 134 | * Fix deploy on local laptop. 135 | 136 | ## 0.2.3 137 | * Clean up GitHub Actions workflow. 138 | 139 | ## 0.2.2 140 | * Add `--verbose` support to `ssdeploy run` and `ssdeploy shell`. 141 | 142 | ## 0.2.1 143 | * Do not open browser on `ssdeploy shell`. 144 | 145 | ## 0.2 146 | * Rename project from `solid-state-deploy` to `ssdeploy`. 147 | * Add `shell` command. 148 | 149 | ## 0.1 150 | * Initial release. 151 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright 2019 Andrey Sitnik 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Solid State Deploy 2 | 3 | Deploy simple websites with Google Cloud and Cloudflare. 4 | It is like Netlify with: 5 | 6 | * **Better performance.** Cloudflare has more features for fast websites 7 | than Netlify CDN. For instance, HTTP/3 and TLS 1.3 0-RTT. 8 | * **Flexibility.** You can have crontab jobs and simple scripts 9 | (without persistence storage). You will have powerful and well documented 10 | Nginx config to define custom headers and redirects. 11 | * **Lack of vendor lock-in.** We use industry standards like Docker 12 | and Nginx. You can change CI, CDN, or Docker cloud separately. 13 | * **Local tests.** You can run a server on your laptop to test redirects 14 | and scripts. 15 | 16 | You will have built-in HTTPS and deploy by `git push`. 17 | 18 | ssdeploy example 19 | 20 | We also have trade-offs. It is not free, but for a simple website, 21 | it will cost you cents per month. You need more steps to install it, 22 | but after you have the same simple workflow. 23 | 24 | 25 | Sponsored by Evil Martians 27 | 28 | 29 | ## Install 30 | 31 | 1. Create an account in [Google Cloud]. 32 | 2. Go to **IAM & Admin** → **Service Accounts**, 33 | click **Create Service Account** and fill form: 34 | * Service Account Name: `Github-actions` 35 | * Service Account Description: `Deploy from Github Actions` 36 | 3. Add **Cloud Run Admin**, **Storage Admin**, **Service Account User** roles. 37 | 4. Click **Create Key**, choose **JSON** → **Create**, download and keep 38 | file for a while. 39 | 5. Open **Container Registry** and enable the service. 40 | 6. Open **Cloud Run** and start the service. 41 | 7. Go to your Github page of your project at **Settings** → **Secrets**. 42 | 8. Add new secret `WEBSITE_URL` with URL to your website domain 43 | (like `example.com`). 44 | 9. Add new secret `GCLOUD_PROJECT` with Google Cloud project name like 45 | `test-255417`. You can find project ID by opening a project switcher 46 | at the top of [Google Cloud]. 47 | 10. Choose application name (like `examplecom`) and add `GCLOUD_APP` secret with 48 | this name. 49 | 11. Call `base64 key-partition-….json` (file from step 4) and add `GCLOUD_AUTH` 50 | secret with the base64 content of this file. 51 | 12. Install Solid State Deploy to your project. 52 | 53 | ```sh 54 | npm i ssdeploy 55 | ``` 56 | 13. Create Github Actions workflow by calling: 57 | 58 | ```sh 59 | npx ssdeploy init 60 | ``` 61 | 14. Your project should build HTML files by `npm build` and put them to `dist/`. 62 | 15. Push the project’s changes to Github Actions to start deploying. 63 | Open **Actions** tab on Github to check out the process. 64 | 16. Go to **Cloud Run** at [Google Cloud] and find your server. Open it 65 | by clicking on the name and find the URL like `examplecom-hjv54hv.a.run.app`. 66 | Check that the website is working. 67 | 17. Click on **Manage Custom Domains** → **Add mapping**. Select your app, 68 | **Verify a new domain**, and enter your domain name. 69 | Finish domain verification with Webmaster Central. 70 | 18. After verification open **Add mapping** dialog again, select your app, 71 | domain, and leave subdomain blank. You will get `A` and `AAAA` records. 72 | 19. Create a new [Cloudflare] account. 73 | Create a site with `A` and `AAAA` records from Cloud Run. 74 | 20. Enable **HTTP/3** and **0-RTT** in Cloudflare **Network** settings. 75 | 21. Find **Zone ID** at site overview and create **API token** 76 | with `cache cleaner` name and `Cache Purge`/`Edit` permission. 77 | 22. Use them in `CLOUDFLARE_ZONE` and `CLOUDFLARE_TOKEN` secrets at Github. 78 | 23. Go to Google Cloud Run, **Manage Custom Domains** → **Add mapping** 79 | to add `www` subdomain and add `CNAME` record to Cloudflare **DNS** 80 | settings. 81 | 82 | We recommend checking the final result 83 | [for blocking in Russia](https://isitblockedinrussia.com/) and recreate 84 | Cloudflare account to change IP addressed. 85 | 86 | Few extra steps will improve security: 87 | 88 | 1. Go to Cloudflare **SSL/TLS** settings and enable **Full** encryption mode. 89 | 2. Add `CAA` records to Cloudflare **DNS** settings: 90 | 91 | ```js 92 | CAA @ 0 "only allow specific hostname" digicert.com 93 | CAA @ 0 "only allow specific hostname" letsencrypt.org 94 | CAA www 0 "only allow specific hostname" digicert.com 95 | CAA www 0 "only allow specific hostname" letsencrypt.org 96 | ``` 97 | 3. Enable **DNSSEC** in **DNS** settings. 98 | 4. Enable **HTST** by creating `nginx.conf` in the root of your project with: 99 | 100 | ```cpp 101 | add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"; 102 | add_header X-Content-Type-Options "nosniff"; 103 | ``` 104 | 105 | [Google Cloud]: https://console.cloud.google.com/ 106 | [Cloudflare]: https://www.cloudflare.com/ 107 | 108 | 109 | ## Deploy 110 | 111 | Just push commits to `master`: 112 | 113 | ```sh 114 | git push origin master 115 | ``` 116 | 117 | You can switch deploy branch at `.Github/workflows/deploy.yml`. 118 | 119 | 120 | ## Run Server Locally 121 | 122 | To test the Docker image locally run: 123 | 124 | ```sh 125 | npm build 126 | npx ssdeploy run 127 | ``` 128 | 129 | ## Deploy Server Locally 130 | 131 | You can deploy a server from the laptop. It can be useful to debug. 132 | 133 | You need to install [Google Cloud SDK](https://cloud.google.com/sdk/install) 134 | and call: 135 | 136 | ```sh 137 | npx ssdeploy deploy 138 | ``` 139 | 140 | 141 | ## Custom Nginx config 142 | 143 | In custom Nginx config, you can define headers and redirects. Create `nginx.conf` 144 | in your project root. 145 | 146 | ```cpp 147 | if ($host ~ ^www\.(?.+)$) { 148 | return 301 https://$domain$request_uri; 149 | } 150 | 151 | location ~* "(\.css|\.png|\.svg|\.woff2)$" { 152 | add_header Cache-Control "public, max-age=31536000, immutable"; 153 | } 154 | ``` 155 | 156 | It will be included inside the `server` context. 157 | 158 | 159 | ## Custom Docker config 160 | 161 | Custom `Dockerfile` should be placed at your project root. It can be used 162 | to define crontab jobs: 163 | 164 | ```sh 165 | FROM nginx:alpine 166 | RUN rm -R /etc/nginx/conf.d 167 | COPY ./dist/ /var/www/ 168 | COPY ./node_modules/ssdeploy/configs/nginx.conf /etc/nginx/nginx.template 169 | COPY ./nginx.conf /etc/nginx/server.conf 170 | RUN echo "#\!/bin/sh\necho 1" > /etc/periodic/hourly/example 171 | RUN chmod a+x /etc/periodic/hourly/example 172 | CMD crond && envsubst \$PORT < /etc/nginx/nginx.template > /etc/nginx/nginx.conf && nginx 173 | ``` 174 | -------------------------------------------------------------------------------- /bin.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import dotenv from 'dotenv' 4 | import pico from 'picocolors' 5 | 6 | import deploy, { stopPreview } from './lib/deploy.js' 7 | import showVersion from './lib/show-version.js' 8 | import showHelp from './lib/show-help.js' 9 | import runImage from './lib/run-image.js' 10 | import changed from './lib/changed.js' 11 | import purge from './lib/purge.js' 12 | import init from './lib/init.js' 13 | import sign from './lib/sign.js' 14 | 15 | dotenv.config() 16 | 17 | function getPullRequestId() { 18 | let pr = process.argv[3] 19 | if (!pr) { 20 | process.stderr.write(pico.red('Missed pull request ID') + '\n') 21 | process.exit(1) 22 | } 23 | return pr 24 | } 25 | 26 | async function run() { 27 | let command = process.argv[2] 28 | if (command === '--version') { 29 | await showVersion() 30 | } else if (!command || command === 'help' || command === '--help') { 31 | showHelp() 32 | } else if (command === 'init') { 33 | await init() 34 | } else if (command === 'shell') { 35 | await runImage('/bin/sh') 36 | } else if (command === 'run') { 37 | await runImage() 38 | } else if (command === 'purge') { 39 | await purge() 40 | } else if (command === 'changed') { 41 | await changed() 42 | } else if (command === 'deploy') { 43 | await deploy() 44 | } else if (command === 'preview') { 45 | await deploy(getPullRequestId()) 46 | } else if (command === 'close') { 47 | await stopPreview(getPullRequestId()) 48 | } else if (command === 'sign') { 49 | let file = process.argv[3] 50 | if (!file) { 51 | process.stderr.write(pico.red('Missed file to sign') + '\n') 52 | process.exit(1) 53 | } 54 | await sign(file) 55 | } else { 56 | process.stderr.write(pico.red(`Unknown command ${command}`) + '\n\n') 57 | showHelp() 58 | process.exit(1) 59 | } 60 | } 61 | 62 | run().catch(e => { 63 | if (!e.own) process.stderr.write(pico.red(e.stack) + '\n') 64 | process.exit(1) 65 | }) 66 | -------------------------------------------------------------------------------- /configs/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | !node_modules/ssdeploy/configs/ 3 | .github/ 4 | .cache/ 5 | .git/ 6 | src/ 7 | .gitignore 8 | .editorconfig 9 | README.md 10 | LICENSE 11 | package.json 12 | yarn.lock 13 | pnpm-lock.yaml 14 | -------------------------------------------------------------------------------- /configs/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:alpine 2 | RUN rm -R /etc/nginx/conf.d 3 | COPY ./nginx-template.conf /etc/nginx/nginx.template 4 | COPY ./nginx.conf /etc/nginx/server.conf 5 | COPY ./dist/ /var/www/ 6 | CMD envsubst \$PORT < /etc/nginx/nginx.template > /etc/nginx/nginx.conf && nginx 7 | -------------------------------------------------------------------------------- /configs/close.yml: -------------------------------------------------------------------------------- 1 | name: Clean Preview 2 | on: 3 | pull_request: 4 | types: [ closed ] 5 | jobs: 6 | close: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Clean from GitHub 10 | uses: bobheadxi/deployments@v1 11 | with: 12 | step: delete-env 13 | token: ${{ secrets.GITHUB_TOKEN }} 14 | env: preview-${{ github.event.number }} 15 | - name: Checkout the repository 16 | uses: actions/checkout@v3 17 | - name: Install Node.js 18 | uses: actions/setup-node@v3 19 | with: 20 | node-version: 18 21 | cache: npm 22 | - name: Install dependencies 23 | run: npm install --production --frozen-lockfile 24 | - name: Auth Google Cloud 25 | uses: google-github-actions/auth@v0 26 | with: 27 | credentials_json: ${{ secrets.GCLOUD_AUTH }} 28 | - name: Install Google Cloud 29 | uses: google-github-actions/setup-gcloud@v0 30 | - name: Clean from Google Cloud 31 | run: ./node_modules/.bin/ssdeploy close $PR --verbose 32 | env: 33 | PR: ${{ github.event.number }} 34 | GCLOUD_APP: ${{ secrets.GCLOUD_APP }} 35 | GCLOUD_PROJECT: ${{ secrets.GCLOUD_PROJECT }} 36 | CLOUDFLARE_ZONE: ${{ secrets.CLOUDFLARE_ZONE }} 37 | CLOUDFLARE_TOKEN: ${{ secrets.CLOUDFLARE_TOKEN }} 38 | -------------------------------------------------------------------------------- /configs/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | on: 3 | push: 4 | branches: 5 | - main 6 | env: 7 | FORCE_COLOR: 2 8 | jobs: 9 | deploy: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout the repository 13 | uses: actions/checkout@v3 14 | - name: Install Node.js 15 | uses: actions/setup-node@v3 16 | with: 17 | node-version: 18 18 | cache: npm 19 | - name: Install dependencies 20 | run: npm install --production --frozen-lockfile 21 | - name: Build static files 22 | run: npm build 23 | - name: Check files changes 24 | id: hash 25 | run: ./node_modules/.bin/ssdeploy changed 26 | env: 27 | WEBSITE_URL: ${{ secrets.WEBSITE_URL }} 28 | - name: Auth Google Cloud 29 | uses: google-github-actions/auth@v0 30 | with: 31 | credentials_json: ${{ secrets.GCLOUD_AUTH }} 32 | - name: Install Google Cloud 33 | if: "!steps.hash.outputs.noChanges" 34 | uses: google-github-actions/setup-gcloud@v0 35 | - name: Deploy files 36 | if: "!steps.hash.outputs.noChanges" 37 | run: ./node_modules/.bin/ssdeploy deploy --verbose 38 | env: 39 | GCLOUD_APP: ${{ secrets.GCLOUD_APP }} 40 | GCLOUD_PROJECT: ${{ secrets.GCLOUD_PROJECT }} 41 | CLOUDFLARE_ZONE: ${{ secrets.CLOUDFLARE_ZONE }} 42 | CLOUDFLARE_TOKEN: ${{ secrets.CLOUDFLARE_TOKEN }} 43 | -------------------------------------------------------------------------------- /configs/nginx-template.conf: -------------------------------------------------------------------------------- 1 | worker_processes 1; 2 | pid /run/nginx.pid; 3 | daemon off; 4 | 5 | events { 6 | worker_connections 1024; 7 | } 8 | 9 | http { 10 | access_log off; 11 | error_log stderr error; 12 | server_tokens off; 13 | 14 | include mime.types; 15 | types { 16 | application/manifest+json webmanifest; 17 | } 18 | default_type application/octet-stream; 19 | charset_types application/javascript text/css application/manifest+json image/svg+xml; 20 | sendfile on; 21 | 22 | server { 23 | listen $PORT; 24 | 25 | root /var/www; 26 | charset UTF-8; 27 | gzip_static on; 28 | 29 | include /etc/nginx/server.conf; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /configs/preview.yml: -------------------------------------------------------------------------------- 1 | name: Preview 2 | on: 3 | pull_request: 4 | env: 5 | FORCE_COLOR: 2 6 | jobs: 7 | preview: 8 | runs-on: ubuntu-latest 9 | if: github.ref != 'refs/heads/main' 10 | steps: 11 | - name: Notify about new deployment 12 | uses: bobheadxi/deployments@v1 13 | id: deployment 14 | with: 15 | step: start 16 | token: ${{ secrets.GITHUB_TOKEN }} 17 | ref: ${{ github.head_ref }} 18 | env: preview-${{ github.event.number }} 19 | - name: Checkout the repository 20 | uses: actions/checkout@v3 21 | - name: Install Node.js 22 | uses: actions/setup-node@v3 23 | with: 24 | node-version: 18 25 | cache: npm 26 | - name: Install dependencies 27 | run: npm install --production --frozen-lockfile 28 | - name: Build static files 29 | run: npm build 30 | - name: Check files changes 31 | id: hash 32 | run: ./node_modules/.bin/ssdeploy changed 33 | env: 34 | WEBSITE_URL: ${{ secrets.WEBSITE_URL }} 35 | - name: Auth Google Cloud 36 | uses: google-github-actions/auth@v0 37 | with: 38 | credentials_json: ${{ secrets.GCLOUD_AUTH }} 39 | - name: Install Google Cloud 40 | uses: google-github-actions/setup-gcloud@v0 41 | - name: Deploy files 42 | id: deploy 43 | run: ./node_modules/.bin/ssdeploy preview $PR --verbose 44 | env: 45 | PR: ${{ github.event.number }} 46 | GCLOUD_APP: ${{ secrets.GCLOUD_APP }} 47 | GCLOUD_PROJECT: ${{ secrets.GCLOUD_PROJECT }} 48 | CLOUDFLARE_ZONE: ${{ secrets.CLOUDFLARE_ZONE }} 49 | CLOUDFLARE_TOKEN: ${{ secrets.CLOUDFLARE_TOKEN }} 50 | - name: Update deployment status 51 | uses: bobheadxi/deployments@v1 52 | if: always() 53 | with: 54 | step: finish 55 | token: ${{ secrets.GITHUB_TOKEN }} 56 | status: ${{ job.status }} 57 | env: ${{ steps.deployment.outputs.env }} 58 | env_url: ${{ steps.deploy.outputs.url }} 59 | deployment_id: ${{ steps.deployment.outputs.deployment_id }} 60 | -------------------------------------------------------------------------------- /example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ai/ssdeploy/cd65ade8bc5f771ad698a71fa7dc0e226bd7c391/example.png -------------------------------------------------------------------------------- /lib/build.js: -------------------------------------------------------------------------------- 1 | import { writeFile, copyFile, unlink } from 'fs/promises' 2 | import { basename, join } from 'path' 3 | import { spawn, exec } from 'child_process' 4 | import { existsSync } from 'fs' 5 | import bytes from 'bytes' 6 | import pico from 'picocolors' 7 | 8 | import debug, { debugCmd } from './debug.js' 9 | import { findPackageDir } from './find-package-up.js' 10 | import detectDocker from './detect-docker.js' 11 | import showSpinner from './show-spinner.js' 12 | import { CONFIGS } from './dirs.js' 13 | 14 | function getSize(bin, name, env) { 15 | return new Promise(resolve => { 16 | exec( 17 | `${bin} image inspect ${name}:latest --format='{{.Size}}'`, 18 | { env }, 19 | (error, stdout) => { 20 | if (error) { 21 | resolve() 22 | } else { 23 | resolve(parseInt(stdout)) 24 | } 25 | } 26 | ) 27 | }) 28 | } 29 | 30 | export default async function build(name, env = process.env, forceDocker) { 31 | let root = await findPackageDir() 32 | if (!name) name = basename(root) 33 | let bin = forceDocker ? 'docker' : await detectDocker() 34 | 35 | let customDocker = join(root, 'Dockerfile') 36 | let localDocker = join(CONFIGS, 'Dockerfile') 37 | let customNginxTemplate = join(root, 'nginx-template.conf') 38 | let localNginxTemplate = join(CONFIGS, 'nginx-template.conf') 39 | let customIgnore = join(root, '.dockerignore') 40 | let localIgnore = join(CONFIGS, '.dockerignore') 41 | let nginxPath = join(root, 'nginx.conf') 42 | 43 | let dockerfile = localDocker 44 | if (existsSync(customDocker)) dockerfile = customDocker 45 | 46 | let args = ['build', '-f', dockerfile, '-t', name, '.'] 47 | debugCmd(bin + ' ' + args.join(' ')) 48 | 49 | let text = 'Building Docker image' 50 | if (bin === 'podman') text = 'Building Podman image' 51 | let spinner = showSpinner(text) 52 | 53 | let temp = [] 54 | try { 55 | if (!existsSync(customIgnore)) { 56 | await copyFile(localIgnore, customIgnore) 57 | temp.push(customIgnore) 58 | } 59 | if (!existsSync(nginxPath)) { 60 | await writeFile(nginxPath, '\n') 61 | temp.push(nginxPath) 62 | } 63 | if (!existsSync(customNginxTemplate)) { 64 | await copyFile(localNginxTemplate, customNginxTemplate) 65 | temp.push(customNginxTemplate) 66 | } 67 | 68 | await new Promise((resolve, reject) => { 69 | let docker = spawn(bin, args, { env }) 70 | let steps = 0 71 | docker.stdout.on('data', data => { 72 | if (!process.env.CI && !process.env.GITHUB_ACTIONS) { 73 | if (data.toString().startsWith('STEP ')) { 74 | steps += 1 75 | process.stdout.write(`${text}: step ${steps}\n`) 76 | } 77 | } 78 | debug(data) 79 | }) 80 | let output = '' 81 | docker.stderr.on('data', data => { 82 | output += data.toString() 83 | }) 84 | docker.on('exit', code => { 85 | if (code === 0) { 86 | resolve() 87 | } else { 88 | spinner.fail() 89 | process.stderr.write(pico.red(output)) 90 | let err = new Error('Docker error ' + code) 91 | err.own = true 92 | reject(err) 93 | } 94 | }) 95 | }) 96 | } finally { 97 | await Promise.all(temp.map(i => unlink(i))) 98 | } 99 | 100 | let size = await getSize(bin, name, env) 101 | if (size) { 102 | spinner.succeed(`Built ${bytes(size, { unitSeparator: ' ' })} image`) 103 | } 104 | 105 | return name 106 | } 107 | -------------------------------------------------------------------------------- /lib/call-cloudflare.js: -------------------------------------------------------------------------------- 1 | import { request } from 'https' 2 | 3 | export default async function callCloudflare (command, opts) { 4 | await new Promise((resolve, reject) => { 5 | let req = request( 6 | { 7 | method: 'POST', 8 | hostname: 'api.cloudflare.com', 9 | path: `/client/v4/zones/${process.env.CLOUDFLARE_ZONE}/${command}`, 10 | headers: { 11 | 'Authorization': `Bearer ${process.env.CLOUDFLARE_TOKEN}`, 12 | 'Content-Type': 'application/json' 13 | } 14 | }, 15 | res => { 16 | let data = '' 17 | res.on('data', chunk => { 18 | data += chunk 19 | }) 20 | res.on('end', () => { 21 | let answer 22 | try { 23 | answer = JSON.parse(data) 24 | } catch { 25 | console.error(data) 26 | process.exit(1) 27 | } 28 | if (answer.success) { 29 | resolve() 30 | } else { 31 | reject(new Error(answer.errors[0].message)) 32 | } 33 | }) 34 | } 35 | ) 36 | if (opts) req.write(JSON.stringify(opts)) 37 | req.on('error', reject) 38 | req.end() 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /lib/changed.js: -------------------------------------------------------------------------------- 1 | import { existsSync, createReadStream } from 'fs' 2 | import { writeFile } from 'fs/promises' 3 | import folderHash from 'folder-hash' 4 | import { join } from 'path' 5 | import { get } from 'https' 6 | import hasha from 'hasha' 7 | import pico from 'picocolors' 8 | 9 | import showError, { showWarning } from './show-error.js' 10 | import showSpinner, { wrap } from './show-spinner.js' 11 | import { findPackageDir } from './find-package-up.js' 12 | 13 | async function fileHash(file) { 14 | if (!existsSync(file)) return '' 15 | return hasha.fromStream(createReadStream(file)) 16 | } 17 | 18 | async function loadPrev(url) { 19 | if (url.startsWith('http://')) { 20 | throw showError('`ssdeploy changed` supports only https:// websites') 21 | } 22 | if (!url.startsWith('https://')) { 23 | url = 'https://' + url 24 | } 25 | 26 | try { 27 | new URL(url) 28 | } catch (e) { 29 | if (e.code === 'ERR_INVALID_URL') { 30 | throw showError( 31 | 'Ivalid URL `' + url + '` in `WEBSITE_URL` environment variables' 32 | ) 33 | } else { 34 | throw e 35 | } 36 | } 37 | 38 | if (!url.endsWith('/')) url += '/' 39 | let hashUrl = url + 'ssdeploy-hash.txt' 40 | 41 | let spinner = showSpinner('Loading hash from previous deploy') 42 | 43 | return new Promise(resolve => { 44 | function error(e) { 45 | spinner.fail() 46 | if (typeof e === 'string') { 47 | showWarning(e) 48 | } else { 49 | showWarning(e.message) 50 | } 51 | resolve('') 52 | } 53 | 54 | let req = get(hashUrl, res => { 55 | if (res.statusCode === 404) { 56 | error( 57 | '`' + 58 | hashUrl + 59 | '` file was not found.\n' + 60 | 'It is OK for first deploy.' 61 | ) 62 | return 63 | } else if (res.statusCode !== 200) { 64 | error( 65 | 'Your website return ' + 66 | res.statusCode + 67 | ' code ' + 68 | 'on `' + 69 | hashUrl + 70 | '` request' 71 | ) 72 | } 73 | let data = '' 74 | res.on('data', chunk => { 75 | data += chunk.toString() 76 | }) 77 | res.on('end', () => { 78 | if (data.endsWith('=')) { 79 | spinner.succeed() 80 | resolve(data) 81 | } else { 82 | error('Wrong data found at `' + hashUrl + '`') 83 | } 84 | }) 85 | }) 86 | req.on('error', error) 87 | req.end() 88 | }) 89 | } 90 | 91 | async function calcCurrent() { 92 | let root = await findPackageDir() 93 | let dist = join(root, 'dist') 94 | let ignoreFile = join(root, '.dockerignore') 95 | let dockerFile = join(root, 'Dockerfile') 96 | let nginxFile = join(root, 'nginx.conf') 97 | let workflowFile = join(root, '.github', 'workflows', 'deploy.yml') 98 | let [{ hash }, workflow, ignore, docker, nginx] = await Promise.all([ 99 | folderHash.hashElement(dist), 100 | fileHash(workflowFile), 101 | fileHash(ignoreFile), 102 | fileHash(dockerFile), 103 | fileHash(nginxFile) 104 | ]) 105 | return [dist, hasha(hash + workflow + ignore + docker + nginx) + '='] 106 | } 107 | 108 | export default async function changed() { 109 | if (!process.env.WEBSITE_URL) { 110 | showWarning( 111 | 'Set `WEBSITE_URL` environment variables at your CI ', 112 | 'to deploy websites only when files will be changed' 113 | ) 114 | return 115 | } 116 | 117 | let [prev, [dist, current]] = await Promise.all([ 118 | loadPrev(process.env.WEBSITE_URL.trim()), 119 | calcCurrent() 120 | ]) 121 | await wrap('Writing ssdeploy-hash.txt', async () => { 122 | await writeFile(join(dist, 'ssdeploy-hash.txt'), current) 123 | }) 124 | if (prev === current) { 125 | process.stderr.write( 126 | pico.yellow('Files were not changed from latest deploy. Stop deploy.\n') 127 | ) 128 | await writeFile(process.env.GITHUB_OUTPUT, 'noChanges=1\n') 129 | } else { 130 | if (prev !== '') { 131 | process.stderr.write('Files was changed. ') 132 | } 133 | process.stderr.write('Continue deploy.\n') 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /lib/debug.js: -------------------------------------------------------------------------------- 1 | import pico from 'picocolors' 2 | 3 | export let isDebug = process.argv.includes('--verbose') 4 | 5 | export function debugCmd(cmd) { 6 | debug(pico.gray('$ ' + cmd) + '\n') 7 | } 8 | 9 | export default function debug(text) { 10 | if (isDebug) { 11 | process.stderr.write(text) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /lib/deploy.js: -------------------------------------------------------------------------------- 1 | import { spawn, execSync } from 'child_process' 2 | import { writeFile } from 'fs/promises' 3 | import pico from 'picocolors' 4 | 5 | import debug, { isDebug, debugCmd } from './debug.js' 6 | import { wrap } from './show-spinner.js' 7 | import showError from './show-error.js' 8 | import build from './build.js' 9 | import purge from './purge.js' 10 | 11 | let safeEnv = {} 12 | for (let i in process.env) { 13 | if (!/^(GCLOUD_|CLOUDFLARE_)/.test(i)) safeEnv[i] = process.env[i] 14 | } 15 | 16 | async function exec(command, opts) { 17 | return new Promise((resolve, reject) => { 18 | debugCmd(command) 19 | let cmd = spawn(command, { ...opts, env: safeEnv, shell: '/bin/bash' }) 20 | let stdout = '' 21 | let stderr = '' 22 | cmd.stdout.on('data', data => { 23 | let out = data.toString() 24 | stdout += out 25 | debug(out) 26 | }) 27 | cmd.stderr.on('data', data => { 28 | stderr += data.toString() 29 | debug(pico.yellow(data)) 30 | }) 31 | cmd.on('exit', code => { 32 | if (code === 0) { 33 | resolve(stdout.trim()) 34 | } else if (isDebug) { 35 | reject(showError('Exit code ' + code)) 36 | } else { 37 | reject(showError(stderr)) 38 | } 39 | }) 40 | }) 41 | } 42 | 43 | async function push(image) { 44 | await wrap('Pushing image to Google Cloud Registry', async () => { 45 | await exec('gcloud auth configure-docker --quiet') 46 | await exec(`docker push ${image}`) 47 | }) 48 | } 49 | 50 | async function setPreviewUrl(project, app, region = 'us-east1', preview) { 51 | let base = execSync( 52 | `gcloud run services describe ${app} ` + 53 | `--project ${project} --region ${region} --format 'value(status.url)'` 54 | ) 55 | .toString() 56 | .trim() 57 | let url = base.replace('https://', `https://preview-${preview}---`) 58 | await writeFile(process.env.GITHUB_OUTPUT, `url=${url}\n`) 59 | } 60 | 61 | async function run(image, project, app, region, preview) { 62 | await wrap('Starting image on Google Cloud Run', async spinner => { 63 | await exec( 64 | `gcloud run deploy ${app} --image ${image} ` + 65 | `--project ${project} --region=${region} ` + 66 | '--platform managed --allow-unauthenticated' + 67 | (preview ? ` --tag preview-${preview} --no-traffic` : '') 68 | ) 69 | spinner.succeed(`Image was deployed at ${region} server`) 70 | }) 71 | } 72 | 73 | async function cleanOldImages(image, tag) { 74 | await wrap('Cleaning registry from old images', async spinner => { 75 | let removed = 0 76 | let filter = '-tags:*' 77 | if (tag) filter = `tags:${tag}` 78 | let out = await exec( 79 | 'gcloud container images list-tags ' + 80 | `${image} --filter='${filter}' --format='get(digest)'` 81 | ) 82 | if (out !== '') { 83 | await Promise.all( 84 | out.split('\n').map(i => { 85 | removed += 1 86 | return exec( 87 | `gcloud container images delete '${image}@${i}' --quiet` + 88 | (tag ? ' --force-delete-tags' : '') 89 | ) 90 | }) 91 | ) 92 | } 93 | spinner.succeed(`Removed ${removed} images`) 94 | }) 95 | } 96 | 97 | async function migrateTraffic(project, app, region) { 98 | await wrap('Moving traffic to new revision', async () => { 99 | await exec( 100 | 'gcloud run services update-traffic ' + 101 | `${app} --project ${project} --region=${region} --to-latest` 102 | ) 103 | }) 104 | } 105 | 106 | export default async function deploy(preview) { 107 | if (!process.env.GCLOUD_PROJECT || !process.env.GCLOUD_APP) { 108 | throw showError( 109 | 'Set `GCLOUD_PROJECT` and `GCLOUD_APP` environment variables at your CI' 110 | ) 111 | } 112 | 113 | let project = process.env.GCLOUD_PROJECT.trim() 114 | let app = process.env.GCLOUD_APP.trim() 115 | let region = process.env.GCLOUD_REGION || 'us-east1' 116 | let image = `gcr.io/${project}/${app}` 117 | let taggedImage = preview ? `${image}:preview-${preview}` : image 118 | 119 | await build(taggedImage, safeEnv, true, preview) 120 | await push(taggedImage) 121 | await run(taggedImage, project, app, region, preview) 122 | if (preview) { 123 | await setPreviewUrl(project, app, region, preview) 124 | } else { 125 | await migrateTraffic(project, app, region) 126 | await purge() 127 | } 128 | await cleanOldImages(image) 129 | } 130 | 131 | export async function stopPreview(preview) { 132 | let project = process.env.GCLOUD_PROJECT.trim() 133 | let app = process.env.GCLOUD_APP.trim() 134 | let image = `gcr.io/${project}/${app}` 135 | let region = process.env.GCLOUD_REGION || 'us-east1' 136 | 137 | await exec( 138 | `gcloud run services update-traffic ${app} ` + 139 | `--region ${region} --project ${project} ` + 140 | `--remove-tags preview-${preview} --async` 141 | ) 142 | await cleanOldImages(image, `preview-${preview}`) 143 | } 144 | -------------------------------------------------------------------------------- /lib/detect-docker.js: -------------------------------------------------------------------------------- 1 | import { promisify } from 'util' 2 | import child from 'child_process' 3 | 4 | let exec = promisify(child.exec) 5 | let runner 6 | 7 | export default async function detectDocker () { 8 | if (!runner) { 9 | try { 10 | await exec('podman --version') 11 | runner = 'podman' 12 | } catch (e) { 13 | runner = 'docker' 14 | } 15 | } 16 | return runner 17 | } 18 | -------------------------------------------------------------------------------- /lib/dirs.js: -------------------------------------------------------------------------------- 1 | import { dirname, join } from 'path' 2 | 3 | let self = new URL(import.meta.url).pathname 4 | 5 | export const ROOT = join(dirname(self), '..') 6 | export const CONFIGS = join(ROOT, 'configs') 7 | -------------------------------------------------------------------------------- /lib/find-package-up.js: -------------------------------------------------------------------------------- 1 | import { resolve, parse, dirname } from 'path' 2 | import { existsSync } from 'fs' 3 | 4 | import showError from './show-error.js' 5 | 6 | async function findUp(name, cwd = '') { 7 | let directory = resolve(cwd) 8 | let { root } = parse(directory) 9 | 10 | while (true) { 11 | let foundPath = await resolve(directory, name) 12 | 13 | if (existsSync(foundPath)) { 14 | return foundPath 15 | } 16 | 17 | if (directory === root) { 18 | return undefined 19 | } 20 | 21 | directory = dirname(directory) 22 | } 23 | } 24 | 25 | export async function findPackageUp(cwd) { 26 | let path = await findUp('package.json', cwd) 27 | if (!path) throw showError('Can’t find package.json') 28 | return path 29 | } 30 | 31 | export async function findPackageDir(cwd) { 32 | return dirname(await findPackageUp(cwd)) 33 | } 34 | -------------------------------------------------------------------------------- /lib/init.js: -------------------------------------------------------------------------------- 1 | import { readFile, mkdir, writeFile } from 'fs/promises' 2 | import { dirname, join } from 'path' 3 | import { existsSync } from 'fs' 4 | 5 | import { findPackageDir } from './find-package-up.js' 6 | import { CONFIGS } from './dirs.js' 7 | 8 | async function copyTemplate(manager, name, to) { 9 | await mkdir(dirname(to), { recursive: true }) 10 | let template = await readFile(join(CONFIGS, name)) 11 | 12 | let config = template.toString() 13 | if (manager === 'yarn') { 14 | config = config 15 | .replace('cache: npm', 'cache: yarn') 16 | .replace(' npm ', ' yarn ') 17 | } else if (manager === 'pnpm') { 18 | config = config 19 | .replace('cache: npm', 'cache: pnpm') 20 | .replace(' npm ', ' pnpm ') 21 | } 22 | 23 | await writeFile(join(to, name), config) 24 | } 25 | 26 | export default async function init() { 27 | let root = await findPackageDir() 28 | let workflows = join(root, '.github', 'workflows') 29 | 30 | let manager = 'npm' 31 | if (existsSync(join(root, 'yarn.lock'))) { 32 | manager = 'yarn' 33 | } else if (existsSync(join(root, 'pnpm-lock.yaml'))) { 34 | manager = 'pnpm' 35 | } 36 | 37 | await Promise.all([ 38 | copyTemplate(manager, workflows, 'deploy.yml'), 39 | copyTemplate(manager, workflows, 'preview.yml'), 40 | copyTemplate(manager, workflows, 'close.yml') 41 | ]) 42 | } 43 | -------------------------------------------------------------------------------- /lib/purge.js: -------------------------------------------------------------------------------- 1 | import callCloudflare from './call-cloudflare.js' 2 | import { showWarning } from './show-error.js' 3 | import { wrap } from './show-spinner.js' 4 | 5 | export default async function purge () { 6 | if (!process.env.CLOUDFLARE_ZONE || !process.env.CLOUDFLARE_TOKEN) { 7 | showWarning( 8 | 'Get zone ID and API token in CLoudflare dashboard', 9 | 'and set `CLOUDFLARE_TOKEN` and `CLOUDFLARE_ZONE`', 10 | 'environment variables at your CI' 11 | ) 12 | } else { 13 | await wrap('Cleaning CDN cache', async spinner => { 14 | await callCloudflare('purge_cache', { purge_everything: true }) 15 | spinner.succeed('CDN cache was cleaned') 16 | }) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/run-image.js: -------------------------------------------------------------------------------- 1 | import { existsSync } from 'fs' 2 | import { spawn } from 'child_process' 3 | import { join } from 'path' 4 | import open from 'open' 5 | import pico from 'picocolors' 6 | 7 | import { findPackageDir } from './find-package-up.js' 8 | import detectDocker from './detect-docker.js' 9 | import { debugCmd } from './debug.js' 10 | import build from './build.js' 11 | 12 | let y = pico.yellow 13 | 14 | export default async function runImage(script) { 15 | let bin = await detectDocker() 16 | let name = await build() 17 | let root = await findPackageDir() 18 | let args = ['run'] 19 | if (existsSync(join(root, 'dist'))) { 20 | args = args.concat(['-v', './dist/:/var/www/']) 21 | } 22 | args = args.concat([ 23 | '--privileged', 24 | '--rm', 25 | '-p', 26 | '8000:80', 27 | '-e', 28 | 'PORT=80', 29 | '-it', 30 | name 31 | ]) 32 | if (script) args.push(script) 33 | debugCmd(bin + ' ' + args.join(' ')) 34 | spawn(bin, args, { stdio: 'inherit' }) 35 | if (!script) { 36 | let ctrlC = 'Ctrl+C' 37 | if (process.platform === 'darwin') ctrlC = 'Cmd + .' 38 | process.stderr.write( 39 | ` Website is available to test at ${y('http://localhost:8000/')}\n` + 40 | ` Press ${y(ctrlC)} to stop the server\n` 41 | ) 42 | open('http://localhost:8000/') 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib/show-error.js: -------------------------------------------------------------------------------- 1 | import pico from 'picocolors' 2 | 3 | export function showWarning(...lines) { 4 | lines = lines.map(line => { 5 | return line.replace(/`[^`]+`/g, i => pico.yellow(i.slice(1, -1))) 6 | }) 7 | process.stderr.write(pico.red(lines.join('\n')) + '\n') 8 | } 9 | 10 | export default function showError(...lines) { 11 | showWarning(...lines) 12 | let err = new Error('show error') 13 | err.own = true 14 | return err 15 | } 16 | -------------------------------------------------------------------------------- /lib/show-help.js: -------------------------------------------------------------------------------- 1 | import pico from 'picocolors' 2 | 3 | let b = pico.bold 4 | let y = pico.yellow 5 | let g = pico.green 6 | 7 | function print(...lines) { 8 | process.stdout.write(lines.join('\n') + '\n') 9 | } 10 | 11 | export default function showHelp() { 12 | print( 13 | b('Usage: ') + 'npx ssdeploy ' + g('COMMAND') + y(' [OPTION]'), 14 | 'Deploy simple websites with Google Cloud and Cloudflare', 15 | '', 16 | b('Commands:'), 17 | ' ' + g('init') + ' Create .github/workflow/deploy.yml', 18 | ' ' + g('deploy') + ' Deploy website to the cloud', 19 | ' ' + g('preview') + ' ' + y('PR') + ' Deploy preview', 20 | ' ' + g('close') + ' ' + y('PR') + ' Clean files from preview', 21 | ' ' + g('run') + ' Run Docker image locally', 22 | ' ' + g('shell') + ' Run shell inside Docker image', 23 | ' ' + g('purge') + ' Clean CDN cache', 24 | ' ' + g('changed') + ' Check changes between dist/ and website', 25 | ' ' + g('sign') + ' ' + y('FILE') + ' Sign security.txt', 26 | '', 27 | b('Arguments:'), 28 | ' ' + y('--verbose') + ' Show debug information', 29 | '', 30 | b('Examples:'), 31 | ' npx ssdeploy deploy', 32 | ' npx ssdeploy run', 33 | ' npx ssdeploy sign ./src/well-known/security.txt' 34 | ) 35 | } 36 | -------------------------------------------------------------------------------- /lib/show-spinner.js: -------------------------------------------------------------------------------- 1 | import pico from 'picocolors' 2 | 3 | export default function showSpinner(text) { 4 | process.stdout.write(pico.gray('- ') + text + '\n') 5 | let finished = false 6 | return { 7 | succeed(newText = text) { 8 | if (!finished) { 9 | finished = true 10 | process.stdout.write(pico.green('✔ ') + newText + '\n') 11 | } 12 | }, 13 | fail(newText = text) { 14 | if (!finished) { 15 | finished = true 16 | process.stdout.write(pico.red('✖ ') + newText + '\n') 17 | } 18 | } 19 | } 20 | } 21 | 22 | export async function wrap(text, cb) { 23 | let spinner = showSpinner(text) 24 | try { 25 | let result = await cb(spinner) 26 | spinner.succeed() 27 | return result 28 | } catch (e) { 29 | spinner.fail() 30 | throw e 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/show-version.js: -------------------------------------------------------------------------------- 1 | import { readFile } from 'fs/promises' 2 | import { join } from 'path' 3 | import pico from 'picocolors' 4 | 5 | import { ROOT } from './dirs.js' 6 | 7 | export default async function showVersion() { 8 | let packagePath = join(ROOT, 'package.json') 9 | let packageJson = await readFile(packagePath) 10 | let { version } = JSON.parse(packageJson) 11 | process.stdout.write(`ssdeploy ${pico.bold(version)}\n`) 12 | } 13 | -------------------------------------------------------------------------------- /lib/sign.js: -------------------------------------------------------------------------------- 1 | import { writeFile, unlink, rename, readFile } from 'fs/promises' 2 | import { promisify } from 'util' 3 | import child from 'child_process' 4 | 5 | let exec = promisify(child.exec) 6 | 7 | export default async function sign(path) { 8 | let content = await readFile(path) 9 | let cleared = content 10 | .toString() 11 | .replace(/-----BEGIN PGP SIGNED MESSAGE-----\nHash:[^\n]+\n\n/, '') 12 | .replace(/-----BEGIN PGP SIGNATURE-----\n\n[\W\w]+$/m, '') 13 | await writeFile(path, cleared) 14 | await exec(`gpg --clearsign ${path}`) 15 | await unlink(path) 16 | await rename(path + '.asc', path) 17 | } 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ssdeploy", 3 | "version": "0.9.3", 4 | "description": "Netlify replacement to deploy simple websites with better flexibility and speed and without vendor lock-in", 5 | "keywords": [ 6 | "deploy", 7 | "google cloud", 8 | "cloudflare", 9 | "netlify" 10 | ], 11 | "bin": "./bin.js", 12 | "type": "module", 13 | "engines": { 14 | "node": ">=14.0.0" 15 | }, 16 | "scripts": { 17 | "test": "eslint ." 18 | }, 19 | "dependencies": { 20 | "bytes": "^3.1.2", 21 | "dotenv": "^16.0.3", 22 | "folder-hash": "^4.0.4", 23 | "hasha": "^5.2.2", 24 | "open": "^8.4.2", 25 | "picocolors": "^1.0.0" 26 | }, 27 | "author": "Andrey Sitnik ", 28 | "license": "MIT", 29 | "repository": "ai/ssdeploy", 30 | "devDependencies": { 31 | "@logux/eslint-config": "^49.0.0", 32 | "clean-publish": "^4.1.1", 33 | "eslint": "^8.36.0", 34 | "eslint-config-standard": "^17.0.0", 35 | "eslint-plugin-import": "^2.27.5", 36 | "eslint-plugin-n": "^15.6.1", 37 | "eslint-plugin-prefer-let": "^3.0.1", 38 | "eslint-plugin-promise": "^6.1.1" 39 | }, 40 | "eslintConfig": { 41 | "extends": "@logux/eslint-config", 42 | "rules": { 43 | "no-console": "off" 44 | } 45 | }, 46 | "eslintIgnore": [ 47 | "lib/dirs.js" 48 | ], 49 | "prettier": { 50 | "arrowParens": "avoid", 51 | "jsxSingleQuote": false, 52 | "quoteProps": "consistent", 53 | "semi": false, 54 | "singleQuote": true, 55 | "trailingComma": "none" 56 | }, 57 | "clean-publish": { 58 | "cleanDocs": true 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | dependencies: 11 | bytes: 12 | specifier: ^3.1.2 13 | version: 3.1.2 14 | dotenv: 15 | specifier: ^16.0.3 16 | version: 16.0.3 17 | folder-hash: 18 | specifier: ^4.0.4 19 | version: 4.0.4 20 | hasha: 21 | specifier: ^5.2.2 22 | version: 5.2.2 23 | open: 24 | specifier: ^8.4.2 25 | version: 8.4.2 26 | picocolors: 27 | specifier: ^1.0.0 28 | version: 1.0.0 29 | devDependencies: 30 | '@logux/eslint-config': 31 | specifier: ^49.0.0 32 | version: 49.0.0(eslint-config-standard@17.0.0(eslint-plugin-import@2.27.5(eslint@8.36.0))(eslint-plugin-n@15.6.1(eslint@8.36.0))(eslint-plugin-promise@6.1.1(eslint@8.36.0))(eslint@8.36.0))(eslint-plugin-import@2.27.5(eslint@8.36.0))(eslint-plugin-n@15.6.1(eslint@8.36.0))(eslint-plugin-prefer-let@3.0.1)(eslint-plugin-promise@6.1.1(eslint@8.36.0))(eslint@8.36.0) 33 | clean-publish: 34 | specifier: ^4.1.1 35 | version: 4.1.1 36 | eslint: 37 | specifier: ^8.36.0 38 | version: 8.36.0 39 | eslint-config-standard: 40 | specifier: ^17.0.0 41 | version: 17.0.0(eslint-plugin-import@2.27.5(eslint@8.36.0))(eslint-plugin-n@15.6.1(eslint@8.36.0))(eslint-plugin-promise@6.1.1(eslint@8.36.0))(eslint@8.36.0) 42 | eslint-plugin-import: 43 | specifier: ^2.27.5 44 | version: 2.27.5(eslint@8.36.0) 45 | eslint-plugin-n: 46 | specifier: ^15.6.1 47 | version: 15.6.1(eslint@8.36.0) 48 | eslint-plugin-prefer-let: 49 | specifier: ^3.0.1 50 | version: 3.0.1 51 | eslint-plugin-promise: 52 | specifier: ^6.1.1 53 | version: 6.1.1(eslint@8.36.0) 54 | 55 | packages: 56 | 57 | '@eslint-community/eslint-utils@4.2.0': 58 | resolution: {integrity: sha512-gB8T4H4DEfX2IV9zGDJPOBgP1e/DbfCPDTtEqUMckpvzS1OYtva8JdFYBqMwYk7xAQ429WGF/UPqn8uQ//h2vQ==} 59 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 60 | peerDependencies: 61 | eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 62 | 63 | '@eslint-community/regexpp@4.4.0': 64 | resolution: {integrity: sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==} 65 | engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} 66 | 67 | '@eslint/eslintrc@2.0.1': 68 | resolution: {integrity: sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==} 69 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 70 | 71 | '@eslint/js@8.36.0': 72 | resolution: {integrity: sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==} 73 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 74 | 75 | '@humanwhocodes/config-array@0.11.8': 76 | resolution: {integrity: sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==} 77 | engines: {node: '>=10.10.0'} 78 | deprecated: Use @eslint/config-array instead 79 | 80 | '@humanwhocodes/module-importer@1.0.1': 81 | resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} 82 | engines: {node: '>=12.22'} 83 | 84 | '@humanwhocodes/object-schema@1.2.1': 85 | resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} 86 | deprecated: Use @eslint/object-schema instead 87 | 88 | '@logux/eslint-config@49.0.0': 89 | resolution: {integrity: sha512-5Aj1wytb+1oej3wLH8G7D35Glx88Iuj07JcVL3YruRhl4v7WZnF3w3RR3IVSQAvllQch4eemvHnLenrZ3PimFg==} 90 | engines: {node: '>=10.0.0'} 91 | peerDependencies: 92 | eslint: ^8.35.0 93 | eslint-config-standard: ^17.0.0 94 | eslint-plugin-import: ^2.27.5 95 | eslint-plugin-n: ^15.6.1 96 | eslint-plugin-prefer-let: ^3.0.1 97 | eslint-plugin-promise: ^6.1.1 98 | 99 | '@nodelib/fs.scandir@2.1.5': 100 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 101 | engines: {node: '>= 8'} 102 | 103 | '@nodelib/fs.stat@2.0.5': 104 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 105 | engines: {node: '>= 8'} 106 | 107 | '@nodelib/fs.walk@1.2.8': 108 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 109 | engines: {node: '>= 8'} 110 | 111 | '@types/json5@0.0.29': 112 | resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} 113 | 114 | acorn-jsx@5.3.2: 115 | resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} 116 | peerDependencies: 117 | acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 118 | 119 | acorn@8.8.2: 120 | resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} 121 | engines: {node: '>=0.4.0'} 122 | hasBin: true 123 | 124 | ajv@6.12.6: 125 | resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} 126 | 127 | ansi-regex@5.0.1: 128 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 129 | engines: {node: '>=8'} 130 | 131 | ansi-styles@4.3.0: 132 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 133 | engines: {node: '>=8'} 134 | 135 | argparse@2.0.1: 136 | resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 137 | 138 | array-buffer-byte-length@1.0.0: 139 | resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} 140 | 141 | array-includes@3.1.6: 142 | resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==} 143 | engines: {node: '>= 0.4'} 144 | 145 | array.prototype.flat@1.3.1: 146 | resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==} 147 | engines: {node: '>= 0.4'} 148 | 149 | array.prototype.flatmap@1.3.1: 150 | resolution: {integrity: sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==} 151 | engines: {node: '>= 0.4'} 152 | 153 | available-typed-arrays@1.0.5: 154 | resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} 155 | engines: {node: '>= 0.4'} 156 | 157 | balanced-match@1.0.2: 158 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 159 | 160 | brace-expansion@1.1.11: 161 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 162 | 163 | brace-expansion@2.0.1: 164 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 165 | 166 | braces@3.0.3: 167 | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 168 | engines: {node: '>=8'} 169 | 170 | builtins@5.0.1: 171 | resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} 172 | 173 | bytes@3.1.2: 174 | resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} 175 | engines: {node: '>= 0.8'} 176 | 177 | call-bind@1.0.2: 178 | resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} 179 | 180 | callsites@3.1.0: 181 | resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} 182 | engines: {node: '>=6'} 183 | 184 | chalk@4.1.2: 185 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 186 | engines: {node: '>=10'} 187 | 188 | clean-publish@4.1.1: 189 | resolution: {integrity: sha512-111O3MNk6x/dAbHZwG+iRZ4AYwpKqc7Qp1MarFhE1KtQIp9m9TkDuI+hedn7qgeFnLgSw3ItgEnHNwvhc7SmGg==} 190 | engines: {node: '>= 16.0.0'} 191 | hasBin: true 192 | 193 | color-convert@2.0.1: 194 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 195 | engines: {node: '>=7.0.0'} 196 | 197 | color-name@1.1.4: 198 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 199 | 200 | concat-map@0.0.1: 201 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 202 | 203 | cross-spawn@7.0.3: 204 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} 205 | engines: {node: '>= 8'} 206 | 207 | debug@3.2.7: 208 | resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} 209 | peerDependencies: 210 | supports-color: '*' 211 | peerDependenciesMeta: 212 | supports-color: 213 | optional: true 214 | 215 | debug@4.3.4: 216 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} 217 | engines: {node: '>=6.0'} 218 | peerDependencies: 219 | supports-color: '*' 220 | peerDependenciesMeta: 221 | supports-color: 222 | optional: true 223 | 224 | deep-is@0.1.4: 225 | resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} 226 | 227 | define-lazy-prop@2.0.0: 228 | resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} 229 | engines: {node: '>=8'} 230 | 231 | define-properties@1.2.0: 232 | resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} 233 | engines: {node: '>= 0.4'} 234 | 235 | doctrine@2.1.0: 236 | resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} 237 | engines: {node: '>=0.10.0'} 238 | 239 | doctrine@3.0.0: 240 | resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} 241 | engines: {node: '>=6.0.0'} 242 | 243 | dotenv@16.0.3: 244 | resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} 245 | engines: {node: '>=12'} 246 | 247 | es-abstract@1.21.2: 248 | resolution: {integrity: sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==} 249 | engines: {node: '>= 0.4'} 250 | 251 | es-set-tostringtag@2.0.1: 252 | resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} 253 | engines: {node: '>= 0.4'} 254 | 255 | es-shim-unscopables@1.0.0: 256 | resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} 257 | 258 | es-to-primitive@1.2.1: 259 | resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} 260 | engines: {node: '>= 0.4'} 261 | 262 | escape-string-regexp@4.0.0: 263 | resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} 264 | engines: {node: '>=10'} 265 | 266 | eslint-config-standard@17.0.0: 267 | resolution: {integrity: sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==} 268 | peerDependencies: 269 | eslint: ^8.0.1 270 | eslint-plugin-import: ^2.25.2 271 | eslint-plugin-n: ^15.0.0 272 | eslint-plugin-promise: ^6.0.0 273 | 274 | eslint-import-resolver-node@0.3.7: 275 | resolution: {integrity: sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==} 276 | 277 | eslint-module-utils@2.7.4: 278 | resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==} 279 | engines: {node: '>=4'} 280 | peerDependencies: 281 | '@typescript-eslint/parser': '*' 282 | eslint: '*' 283 | eslint-import-resolver-node: '*' 284 | eslint-import-resolver-typescript: '*' 285 | eslint-import-resolver-webpack: '*' 286 | peerDependenciesMeta: 287 | '@typescript-eslint/parser': 288 | optional: true 289 | eslint: 290 | optional: true 291 | eslint-import-resolver-node: 292 | optional: true 293 | eslint-import-resolver-typescript: 294 | optional: true 295 | eslint-import-resolver-webpack: 296 | optional: true 297 | 298 | eslint-plugin-es@4.1.0: 299 | resolution: {integrity: sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==} 300 | engines: {node: '>=8.10.0'} 301 | peerDependencies: 302 | eslint: '>=4.19.1' 303 | 304 | eslint-plugin-import@2.27.5: 305 | resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} 306 | engines: {node: '>=4'} 307 | peerDependencies: 308 | '@typescript-eslint/parser': '*' 309 | eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 310 | peerDependenciesMeta: 311 | '@typescript-eslint/parser': 312 | optional: true 313 | 314 | eslint-plugin-n@15.6.1: 315 | resolution: {integrity: sha512-R9xw9OtCRxxaxaszTQmQAlPgM+RdGjaL1akWuY/Fv9fRAi8Wj4CUKc6iYVG8QNRjRuo8/BqVYIpfqberJUEacA==} 316 | engines: {node: '>=12.22.0'} 317 | peerDependencies: 318 | eslint: '>=7.0.0' 319 | 320 | eslint-plugin-prefer-let@3.0.1: 321 | resolution: {integrity: sha512-vbznkkBSXB63d4o1o0NIm5C2ey3V5wKr/25dAvPdydQXdowAcnr69cbLgxd2YAG81IV5eddCO55Lp6gL7wSE4w==} 322 | engines: {node: '>=0.10.0'} 323 | 324 | eslint-plugin-promise@6.1.1: 325 | resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} 326 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 327 | peerDependencies: 328 | eslint: ^7.0.0 || ^8.0.0 329 | 330 | eslint-scope@7.1.1: 331 | resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==} 332 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 333 | 334 | eslint-utils@2.1.0: 335 | resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} 336 | engines: {node: '>=6'} 337 | 338 | eslint-utils@3.0.0: 339 | resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} 340 | engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} 341 | peerDependencies: 342 | eslint: '>=5' 343 | 344 | eslint-visitor-keys@1.3.0: 345 | resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} 346 | engines: {node: '>=4'} 347 | 348 | eslint-visitor-keys@2.1.0: 349 | resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} 350 | engines: {node: '>=10'} 351 | 352 | eslint-visitor-keys@3.3.0: 353 | resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==} 354 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 355 | 356 | eslint@8.36.0: 357 | resolution: {integrity: sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==} 358 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 359 | hasBin: true 360 | 361 | espree@9.5.0: 362 | resolution: {integrity: sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==} 363 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 364 | 365 | esquery@1.5.0: 366 | resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} 367 | engines: {node: '>=0.10'} 368 | 369 | esrecurse@4.3.0: 370 | resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} 371 | engines: {node: '>=4.0'} 372 | 373 | estraverse@5.3.0: 374 | resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} 375 | engines: {node: '>=4.0'} 376 | 377 | esutils@2.0.3: 378 | resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} 379 | engines: {node: '>=0.10.0'} 380 | 381 | fast-deep-equal@3.1.3: 382 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 383 | 384 | fast-glob@3.2.12: 385 | resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} 386 | engines: {node: '>=8.6.0'} 387 | 388 | fast-json-stable-stringify@2.1.0: 389 | resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} 390 | 391 | fast-levenshtein@2.0.6: 392 | resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} 393 | 394 | fastq@1.15.0: 395 | resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} 396 | 397 | file-entry-cache@6.0.1: 398 | resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} 399 | engines: {node: ^10.12.0 || >=12.0.0} 400 | 401 | fill-range@7.1.1: 402 | resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 403 | engines: {node: '>=8'} 404 | 405 | find-up@5.0.0: 406 | resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} 407 | engines: {node: '>=10'} 408 | 409 | flat-cache@3.0.4: 410 | resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} 411 | engines: {node: ^10.12.0 || >=12.0.0} 412 | 413 | flatted@3.2.7: 414 | resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} 415 | 416 | folder-hash@4.0.4: 417 | resolution: {integrity: sha512-zEyYH+UsHEfJJcCRSf9ai5I4CTZwZ8ObONRuEI5hcEmJY5pS0FUWKruX9mMnYJrgC7MlPFDYnGsK1R+WFYjLlQ==} 418 | engines: {node: '>=10.10.0'} 419 | hasBin: true 420 | 421 | for-each@0.3.3: 422 | resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} 423 | 424 | fs.realpath@1.0.0: 425 | resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} 426 | 427 | function-bind@1.1.1: 428 | resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} 429 | 430 | function.prototype.name@1.1.5: 431 | resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} 432 | engines: {node: '>= 0.4'} 433 | 434 | functions-have-names@1.2.3: 435 | resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} 436 | 437 | get-intrinsic@1.2.0: 438 | resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==} 439 | 440 | get-symbol-description@1.0.0: 441 | resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} 442 | engines: {node: '>= 0.4'} 443 | 444 | glob-parent@5.1.2: 445 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 446 | engines: {node: '>= 6'} 447 | 448 | glob-parent@6.0.2: 449 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} 450 | engines: {node: '>=10.13.0'} 451 | 452 | glob@7.2.3: 453 | resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} 454 | deprecated: Glob versions prior to v9 are no longer supported 455 | 456 | globals@13.20.0: 457 | resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} 458 | engines: {node: '>=8'} 459 | 460 | globalthis@1.0.3: 461 | resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} 462 | engines: {node: '>= 0.4'} 463 | 464 | gopd@1.0.1: 465 | resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} 466 | 467 | grapheme-splitter@1.0.4: 468 | resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} 469 | 470 | has-bigints@1.0.2: 471 | resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} 472 | 473 | has-flag@4.0.0: 474 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 475 | engines: {node: '>=8'} 476 | 477 | has-property-descriptors@1.0.0: 478 | resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} 479 | 480 | has-proto@1.0.1: 481 | resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} 482 | engines: {node: '>= 0.4'} 483 | 484 | has-symbols@1.0.3: 485 | resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} 486 | engines: {node: '>= 0.4'} 487 | 488 | has-tostringtag@1.0.0: 489 | resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} 490 | engines: {node: '>= 0.4'} 491 | 492 | has@1.0.3: 493 | resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} 494 | engines: {node: '>= 0.4.0'} 495 | 496 | hasha@5.2.2: 497 | resolution: {integrity: sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==} 498 | engines: {node: '>=8'} 499 | 500 | ignore@5.2.4: 501 | resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} 502 | engines: {node: '>= 4'} 503 | 504 | import-fresh@3.3.0: 505 | resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} 506 | engines: {node: '>=6'} 507 | 508 | imurmurhash@0.1.4: 509 | resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} 510 | engines: {node: '>=0.8.19'} 511 | 512 | inflight@1.0.6: 513 | resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} 514 | deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. 515 | 516 | inherits@2.0.4: 517 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 518 | 519 | internal-slot@1.0.5: 520 | resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} 521 | engines: {node: '>= 0.4'} 522 | 523 | is-array-buffer@3.0.2: 524 | resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} 525 | 526 | is-bigint@1.0.4: 527 | resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} 528 | 529 | is-boolean-object@1.1.2: 530 | resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} 531 | engines: {node: '>= 0.4'} 532 | 533 | is-callable@1.2.7: 534 | resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} 535 | engines: {node: '>= 0.4'} 536 | 537 | is-core-module@2.11.0: 538 | resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} 539 | 540 | is-date-object@1.0.5: 541 | resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} 542 | engines: {node: '>= 0.4'} 543 | 544 | is-docker@2.2.1: 545 | resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} 546 | engines: {node: '>=8'} 547 | hasBin: true 548 | 549 | is-extglob@2.1.1: 550 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 551 | engines: {node: '>=0.10.0'} 552 | 553 | is-glob@4.0.3: 554 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 555 | engines: {node: '>=0.10.0'} 556 | 557 | is-negative-zero@2.0.2: 558 | resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} 559 | engines: {node: '>= 0.4'} 560 | 561 | is-number-object@1.0.7: 562 | resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} 563 | engines: {node: '>= 0.4'} 564 | 565 | is-number@7.0.0: 566 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 567 | engines: {node: '>=0.12.0'} 568 | 569 | is-path-inside@3.0.3: 570 | resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} 571 | engines: {node: '>=8'} 572 | 573 | is-regex@1.1.4: 574 | resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} 575 | engines: {node: '>= 0.4'} 576 | 577 | is-shared-array-buffer@1.0.2: 578 | resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} 579 | 580 | is-stream@2.0.1: 581 | resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} 582 | engines: {node: '>=8'} 583 | 584 | is-string@1.0.7: 585 | resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} 586 | engines: {node: '>= 0.4'} 587 | 588 | is-symbol@1.0.4: 589 | resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} 590 | engines: {node: '>= 0.4'} 591 | 592 | is-typed-array@1.1.10: 593 | resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==} 594 | engines: {node: '>= 0.4'} 595 | 596 | is-weakref@1.0.2: 597 | resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} 598 | 599 | is-wsl@2.2.0: 600 | resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} 601 | engines: {node: '>=8'} 602 | 603 | isexe@2.0.0: 604 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 605 | 606 | js-sdsl@4.3.0: 607 | resolution: {integrity: sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==} 608 | 609 | js-yaml@4.1.0: 610 | resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} 611 | hasBin: true 612 | 613 | json-schema-traverse@0.4.1: 614 | resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} 615 | 616 | json-stable-stringify-without-jsonify@1.0.1: 617 | resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} 618 | 619 | json5@1.0.2: 620 | resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} 621 | hasBin: true 622 | 623 | levn@0.4.1: 624 | resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} 625 | engines: {node: '>= 0.8.0'} 626 | 627 | lilconfig@2.1.0: 628 | resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} 629 | engines: {node: '>=10'} 630 | 631 | locate-path@6.0.0: 632 | resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} 633 | engines: {node: '>=10'} 634 | 635 | lodash.merge@4.6.2: 636 | resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} 637 | 638 | lru-cache@6.0.0: 639 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} 640 | engines: {node: '>=10'} 641 | 642 | merge2@1.4.1: 643 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 644 | engines: {node: '>= 8'} 645 | 646 | micromatch@4.0.5: 647 | resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} 648 | engines: {node: '>=8.6'} 649 | 650 | minimatch@3.1.2: 651 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 652 | 653 | minimatch@5.1.6: 654 | resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} 655 | engines: {node: '>=10'} 656 | 657 | minimist@1.2.8: 658 | resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} 659 | 660 | ms@2.1.2: 661 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 662 | 663 | ms@2.1.3: 664 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 665 | 666 | natural-compare@1.4.0: 667 | resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} 668 | 669 | object-inspect@1.12.3: 670 | resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} 671 | 672 | object-keys@1.1.1: 673 | resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} 674 | engines: {node: '>= 0.4'} 675 | 676 | object.assign@4.1.4: 677 | resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} 678 | engines: {node: '>= 0.4'} 679 | 680 | object.values@1.1.6: 681 | resolution: {integrity: sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==} 682 | engines: {node: '>= 0.4'} 683 | 684 | once@1.4.0: 685 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 686 | 687 | open@8.4.2: 688 | resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} 689 | engines: {node: '>=12'} 690 | 691 | optionator@0.9.1: 692 | resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} 693 | engines: {node: '>= 0.8.0'} 694 | 695 | p-limit@3.1.0: 696 | resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} 697 | engines: {node: '>=10'} 698 | 699 | p-locate@5.0.0: 700 | resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} 701 | engines: {node: '>=10'} 702 | 703 | parent-module@1.0.1: 704 | resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} 705 | engines: {node: '>=6'} 706 | 707 | path-exists@4.0.0: 708 | resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 709 | engines: {node: '>=8'} 710 | 711 | path-is-absolute@1.0.1: 712 | resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} 713 | engines: {node: '>=0.10.0'} 714 | 715 | path-key@3.1.1: 716 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 717 | engines: {node: '>=8'} 718 | 719 | path-parse@1.0.7: 720 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 721 | 722 | picocolors@1.0.0: 723 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} 724 | 725 | picomatch@2.3.1: 726 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 727 | engines: {node: '>=8.6'} 728 | 729 | prelude-ls@1.2.1: 730 | resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} 731 | engines: {node: '>= 0.8.0'} 732 | 733 | punycode@2.3.0: 734 | resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} 735 | engines: {node: '>=6'} 736 | 737 | queue-microtask@1.2.3: 738 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 739 | 740 | regexp.prototype.flags@1.4.3: 741 | resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==} 742 | engines: {node: '>= 0.4'} 743 | 744 | regexpp@3.2.0: 745 | resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} 746 | engines: {node: '>=8'} 747 | 748 | requireindex@1.2.0: 749 | resolution: {integrity: sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==} 750 | engines: {node: '>=0.10.5'} 751 | 752 | resolve-from@4.0.0: 753 | resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} 754 | engines: {node: '>=4'} 755 | 756 | resolve@1.22.1: 757 | resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} 758 | hasBin: true 759 | 760 | reusify@1.0.4: 761 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 762 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 763 | 764 | rimraf@3.0.2: 765 | resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} 766 | deprecated: Rimraf versions prior to v4 are no longer supported 767 | hasBin: true 768 | 769 | run-parallel@1.2.0: 770 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 771 | 772 | safe-regex-test@1.0.0: 773 | resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} 774 | 775 | semver@6.3.0: 776 | resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} 777 | hasBin: true 778 | 779 | semver@7.3.8: 780 | resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} 781 | engines: {node: '>=10'} 782 | hasBin: true 783 | 784 | shebang-command@2.0.0: 785 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 786 | engines: {node: '>=8'} 787 | 788 | shebang-regex@3.0.0: 789 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 790 | engines: {node: '>=8'} 791 | 792 | side-channel@1.0.4: 793 | resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} 794 | 795 | string.prototype.trim@1.2.7: 796 | resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} 797 | engines: {node: '>= 0.4'} 798 | 799 | string.prototype.trimend@1.0.6: 800 | resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} 801 | 802 | string.prototype.trimstart@1.0.6: 803 | resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} 804 | 805 | strip-ansi@6.0.1: 806 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 807 | engines: {node: '>=8'} 808 | 809 | strip-bom@3.0.0: 810 | resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} 811 | engines: {node: '>=4'} 812 | 813 | strip-json-comments@3.1.1: 814 | resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} 815 | engines: {node: '>=8'} 816 | 817 | supports-color@7.2.0: 818 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 819 | engines: {node: '>=8'} 820 | 821 | supports-preserve-symlinks-flag@1.0.0: 822 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 823 | engines: {node: '>= 0.4'} 824 | 825 | text-table@0.2.0: 826 | resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} 827 | 828 | to-regex-range@5.0.1: 829 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 830 | engines: {node: '>=8.0'} 831 | 832 | tsconfig-paths@3.14.2: 833 | resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} 834 | 835 | type-check@0.4.0: 836 | resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 837 | engines: {node: '>= 0.8.0'} 838 | 839 | type-fest@0.20.2: 840 | resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} 841 | engines: {node: '>=10'} 842 | 843 | type-fest@0.8.1: 844 | resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} 845 | engines: {node: '>=8'} 846 | 847 | typed-array-length@1.0.4: 848 | resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} 849 | 850 | unbox-primitive@1.0.2: 851 | resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} 852 | 853 | uri-js@4.4.1: 854 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 855 | 856 | which-boxed-primitive@1.0.2: 857 | resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} 858 | 859 | which-typed-array@1.1.9: 860 | resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==} 861 | engines: {node: '>= 0.4'} 862 | 863 | which@2.0.2: 864 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 865 | engines: {node: '>= 8'} 866 | hasBin: true 867 | 868 | word-wrap@1.2.4: 869 | resolution: {integrity: sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==} 870 | engines: {node: '>=0.10.0'} 871 | 872 | wrappy@1.0.2: 873 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 874 | 875 | yallist@4.0.0: 876 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} 877 | 878 | yocto-queue@0.1.0: 879 | resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} 880 | engines: {node: '>=10'} 881 | 882 | snapshots: 883 | 884 | '@eslint-community/eslint-utils@4.2.0(eslint@8.36.0)': 885 | dependencies: 886 | eslint: 8.36.0 887 | eslint-visitor-keys: 3.3.0 888 | 889 | '@eslint-community/regexpp@4.4.0': {} 890 | 891 | '@eslint/eslintrc@2.0.1': 892 | dependencies: 893 | ajv: 6.12.6 894 | debug: 4.3.4 895 | espree: 9.5.0 896 | globals: 13.20.0 897 | ignore: 5.2.4 898 | import-fresh: 3.3.0 899 | js-yaml: 4.1.0 900 | minimatch: 3.1.2 901 | strip-json-comments: 3.1.1 902 | transitivePeerDependencies: 903 | - supports-color 904 | 905 | '@eslint/js@8.36.0': {} 906 | 907 | '@humanwhocodes/config-array@0.11.8': 908 | dependencies: 909 | '@humanwhocodes/object-schema': 1.2.1 910 | debug: 4.3.4 911 | minimatch: 3.1.2 912 | transitivePeerDependencies: 913 | - supports-color 914 | 915 | '@humanwhocodes/module-importer@1.0.1': {} 916 | 917 | '@humanwhocodes/object-schema@1.2.1': {} 918 | 919 | '@logux/eslint-config@49.0.0(eslint-config-standard@17.0.0(eslint-plugin-import@2.27.5(eslint@8.36.0))(eslint-plugin-n@15.6.1(eslint@8.36.0))(eslint-plugin-promise@6.1.1(eslint@8.36.0))(eslint@8.36.0))(eslint-plugin-import@2.27.5(eslint@8.36.0))(eslint-plugin-n@15.6.1(eslint@8.36.0))(eslint-plugin-prefer-let@3.0.1)(eslint-plugin-promise@6.1.1(eslint@8.36.0))(eslint@8.36.0)': 920 | dependencies: 921 | eslint: 8.36.0 922 | eslint-config-standard: 17.0.0(eslint-plugin-import@2.27.5(eslint@8.36.0))(eslint-plugin-n@15.6.1(eslint@8.36.0))(eslint-plugin-promise@6.1.1(eslint@8.36.0))(eslint@8.36.0) 923 | eslint-plugin-import: 2.27.5(eslint@8.36.0) 924 | eslint-plugin-n: 15.6.1(eslint@8.36.0) 925 | eslint-plugin-prefer-let: 3.0.1 926 | eslint-plugin-promise: 6.1.1(eslint@8.36.0) 927 | 928 | '@nodelib/fs.scandir@2.1.5': 929 | dependencies: 930 | '@nodelib/fs.stat': 2.0.5 931 | run-parallel: 1.2.0 932 | 933 | '@nodelib/fs.stat@2.0.5': {} 934 | 935 | '@nodelib/fs.walk@1.2.8': 936 | dependencies: 937 | '@nodelib/fs.scandir': 2.1.5 938 | fastq: 1.15.0 939 | 940 | '@types/json5@0.0.29': {} 941 | 942 | acorn-jsx@5.3.2(acorn@8.8.2): 943 | dependencies: 944 | acorn: 8.8.2 945 | 946 | acorn@8.8.2: {} 947 | 948 | ajv@6.12.6: 949 | dependencies: 950 | fast-deep-equal: 3.1.3 951 | fast-json-stable-stringify: 2.1.0 952 | json-schema-traverse: 0.4.1 953 | uri-js: 4.4.1 954 | 955 | ansi-regex@5.0.1: {} 956 | 957 | ansi-styles@4.3.0: 958 | dependencies: 959 | color-convert: 2.0.1 960 | 961 | argparse@2.0.1: {} 962 | 963 | array-buffer-byte-length@1.0.0: 964 | dependencies: 965 | call-bind: 1.0.2 966 | is-array-buffer: 3.0.2 967 | 968 | array-includes@3.1.6: 969 | dependencies: 970 | call-bind: 1.0.2 971 | define-properties: 1.2.0 972 | es-abstract: 1.21.2 973 | get-intrinsic: 1.2.0 974 | is-string: 1.0.7 975 | 976 | array.prototype.flat@1.3.1: 977 | dependencies: 978 | call-bind: 1.0.2 979 | define-properties: 1.2.0 980 | es-abstract: 1.21.2 981 | es-shim-unscopables: 1.0.0 982 | 983 | array.prototype.flatmap@1.3.1: 984 | dependencies: 985 | call-bind: 1.0.2 986 | define-properties: 1.2.0 987 | es-abstract: 1.21.2 988 | es-shim-unscopables: 1.0.0 989 | 990 | available-typed-arrays@1.0.5: {} 991 | 992 | balanced-match@1.0.2: {} 993 | 994 | brace-expansion@1.1.11: 995 | dependencies: 996 | balanced-match: 1.0.2 997 | concat-map: 0.0.1 998 | 999 | brace-expansion@2.0.1: 1000 | dependencies: 1001 | balanced-match: 1.0.2 1002 | 1003 | braces@3.0.3: 1004 | dependencies: 1005 | fill-range: 7.1.1 1006 | 1007 | builtins@5.0.1: 1008 | dependencies: 1009 | semver: 7.3.8 1010 | 1011 | bytes@3.1.2: {} 1012 | 1013 | call-bind@1.0.2: 1014 | dependencies: 1015 | function-bind: 1.1.1 1016 | get-intrinsic: 1.2.0 1017 | 1018 | callsites@3.1.0: {} 1019 | 1020 | chalk@4.1.2: 1021 | dependencies: 1022 | ansi-styles: 4.3.0 1023 | supports-color: 7.2.0 1024 | 1025 | clean-publish@4.1.1: 1026 | dependencies: 1027 | cross-spawn: 7.0.3 1028 | fast-glob: 3.2.12 1029 | lilconfig: 2.1.0 1030 | micromatch: 4.0.5 1031 | 1032 | color-convert@2.0.1: 1033 | dependencies: 1034 | color-name: 1.1.4 1035 | 1036 | color-name@1.1.4: {} 1037 | 1038 | concat-map@0.0.1: {} 1039 | 1040 | cross-spawn@7.0.3: 1041 | dependencies: 1042 | path-key: 3.1.1 1043 | shebang-command: 2.0.0 1044 | which: 2.0.2 1045 | 1046 | debug@3.2.7: 1047 | dependencies: 1048 | ms: 2.1.3 1049 | 1050 | debug@4.3.4: 1051 | dependencies: 1052 | ms: 2.1.2 1053 | 1054 | deep-is@0.1.4: {} 1055 | 1056 | define-lazy-prop@2.0.0: {} 1057 | 1058 | define-properties@1.2.0: 1059 | dependencies: 1060 | has-property-descriptors: 1.0.0 1061 | object-keys: 1.1.1 1062 | 1063 | doctrine@2.1.0: 1064 | dependencies: 1065 | esutils: 2.0.3 1066 | 1067 | doctrine@3.0.0: 1068 | dependencies: 1069 | esutils: 2.0.3 1070 | 1071 | dotenv@16.0.3: {} 1072 | 1073 | es-abstract@1.21.2: 1074 | dependencies: 1075 | array-buffer-byte-length: 1.0.0 1076 | available-typed-arrays: 1.0.5 1077 | call-bind: 1.0.2 1078 | es-set-tostringtag: 2.0.1 1079 | es-to-primitive: 1.2.1 1080 | function.prototype.name: 1.1.5 1081 | get-intrinsic: 1.2.0 1082 | get-symbol-description: 1.0.0 1083 | globalthis: 1.0.3 1084 | gopd: 1.0.1 1085 | has: 1.0.3 1086 | has-property-descriptors: 1.0.0 1087 | has-proto: 1.0.1 1088 | has-symbols: 1.0.3 1089 | internal-slot: 1.0.5 1090 | is-array-buffer: 3.0.2 1091 | is-callable: 1.2.7 1092 | is-negative-zero: 2.0.2 1093 | is-regex: 1.1.4 1094 | is-shared-array-buffer: 1.0.2 1095 | is-string: 1.0.7 1096 | is-typed-array: 1.1.10 1097 | is-weakref: 1.0.2 1098 | object-inspect: 1.12.3 1099 | object-keys: 1.1.1 1100 | object.assign: 4.1.4 1101 | regexp.prototype.flags: 1.4.3 1102 | safe-regex-test: 1.0.0 1103 | string.prototype.trim: 1.2.7 1104 | string.prototype.trimend: 1.0.6 1105 | string.prototype.trimstart: 1.0.6 1106 | typed-array-length: 1.0.4 1107 | unbox-primitive: 1.0.2 1108 | which-typed-array: 1.1.9 1109 | 1110 | es-set-tostringtag@2.0.1: 1111 | dependencies: 1112 | get-intrinsic: 1.2.0 1113 | has: 1.0.3 1114 | has-tostringtag: 1.0.0 1115 | 1116 | es-shim-unscopables@1.0.0: 1117 | dependencies: 1118 | has: 1.0.3 1119 | 1120 | es-to-primitive@1.2.1: 1121 | dependencies: 1122 | is-callable: 1.2.7 1123 | is-date-object: 1.0.5 1124 | is-symbol: 1.0.4 1125 | 1126 | escape-string-regexp@4.0.0: {} 1127 | 1128 | eslint-config-standard@17.0.0(eslint-plugin-import@2.27.5(eslint@8.36.0))(eslint-plugin-n@15.6.1(eslint@8.36.0))(eslint-plugin-promise@6.1.1(eslint@8.36.0))(eslint@8.36.0): 1129 | dependencies: 1130 | eslint: 8.36.0 1131 | eslint-plugin-import: 2.27.5(eslint@8.36.0) 1132 | eslint-plugin-n: 15.6.1(eslint@8.36.0) 1133 | eslint-plugin-promise: 6.1.1(eslint@8.36.0) 1134 | 1135 | eslint-import-resolver-node@0.3.7: 1136 | dependencies: 1137 | debug: 3.2.7 1138 | is-core-module: 2.11.0 1139 | resolve: 1.22.1 1140 | transitivePeerDependencies: 1141 | - supports-color 1142 | 1143 | eslint-module-utils@2.7.4(eslint-import-resolver-node@0.3.7)(eslint@8.36.0): 1144 | dependencies: 1145 | debug: 3.2.7 1146 | optionalDependencies: 1147 | eslint: 8.36.0 1148 | eslint-import-resolver-node: 0.3.7 1149 | transitivePeerDependencies: 1150 | - supports-color 1151 | 1152 | eslint-plugin-es@4.1.0(eslint@8.36.0): 1153 | dependencies: 1154 | eslint: 8.36.0 1155 | eslint-utils: 2.1.0 1156 | regexpp: 3.2.0 1157 | 1158 | eslint-plugin-import@2.27.5(eslint@8.36.0): 1159 | dependencies: 1160 | array-includes: 3.1.6 1161 | array.prototype.flat: 1.3.1 1162 | array.prototype.flatmap: 1.3.1 1163 | debug: 3.2.7 1164 | doctrine: 2.1.0 1165 | eslint: 8.36.0 1166 | eslint-import-resolver-node: 0.3.7 1167 | eslint-module-utils: 2.7.4(eslint-import-resolver-node@0.3.7)(eslint@8.36.0) 1168 | has: 1.0.3 1169 | is-core-module: 2.11.0 1170 | is-glob: 4.0.3 1171 | minimatch: 3.1.2 1172 | object.values: 1.1.6 1173 | resolve: 1.22.1 1174 | semver: 6.3.0 1175 | tsconfig-paths: 3.14.2 1176 | transitivePeerDependencies: 1177 | - eslint-import-resolver-typescript 1178 | - eslint-import-resolver-webpack 1179 | - supports-color 1180 | 1181 | eslint-plugin-n@15.6.1(eslint@8.36.0): 1182 | dependencies: 1183 | builtins: 5.0.1 1184 | eslint: 8.36.0 1185 | eslint-plugin-es: 4.1.0(eslint@8.36.0) 1186 | eslint-utils: 3.0.0(eslint@8.36.0) 1187 | ignore: 5.2.4 1188 | is-core-module: 2.11.0 1189 | minimatch: 3.1.2 1190 | resolve: 1.22.1 1191 | semver: 7.3.8 1192 | 1193 | eslint-plugin-prefer-let@3.0.1: 1194 | dependencies: 1195 | requireindex: 1.2.0 1196 | 1197 | eslint-plugin-promise@6.1.1(eslint@8.36.0): 1198 | dependencies: 1199 | eslint: 8.36.0 1200 | 1201 | eslint-scope@7.1.1: 1202 | dependencies: 1203 | esrecurse: 4.3.0 1204 | estraverse: 5.3.0 1205 | 1206 | eslint-utils@2.1.0: 1207 | dependencies: 1208 | eslint-visitor-keys: 1.3.0 1209 | 1210 | eslint-utils@3.0.0(eslint@8.36.0): 1211 | dependencies: 1212 | eslint: 8.36.0 1213 | eslint-visitor-keys: 2.1.0 1214 | 1215 | eslint-visitor-keys@1.3.0: {} 1216 | 1217 | eslint-visitor-keys@2.1.0: {} 1218 | 1219 | eslint-visitor-keys@3.3.0: {} 1220 | 1221 | eslint@8.36.0: 1222 | dependencies: 1223 | '@eslint-community/eslint-utils': 4.2.0(eslint@8.36.0) 1224 | '@eslint-community/regexpp': 4.4.0 1225 | '@eslint/eslintrc': 2.0.1 1226 | '@eslint/js': 8.36.0 1227 | '@humanwhocodes/config-array': 0.11.8 1228 | '@humanwhocodes/module-importer': 1.0.1 1229 | '@nodelib/fs.walk': 1.2.8 1230 | ajv: 6.12.6 1231 | chalk: 4.1.2 1232 | cross-spawn: 7.0.3 1233 | debug: 4.3.4 1234 | doctrine: 3.0.0 1235 | escape-string-regexp: 4.0.0 1236 | eslint-scope: 7.1.1 1237 | eslint-visitor-keys: 3.3.0 1238 | espree: 9.5.0 1239 | esquery: 1.5.0 1240 | esutils: 2.0.3 1241 | fast-deep-equal: 3.1.3 1242 | file-entry-cache: 6.0.1 1243 | find-up: 5.0.0 1244 | glob-parent: 6.0.2 1245 | globals: 13.20.0 1246 | grapheme-splitter: 1.0.4 1247 | ignore: 5.2.4 1248 | import-fresh: 3.3.0 1249 | imurmurhash: 0.1.4 1250 | is-glob: 4.0.3 1251 | is-path-inside: 3.0.3 1252 | js-sdsl: 4.3.0 1253 | js-yaml: 4.1.0 1254 | json-stable-stringify-without-jsonify: 1.0.1 1255 | levn: 0.4.1 1256 | lodash.merge: 4.6.2 1257 | minimatch: 3.1.2 1258 | natural-compare: 1.4.0 1259 | optionator: 0.9.1 1260 | strip-ansi: 6.0.1 1261 | strip-json-comments: 3.1.1 1262 | text-table: 0.2.0 1263 | transitivePeerDependencies: 1264 | - supports-color 1265 | 1266 | espree@9.5.0: 1267 | dependencies: 1268 | acorn: 8.8.2 1269 | acorn-jsx: 5.3.2(acorn@8.8.2) 1270 | eslint-visitor-keys: 3.3.0 1271 | 1272 | esquery@1.5.0: 1273 | dependencies: 1274 | estraverse: 5.3.0 1275 | 1276 | esrecurse@4.3.0: 1277 | dependencies: 1278 | estraverse: 5.3.0 1279 | 1280 | estraverse@5.3.0: {} 1281 | 1282 | esutils@2.0.3: {} 1283 | 1284 | fast-deep-equal@3.1.3: {} 1285 | 1286 | fast-glob@3.2.12: 1287 | dependencies: 1288 | '@nodelib/fs.stat': 2.0.5 1289 | '@nodelib/fs.walk': 1.2.8 1290 | glob-parent: 5.1.2 1291 | merge2: 1.4.1 1292 | micromatch: 4.0.5 1293 | 1294 | fast-json-stable-stringify@2.1.0: {} 1295 | 1296 | fast-levenshtein@2.0.6: {} 1297 | 1298 | fastq@1.15.0: 1299 | dependencies: 1300 | reusify: 1.0.4 1301 | 1302 | file-entry-cache@6.0.1: 1303 | dependencies: 1304 | flat-cache: 3.0.4 1305 | 1306 | fill-range@7.1.1: 1307 | dependencies: 1308 | to-regex-range: 5.0.1 1309 | 1310 | find-up@5.0.0: 1311 | dependencies: 1312 | locate-path: 6.0.0 1313 | path-exists: 4.0.0 1314 | 1315 | flat-cache@3.0.4: 1316 | dependencies: 1317 | flatted: 3.2.7 1318 | rimraf: 3.0.2 1319 | 1320 | flatted@3.2.7: {} 1321 | 1322 | folder-hash@4.0.4: 1323 | dependencies: 1324 | debug: 4.3.4 1325 | minimatch: 5.1.6 1326 | transitivePeerDependencies: 1327 | - supports-color 1328 | 1329 | for-each@0.3.3: 1330 | dependencies: 1331 | is-callable: 1.2.7 1332 | 1333 | fs.realpath@1.0.0: {} 1334 | 1335 | function-bind@1.1.1: {} 1336 | 1337 | function.prototype.name@1.1.5: 1338 | dependencies: 1339 | call-bind: 1.0.2 1340 | define-properties: 1.2.0 1341 | es-abstract: 1.21.2 1342 | functions-have-names: 1.2.3 1343 | 1344 | functions-have-names@1.2.3: {} 1345 | 1346 | get-intrinsic@1.2.0: 1347 | dependencies: 1348 | function-bind: 1.1.1 1349 | has: 1.0.3 1350 | has-symbols: 1.0.3 1351 | 1352 | get-symbol-description@1.0.0: 1353 | dependencies: 1354 | call-bind: 1.0.2 1355 | get-intrinsic: 1.2.0 1356 | 1357 | glob-parent@5.1.2: 1358 | dependencies: 1359 | is-glob: 4.0.3 1360 | 1361 | glob-parent@6.0.2: 1362 | dependencies: 1363 | is-glob: 4.0.3 1364 | 1365 | glob@7.2.3: 1366 | dependencies: 1367 | fs.realpath: 1.0.0 1368 | inflight: 1.0.6 1369 | inherits: 2.0.4 1370 | minimatch: 3.1.2 1371 | once: 1.4.0 1372 | path-is-absolute: 1.0.1 1373 | 1374 | globals@13.20.0: 1375 | dependencies: 1376 | type-fest: 0.20.2 1377 | 1378 | globalthis@1.0.3: 1379 | dependencies: 1380 | define-properties: 1.2.0 1381 | 1382 | gopd@1.0.1: 1383 | dependencies: 1384 | get-intrinsic: 1.2.0 1385 | 1386 | grapheme-splitter@1.0.4: {} 1387 | 1388 | has-bigints@1.0.2: {} 1389 | 1390 | has-flag@4.0.0: {} 1391 | 1392 | has-property-descriptors@1.0.0: 1393 | dependencies: 1394 | get-intrinsic: 1.2.0 1395 | 1396 | has-proto@1.0.1: {} 1397 | 1398 | has-symbols@1.0.3: {} 1399 | 1400 | has-tostringtag@1.0.0: 1401 | dependencies: 1402 | has-symbols: 1.0.3 1403 | 1404 | has@1.0.3: 1405 | dependencies: 1406 | function-bind: 1.1.1 1407 | 1408 | hasha@5.2.2: 1409 | dependencies: 1410 | is-stream: 2.0.1 1411 | type-fest: 0.8.1 1412 | 1413 | ignore@5.2.4: {} 1414 | 1415 | import-fresh@3.3.0: 1416 | dependencies: 1417 | parent-module: 1.0.1 1418 | resolve-from: 4.0.0 1419 | 1420 | imurmurhash@0.1.4: {} 1421 | 1422 | inflight@1.0.6: 1423 | dependencies: 1424 | once: 1.4.0 1425 | wrappy: 1.0.2 1426 | 1427 | inherits@2.0.4: {} 1428 | 1429 | internal-slot@1.0.5: 1430 | dependencies: 1431 | get-intrinsic: 1.2.0 1432 | has: 1.0.3 1433 | side-channel: 1.0.4 1434 | 1435 | is-array-buffer@3.0.2: 1436 | dependencies: 1437 | call-bind: 1.0.2 1438 | get-intrinsic: 1.2.0 1439 | is-typed-array: 1.1.10 1440 | 1441 | is-bigint@1.0.4: 1442 | dependencies: 1443 | has-bigints: 1.0.2 1444 | 1445 | is-boolean-object@1.1.2: 1446 | dependencies: 1447 | call-bind: 1.0.2 1448 | has-tostringtag: 1.0.0 1449 | 1450 | is-callable@1.2.7: {} 1451 | 1452 | is-core-module@2.11.0: 1453 | dependencies: 1454 | has: 1.0.3 1455 | 1456 | is-date-object@1.0.5: 1457 | dependencies: 1458 | has-tostringtag: 1.0.0 1459 | 1460 | is-docker@2.2.1: {} 1461 | 1462 | is-extglob@2.1.1: {} 1463 | 1464 | is-glob@4.0.3: 1465 | dependencies: 1466 | is-extglob: 2.1.1 1467 | 1468 | is-negative-zero@2.0.2: {} 1469 | 1470 | is-number-object@1.0.7: 1471 | dependencies: 1472 | has-tostringtag: 1.0.0 1473 | 1474 | is-number@7.0.0: {} 1475 | 1476 | is-path-inside@3.0.3: {} 1477 | 1478 | is-regex@1.1.4: 1479 | dependencies: 1480 | call-bind: 1.0.2 1481 | has-tostringtag: 1.0.0 1482 | 1483 | is-shared-array-buffer@1.0.2: 1484 | dependencies: 1485 | call-bind: 1.0.2 1486 | 1487 | is-stream@2.0.1: {} 1488 | 1489 | is-string@1.0.7: 1490 | dependencies: 1491 | has-tostringtag: 1.0.0 1492 | 1493 | is-symbol@1.0.4: 1494 | dependencies: 1495 | has-symbols: 1.0.3 1496 | 1497 | is-typed-array@1.1.10: 1498 | dependencies: 1499 | available-typed-arrays: 1.0.5 1500 | call-bind: 1.0.2 1501 | for-each: 0.3.3 1502 | gopd: 1.0.1 1503 | has-tostringtag: 1.0.0 1504 | 1505 | is-weakref@1.0.2: 1506 | dependencies: 1507 | call-bind: 1.0.2 1508 | 1509 | is-wsl@2.2.0: 1510 | dependencies: 1511 | is-docker: 2.2.1 1512 | 1513 | isexe@2.0.0: {} 1514 | 1515 | js-sdsl@4.3.0: {} 1516 | 1517 | js-yaml@4.1.0: 1518 | dependencies: 1519 | argparse: 2.0.1 1520 | 1521 | json-schema-traverse@0.4.1: {} 1522 | 1523 | json-stable-stringify-without-jsonify@1.0.1: {} 1524 | 1525 | json5@1.0.2: 1526 | dependencies: 1527 | minimist: 1.2.8 1528 | 1529 | levn@0.4.1: 1530 | dependencies: 1531 | prelude-ls: 1.2.1 1532 | type-check: 0.4.0 1533 | 1534 | lilconfig@2.1.0: {} 1535 | 1536 | locate-path@6.0.0: 1537 | dependencies: 1538 | p-locate: 5.0.0 1539 | 1540 | lodash.merge@4.6.2: {} 1541 | 1542 | lru-cache@6.0.0: 1543 | dependencies: 1544 | yallist: 4.0.0 1545 | 1546 | merge2@1.4.1: {} 1547 | 1548 | micromatch@4.0.5: 1549 | dependencies: 1550 | braces: 3.0.3 1551 | picomatch: 2.3.1 1552 | 1553 | minimatch@3.1.2: 1554 | dependencies: 1555 | brace-expansion: 1.1.11 1556 | 1557 | minimatch@5.1.6: 1558 | dependencies: 1559 | brace-expansion: 2.0.1 1560 | 1561 | minimist@1.2.8: {} 1562 | 1563 | ms@2.1.2: {} 1564 | 1565 | ms@2.1.3: {} 1566 | 1567 | natural-compare@1.4.0: {} 1568 | 1569 | object-inspect@1.12.3: {} 1570 | 1571 | object-keys@1.1.1: {} 1572 | 1573 | object.assign@4.1.4: 1574 | dependencies: 1575 | call-bind: 1.0.2 1576 | define-properties: 1.2.0 1577 | has-symbols: 1.0.3 1578 | object-keys: 1.1.1 1579 | 1580 | object.values@1.1.6: 1581 | dependencies: 1582 | call-bind: 1.0.2 1583 | define-properties: 1.2.0 1584 | es-abstract: 1.21.2 1585 | 1586 | once@1.4.0: 1587 | dependencies: 1588 | wrappy: 1.0.2 1589 | 1590 | open@8.4.2: 1591 | dependencies: 1592 | define-lazy-prop: 2.0.0 1593 | is-docker: 2.2.1 1594 | is-wsl: 2.2.0 1595 | 1596 | optionator@0.9.1: 1597 | dependencies: 1598 | deep-is: 0.1.4 1599 | fast-levenshtein: 2.0.6 1600 | levn: 0.4.1 1601 | prelude-ls: 1.2.1 1602 | type-check: 0.4.0 1603 | word-wrap: 1.2.4 1604 | 1605 | p-limit@3.1.0: 1606 | dependencies: 1607 | yocto-queue: 0.1.0 1608 | 1609 | p-locate@5.0.0: 1610 | dependencies: 1611 | p-limit: 3.1.0 1612 | 1613 | parent-module@1.0.1: 1614 | dependencies: 1615 | callsites: 3.1.0 1616 | 1617 | path-exists@4.0.0: {} 1618 | 1619 | path-is-absolute@1.0.1: {} 1620 | 1621 | path-key@3.1.1: {} 1622 | 1623 | path-parse@1.0.7: {} 1624 | 1625 | picocolors@1.0.0: {} 1626 | 1627 | picomatch@2.3.1: {} 1628 | 1629 | prelude-ls@1.2.1: {} 1630 | 1631 | punycode@2.3.0: {} 1632 | 1633 | queue-microtask@1.2.3: {} 1634 | 1635 | regexp.prototype.flags@1.4.3: 1636 | dependencies: 1637 | call-bind: 1.0.2 1638 | define-properties: 1.2.0 1639 | functions-have-names: 1.2.3 1640 | 1641 | regexpp@3.2.0: {} 1642 | 1643 | requireindex@1.2.0: {} 1644 | 1645 | resolve-from@4.0.0: {} 1646 | 1647 | resolve@1.22.1: 1648 | dependencies: 1649 | is-core-module: 2.11.0 1650 | path-parse: 1.0.7 1651 | supports-preserve-symlinks-flag: 1.0.0 1652 | 1653 | reusify@1.0.4: {} 1654 | 1655 | rimraf@3.0.2: 1656 | dependencies: 1657 | glob: 7.2.3 1658 | 1659 | run-parallel@1.2.0: 1660 | dependencies: 1661 | queue-microtask: 1.2.3 1662 | 1663 | safe-regex-test@1.0.0: 1664 | dependencies: 1665 | call-bind: 1.0.2 1666 | get-intrinsic: 1.2.0 1667 | is-regex: 1.1.4 1668 | 1669 | semver@6.3.0: {} 1670 | 1671 | semver@7.3.8: 1672 | dependencies: 1673 | lru-cache: 6.0.0 1674 | 1675 | shebang-command@2.0.0: 1676 | dependencies: 1677 | shebang-regex: 3.0.0 1678 | 1679 | shebang-regex@3.0.0: {} 1680 | 1681 | side-channel@1.0.4: 1682 | dependencies: 1683 | call-bind: 1.0.2 1684 | get-intrinsic: 1.2.0 1685 | object-inspect: 1.12.3 1686 | 1687 | string.prototype.trim@1.2.7: 1688 | dependencies: 1689 | call-bind: 1.0.2 1690 | define-properties: 1.2.0 1691 | es-abstract: 1.21.2 1692 | 1693 | string.prototype.trimend@1.0.6: 1694 | dependencies: 1695 | call-bind: 1.0.2 1696 | define-properties: 1.2.0 1697 | es-abstract: 1.21.2 1698 | 1699 | string.prototype.trimstart@1.0.6: 1700 | dependencies: 1701 | call-bind: 1.0.2 1702 | define-properties: 1.2.0 1703 | es-abstract: 1.21.2 1704 | 1705 | strip-ansi@6.0.1: 1706 | dependencies: 1707 | ansi-regex: 5.0.1 1708 | 1709 | strip-bom@3.0.0: {} 1710 | 1711 | strip-json-comments@3.1.1: {} 1712 | 1713 | supports-color@7.2.0: 1714 | dependencies: 1715 | has-flag: 4.0.0 1716 | 1717 | supports-preserve-symlinks-flag@1.0.0: {} 1718 | 1719 | text-table@0.2.0: {} 1720 | 1721 | to-regex-range@5.0.1: 1722 | dependencies: 1723 | is-number: 7.0.0 1724 | 1725 | tsconfig-paths@3.14.2: 1726 | dependencies: 1727 | '@types/json5': 0.0.29 1728 | json5: 1.0.2 1729 | minimist: 1.2.8 1730 | strip-bom: 3.0.0 1731 | 1732 | type-check@0.4.0: 1733 | dependencies: 1734 | prelude-ls: 1.2.1 1735 | 1736 | type-fest@0.20.2: {} 1737 | 1738 | type-fest@0.8.1: {} 1739 | 1740 | typed-array-length@1.0.4: 1741 | dependencies: 1742 | call-bind: 1.0.2 1743 | for-each: 0.3.3 1744 | is-typed-array: 1.1.10 1745 | 1746 | unbox-primitive@1.0.2: 1747 | dependencies: 1748 | call-bind: 1.0.2 1749 | has-bigints: 1.0.2 1750 | has-symbols: 1.0.3 1751 | which-boxed-primitive: 1.0.2 1752 | 1753 | uri-js@4.4.1: 1754 | dependencies: 1755 | punycode: 2.3.0 1756 | 1757 | which-boxed-primitive@1.0.2: 1758 | dependencies: 1759 | is-bigint: 1.0.4 1760 | is-boolean-object: 1.1.2 1761 | is-number-object: 1.0.7 1762 | is-string: 1.0.7 1763 | is-symbol: 1.0.4 1764 | 1765 | which-typed-array@1.1.9: 1766 | dependencies: 1767 | available-typed-arrays: 1.0.5 1768 | call-bind: 1.0.2 1769 | for-each: 0.3.3 1770 | gopd: 1.0.1 1771 | has-tostringtag: 1.0.0 1772 | is-typed-array: 1.1.10 1773 | 1774 | which@2.0.2: 1775 | dependencies: 1776 | isexe: 2.0.0 1777 | 1778 | word-wrap@1.2.4: {} 1779 | 1780 | wrappy@1.0.2: {} 1781 | 1782 | yallist@4.0.0: {} 1783 | 1784 | yocto-queue@0.1.0: {} 1785 | -------------------------------------------------------------------------------- /purge.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import callCloudflare from './lib/call-cloudflare.js' 4 | 5 | callCloudflare('purge_cache', { purge_everything: true }).catch(e => { 6 | process.stderr.write(e.stack + '\n') 7 | process.exit(1) 8 | }) 9 | --------------------------------------------------------------------------------