├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── app.json ├── example.env ├── index.js ├── package-lock.json ├── package.json └── render.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 2 | # Contributor Covenant Code of Conduct 3 | 4 | ## Our Pledge 5 | 6 | We as members, contributors, and leaders pledge to make participation in our 7 | community a harassment-free experience for everyone, regardless of age, body 8 | size, visible or invisible disability, ethnicity, sex characteristics, gender 9 | identity and expression, level of experience, education, socio-economic status, 10 | nationality, personal appearance, race, caste, color, religion, or sexual identity 11 | and orientation. 12 | 13 | We pledge to act and interact in ways that contribute to an open, welcoming, 14 | diverse, inclusive, and healthy community. 15 | 16 | ## Our Standards 17 | 18 | Examples of behavior that contributes to a positive environment for our 19 | community include: 20 | 21 | * Demonstrating empathy and kindness toward other people 22 | * Being respectful of differing opinions, viewpoints, and experiences 23 | * Giving and gracefully accepting constructive feedback 24 | * Accepting responsibility and apologizing to those affected by our mistakes, 25 | and learning from the experience 26 | * Focusing on what is best not just for us as individuals, but for the 27 | overall community 28 | 29 | Examples of unacceptable behavior include: 30 | 31 | * The use of sexualized language or imagery, and sexual attention or 32 | advances of any kind 33 | * Trolling, insulting or derogatory comments, and personal or political attacks 34 | * Public or private harassment 35 | * Publishing others' private information, such as a physical or email 36 | address, without their explicit permission 37 | * Other conduct which could reasonably be considered inappropriate in a 38 | professional setting 39 | 40 | ## Enforcement Responsibilities 41 | 42 | Community leaders are responsible for clarifying and enforcing our standards of 43 | acceptable behavior and will take appropriate and fair corrective action in 44 | response to any behavior that they deem inappropriate, threatening, offensive, 45 | or harmful. 46 | 47 | Community leaders have the right and responsibility to remove, edit, or reject 48 | comments, commits, code, wiki edits, issues, and other contributions that are 49 | not aligned to this Code of Conduct, and will communicate reasons for moderation 50 | decisions when appropriate. 51 | 52 | ## Scope 53 | 54 | This Code of Conduct applies within all community spaces, and also applies when 55 | an individual is officially representing the community in public spaces. 56 | Examples of representing our community include using an official e-mail address, 57 | posting via an official social media account, or acting as an appointed 58 | representative at an online or offline event. 59 | 60 | ## Enforcement 61 | 62 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 63 | reported to the community leaders responsible for enforcement at 64 | [INSERT CONTACT METHOD]. 65 | All complaints will be reviewed and investigated promptly and fairly. 66 | 67 | All community leaders are obligated to respect the privacy and security of the 68 | reporter of any incident. 69 | 70 | ## Enforcement Guidelines 71 | 72 | Community leaders will follow these Community Impact Guidelines in determining 73 | the consequences for any action they deem in violation of this Code of Conduct: 74 | 75 | ### 1. Correction 76 | 77 | **Community Impact**: Use of inappropriate language or other behavior deemed 78 | unprofessional or unwelcome in the community. 79 | 80 | **Consequence**: A private, written warning from community leaders, providing 81 | clarity around the nature of the violation and an explanation of why the 82 | behavior was inappropriate. A public apology may be requested. 83 | 84 | ### 2. Warning 85 | 86 | **Community Impact**: A violation through a single incident or series 87 | of actions. 88 | 89 | **Consequence**: A warning with consequences for continued behavior. No 90 | interaction with the people involved, including unsolicited interaction with 91 | those enforcing the Code of Conduct, for a specified period of time. This 92 | includes avoiding interactions in community spaces as well as external channels 93 | like social media. Violating these terms may lead to a temporary or 94 | permanent ban. 95 | 96 | ### 3. Temporary Ban 97 | 98 | **Community Impact**: A serious violation of community standards, including 99 | sustained inappropriate behavior. 100 | 101 | **Consequence**: A temporary ban from any sort of interaction or public 102 | communication with the community for a specified period of time. No public or 103 | private interaction with the people involved, including unsolicited interaction 104 | with those enforcing the Code of Conduct, is allowed during this period. 105 | Violating these terms may lead to a permanent ban. 106 | 107 | ### 4. Permanent Ban 108 | 109 | **Community Impact**: Demonstrating a pattern of violation of community 110 | standards, including sustained inappropriate behavior, harassment of an 111 | individual, or aggression toward or disparagement of classes of individuals. 112 | 113 | **Consequence**: A permanent ban from any sort of public interaction within 114 | the community. 115 | 116 | ## Attribution 117 | 118 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 119 | version 2.0, available at 120 | [https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0]. 121 | 122 | Community Impact Guidelines were inspired by 123 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. 124 | 125 | For answers to common questions about this code of conduct, see the FAQ at 126 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available 127 | at [https://www.contributor-covenant.org/translations][translations]. 128 | 129 | [homepage]: https://www.contributor-covenant.org 130 | [v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html 131 | [Mozilla CoC]: https://github.com/mozilla/diversity 132 | [FAQ]: https://www.contributor-covenant.org/faq 133 | [translations]: https://www.contributor-covenant.org/translations 134 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Use of this sample app is subject to our [Terms of Use](https://explore.zoom.us/en/legal/zoom-api-license-and-tou/) 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Zoom Webhook sample 2 | 3 | Use of this sample app is subject to our [Terms of Use](https://explore.zoom.us/en/legal/zoom-api-license-and-tou/). 4 | 5 | --- 6 | 7 | **NOTE:** This Sample App has been updated to use the [Webhook Secret Token](https://developers.zoom.us/docs/api/rest/webhook-reference/#verify-webhook-events) instead of the [Webhook Verification Token](https://developers.zoom.us/docs/api/rest/webhook-reference/#verify-webhook-events) to validate requests are sent from Zoom. 8 | 9 | --- 10 | 11 | This is a Node.js / Express server that receives [Zoom Platform Webhooks](https://developers.zoom.us/docs/api/rest/webhook-reference/#enable-webhooks) and [Zoom Video SDK Webhooks](https://developers.zoom.us/docs/api/rest/webhook-reference/#enable-webhooks). 12 | 13 | If you would like to skip these steps and just deploy the finished code to a managed service, click the Deploy to Railway/Render/Heroku button. (You will still need to configure a few simple things, so skip to [Deployment](#deployment).) 14 | 15 | | Railway | Render | Heroku | 16 | |:-:|:-:|:-:| 17 | | [![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/template/ERSEbO?referralCode=HTPdHX) | [![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/zoom/webhook-sample) | [![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/zoom/webhook-sample) | 18 | 19 | 20 | ## Installation 21 | 22 | In terminal, run the following command to clone the repo: 23 | 24 | `$ git clone https://github.com/zoom/webhook-sample.git` 25 | 26 | ## Setup 27 | 28 | 1. In terminal, cd into the cloned repo: 29 | 30 | `$ cd webhook-sample` 31 | 32 | 1. Then install the dependencies: 33 | 34 | `$ npm install` 35 | 36 | 1. Create an environment file to store your Webhook Secret Token: 37 | 38 | `$ touch .env` 39 | 40 | 1. Add the following code to the .env file, and insert your [Zoom Webhook Secret Token](https://developers.zoom.us/docs/api/rest/webhook-reference/#verify-webhook-events): 41 | 42 | ``` 43 | ZOOM_WEBHOOK_SECRET_TOKEN=ZOOM_WEBHOOK_SECRET_TOKEN_HERE 44 | ``` 45 | 46 | ![Zoom Webhook Secret Token](https://developers.zoom.us/img/nextImageExportOptimizer/webhook-secret-token-opt-640.WEBP "Zoom Webhook Secret Token") 47 | 48 | > The Webhook Secret Token allows you to [verify webhook requests come from Zoom](https://developers.zoom.us/docs/api/rest/webhook-reference/#verify-webhook-events) and for Zoom to [validate that you control your webhook endpoint](https://developers.zoom.us/docs/api/rest/webhook-reference/#validate-your-webhook-endpoint). 49 | 50 | 1. Save and close .env. 51 | 52 | 1. Start the server: 53 | 54 | `$ npm run start` 55 | 56 | 1. We need to expose the local server to the internet to accept post requests, we will use [Ngrok](https://ngrok.com) (free) for this. 57 | 58 | Once installed, open a new terminal tab and run: 59 | 60 | `$ ngrok http 4000` 61 | 62 | > NOTE: [I've put ngrok in my PATH so I can call it globally.](https://stackoverflow.com/a/36759493/6592510) 63 | 64 | 1. Copy the ngrok https url and paste it in the Bot endpoint URL input on your Zoom App's Features section. Remember to include `/webhook` path. 65 | 66 | Example: `https://abc123.ngrok.io/webhook` 67 | 68 | 1. Click "Validate". 69 | 70 | ![Zoom Webhook Configuration](https://developers.zoom.us/img/nextImageExportOptimizer/webhook-validate-opt-640.WEBP "Zoom Webhook Configuration") 71 | 72 | 1. Choose the events you'd like to subscribe to. 73 | 74 | 1. Click "Save". 75 | 76 | ![Zoom Webhooks Configured](https://developers.zoom.us/img/nextImageExportOptimizer/webhook-validate-success-opt-640.WEBP "Zoom Webhooks Configured") 77 | 78 | ## Usage 79 | 80 | 1. Trigger the respective Webhook. 81 | 82 | For example, if you chose the [Start Meeting Webhook](https://developers.zoom.us/docs/api/rest/reference/zoom-api/events/#operation/meeting.started), start a Zoom Meeting. You will see the Webhook headers and payload logged in terminal. 83 | 84 | ```json 85 | { 86 | "host": "abc123.ngrok.io", 87 | "user-agent": "Zoom Marketplace/1.0a", 88 | "content-length": "335", 89 | "authorization": "{LEGACY_WEBHOOK_VERIFICATION_TOKEN}", 90 | "clientid": "{CLIENT_ID}", 91 | "content-type": "application/json; charset=utf-8", 92 | "x-forwarded-for": "{X_FORWARDED_FOR}", 93 | "x-forwarded-proto": "https", 94 | "x-zm-request-timestamp": "X_ZM_REQUEST_TIMESTAMP", 95 | "x-zm-signature": "v0={HASHED_WEBHOOK_SECRET_TOKEN}", 96 | "x-zm-trackingid": "{X_ZM_TRACKINGID}", 97 | "accept-encoding": "gzip" 98 | } 99 | ``` 100 | 101 | ```json 102 | { 103 | "event": "meeting.started", 104 | "payload": { 105 | "account_id": "{ACCOUNT_ID}", 106 | "object": { 107 | "duration": 0, 108 | "start_time": "2021-11-02T20:43:19Z", 109 | "timezone": "America/Denver", 110 | "topic": "{TOPIC}", 111 | "id": "{MEETING_ID}", 112 | "type": 4, 113 | "uuid": "{MEETING_UUID}", 114 | "host_id": "{HOST_ID}" 115 | } 116 | }, 117 | "event_ts": 1635885799302 118 | } 119 | ``` 120 | 121 | ## Deployment 122 | 123 | ### Deploy to a Managed Service 124 | 125 | 1. After clicking the "Deploy to " button, enter a name for your app (or leave it blank to have a name generated for you), and insert your [Zoom Webhook Secret Token](https://developers.zoom.us/docs/api/rest/webhook-reference/#verify-webhook-events): 126 | 127 | - `ZOOM_WEBHOOK_SECRET_TOKEN` (Your Zoom Webhook Secret Token, found on your App's Features page) 128 | 129 | 1. Then click "Deploy App". 130 | 131 | 1. Copy the url and paste it in the Event notification endpoint URL input on your Zoom App's Features section. Remember to include `/webhook` path. 132 | 133 | Example: `https://abc123.provider.com/webhook` 134 | 135 | 142 | 143 | ### Other Server Hosting 144 | 145 | 1. For Other Server Hosting information, see [this tutorial](https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/deployment#choosing_a_hosting_provider). 146 | 147 | 1. Copy the deployed url and paste it in the Event notification endpoint URL input on your Zoom App's Features section. Remember to include `/webhook` path. 148 | 149 | Example: `https://abc123.compute-1.amazonaws.com/webhook` 150 | 151 | Now you are ready to [receive Zoom webhooks](#usage). 152 | 153 | ## Need help? 154 | 155 | If you're looking for help, try [Developer Support](https://devsupport.zoom.us) or our [Developer Forum](https://devforum.zoom.us). Priority support is also available with [Premier Developer Support](https://explore.zoom.us/docs/en-us/developer-support-plans.html) plans. 156 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Zoom Webhook sample", 3 | "description": "Receive Zoom webhooks.", 4 | "repository": "https://github.com/zoom/webhook-sample-node.js", 5 | "logo": "https://avatars1.githubusercontent.com/u/29114944?s=200&v=4", 6 | "keywords": ["zoom", "webhook", "node.js", "express"], 7 | "env": { 8 | "ZOOM_WEBHOOK_SECRET_TOKEN": { 9 | "description": "Your Zoom Webhook Secret Token, found on your App's Features page", 10 | "value": "", 11 | "required": true 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /example.env: -------------------------------------------------------------------------------- 1 | ZOOM_WEBHOOK_SECRET_TOKEN="" -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config() 2 | const express = require('express') 3 | const bodyParser = require('body-parser') 4 | const crypto = require('crypto') 5 | 6 | const app = express() 7 | const port = process.env.PORT || 4000 8 | 9 | app.use(bodyParser.json()) 10 | 11 | app.get('/', (req, res) => { 12 | res.status(200) 13 | res.send(`Zoom Webhook sample successfully running. Set this URL with the /webhook path as your apps Event notification endpoint URL. https://github.com/zoom/webhook-sample`) 14 | }) 15 | 16 | app.post('/webhook', (req, res) => { 17 | 18 | var response 19 | 20 | console.log(req.headers) 21 | console.log(req.body) 22 | 23 | // construct the message string 24 | const message = `v0:${req.headers['x-zm-request-timestamp']}:${JSON.stringify(req.body)}` 25 | 26 | const hashForVerify = crypto.createHmac('sha256', process.env.ZOOM_WEBHOOK_SECRET_TOKEN).update(message).digest('hex') 27 | 28 | // hash the message string with your Webhook Secret Token and prepend the version semantic 29 | const signature = `v0=${hashForVerify}` 30 | 31 | // you validating the request came from Zoom https://marketplace.zoom.us/docs/api-reference/webhook-reference#notification-structure 32 | if (req.headers['x-zm-signature'] === signature) { 33 | 34 | // Zoom validating you control the webhook endpoint https://marketplace.zoom.us/docs/api-reference/webhook-reference#validate-webhook-endpoint 35 | if(req.body.event === 'endpoint.url_validation') { 36 | const hashForValidate = crypto.createHmac('sha256', process.env.ZOOM_WEBHOOK_SECRET_TOKEN).update(req.body.payload.plainToken).digest('hex') 37 | 38 | response = { 39 | message: { 40 | plainToken: req.body.payload.plainToken, 41 | encryptedToken: hashForValidate 42 | }, 43 | status: 200 44 | } 45 | 46 | console.log(response.message) 47 | 48 | res.status(response.status) 49 | res.json(response.message) 50 | } else { 51 | response = { message: 'Authorized request to Zoom Webhook sample.', status: 200 } 52 | 53 | console.log(response.message) 54 | 55 | res.status(response.status) 56 | res.json(response) 57 | 58 | // business logic here, example make API request to Zoom or 3rd party 59 | 60 | } 61 | } else { 62 | 63 | response = { message: 'Unauthorized request to Zoom Webhook sample.', status: 401 } 64 | 65 | console.log(response.message) 66 | 67 | res.status(response.status) 68 | res.json(response) 69 | } 70 | }) 71 | 72 | app.listen(port, () => console.log(`Zoom Webhook sample listening on port ${port}!`)) 73 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webhook-sample", 3 | "version": "2.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "webhook-sample", 9 | "version": "2.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "body-parser": "^1.19.0", 13 | "dotenv": "^10.0.0", 14 | "express": "^4.17.1" 15 | } 16 | }, 17 | "node_modules/accepts": { 18 | "version": "1.3.8", 19 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 20 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 21 | "dependencies": { 22 | "mime-types": "~2.1.34", 23 | "negotiator": "0.6.3" 24 | }, 25 | "engines": { 26 | "node": ">= 0.6" 27 | } 28 | }, 29 | "node_modules/array-flatten": { 30 | "version": "1.1.1", 31 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 32 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 33 | }, 34 | "node_modules/body-parser": { 35 | "version": "1.20.3", 36 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", 37 | "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", 38 | "license": "MIT", 39 | "dependencies": { 40 | "bytes": "3.1.2", 41 | "content-type": "~1.0.5", 42 | "debug": "2.6.9", 43 | "depd": "2.0.0", 44 | "destroy": "1.2.0", 45 | "http-errors": "2.0.0", 46 | "iconv-lite": "0.4.24", 47 | "on-finished": "2.4.1", 48 | "qs": "6.13.0", 49 | "raw-body": "2.5.2", 50 | "type-is": "~1.6.18", 51 | "unpipe": "1.0.0" 52 | }, 53 | "engines": { 54 | "node": ">= 0.8", 55 | "npm": "1.2.8000 || >= 1.4.16" 56 | } 57 | }, 58 | "node_modules/bytes": { 59 | "version": "3.1.2", 60 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 61 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 62 | "license": "MIT", 63 | "engines": { 64 | "node": ">= 0.8" 65 | } 66 | }, 67 | "node_modules/call-bind": { 68 | "version": "1.0.7", 69 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", 70 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", 71 | "license": "MIT", 72 | "dependencies": { 73 | "es-define-property": "^1.0.0", 74 | "es-errors": "^1.3.0", 75 | "function-bind": "^1.1.2", 76 | "get-intrinsic": "^1.2.4", 77 | "set-function-length": "^1.2.1" 78 | }, 79 | "engines": { 80 | "node": ">= 0.4" 81 | }, 82 | "funding": { 83 | "url": "https://github.com/sponsors/ljharb" 84 | } 85 | }, 86 | "node_modules/content-disposition": { 87 | "version": "0.5.4", 88 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 89 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 90 | "dependencies": { 91 | "safe-buffer": "5.2.1" 92 | }, 93 | "engines": { 94 | "node": ">= 0.6" 95 | } 96 | }, 97 | "node_modules/content-type": { 98 | "version": "1.0.5", 99 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 100 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 101 | "license": "MIT", 102 | "engines": { 103 | "node": ">= 0.6" 104 | } 105 | }, 106 | "node_modules/cookie": { 107 | "version": "0.7.1", 108 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", 109 | "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", 110 | "license": "MIT", 111 | "engines": { 112 | "node": ">= 0.6" 113 | } 114 | }, 115 | "node_modules/cookie-signature": { 116 | "version": "1.0.6", 117 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 118 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 119 | }, 120 | "node_modules/debug": { 121 | "version": "2.6.9", 122 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 123 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 124 | "dependencies": { 125 | "ms": "2.0.0" 126 | } 127 | }, 128 | "node_modules/define-data-property": { 129 | "version": "1.1.4", 130 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", 131 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", 132 | "license": "MIT", 133 | "dependencies": { 134 | "es-define-property": "^1.0.0", 135 | "es-errors": "^1.3.0", 136 | "gopd": "^1.0.1" 137 | }, 138 | "engines": { 139 | "node": ">= 0.4" 140 | }, 141 | "funding": { 142 | "url": "https://github.com/sponsors/ljharb" 143 | } 144 | }, 145 | "node_modules/depd": { 146 | "version": "2.0.0", 147 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 148 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 149 | "engines": { 150 | "node": ">= 0.8" 151 | } 152 | }, 153 | "node_modules/destroy": { 154 | "version": "1.2.0", 155 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 156 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 157 | "engines": { 158 | "node": ">= 0.8", 159 | "npm": "1.2.8000 || >= 1.4.16" 160 | } 161 | }, 162 | "node_modules/dotenv": { 163 | "version": "10.0.0", 164 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", 165 | "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", 166 | "engines": { 167 | "node": ">=10" 168 | } 169 | }, 170 | "node_modules/ee-first": { 171 | "version": "1.1.1", 172 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 173 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 174 | }, 175 | "node_modules/encodeurl": { 176 | "version": "2.0.0", 177 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 178 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 179 | "license": "MIT", 180 | "engines": { 181 | "node": ">= 0.8" 182 | } 183 | }, 184 | "node_modules/es-define-property": { 185 | "version": "1.0.0", 186 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", 187 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", 188 | "license": "MIT", 189 | "dependencies": { 190 | "get-intrinsic": "^1.2.4" 191 | }, 192 | "engines": { 193 | "node": ">= 0.4" 194 | } 195 | }, 196 | "node_modules/es-errors": { 197 | "version": "1.3.0", 198 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 199 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 200 | "license": "MIT", 201 | "engines": { 202 | "node": ">= 0.4" 203 | } 204 | }, 205 | "node_modules/escape-html": { 206 | "version": "1.0.3", 207 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 208 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", 209 | "license": "MIT" 210 | }, 211 | "node_modules/etag": { 212 | "version": "1.8.1", 213 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 214 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 215 | "license": "MIT", 216 | "engines": { 217 | "node": ">= 0.6" 218 | } 219 | }, 220 | "node_modules/express": { 221 | "version": "4.21.2", 222 | "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", 223 | "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", 224 | "license": "MIT", 225 | "dependencies": { 226 | "accepts": "~1.3.8", 227 | "array-flatten": "1.1.1", 228 | "body-parser": "1.20.3", 229 | "content-disposition": "0.5.4", 230 | "content-type": "~1.0.4", 231 | "cookie": "0.7.1", 232 | "cookie-signature": "1.0.6", 233 | "debug": "2.6.9", 234 | "depd": "2.0.0", 235 | "encodeurl": "~2.0.0", 236 | "escape-html": "~1.0.3", 237 | "etag": "~1.8.1", 238 | "finalhandler": "1.3.1", 239 | "fresh": "0.5.2", 240 | "http-errors": "2.0.0", 241 | "merge-descriptors": "1.0.3", 242 | "methods": "~1.1.2", 243 | "on-finished": "2.4.1", 244 | "parseurl": "~1.3.3", 245 | "path-to-regexp": "0.1.12", 246 | "proxy-addr": "~2.0.7", 247 | "qs": "6.13.0", 248 | "range-parser": "~1.2.1", 249 | "safe-buffer": "5.2.1", 250 | "send": "0.19.0", 251 | "serve-static": "1.16.2", 252 | "setprototypeof": "1.2.0", 253 | "statuses": "2.0.1", 254 | "type-is": "~1.6.18", 255 | "utils-merge": "1.0.1", 256 | "vary": "~1.1.2" 257 | }, 258 | "engines": { 259 | "node": ">= 0.10.0" 260 | }, 261 | "funding": { 262 | "type": "opencollective", 263 | "url": "https://opencollective.com/express" 264 | } 265 | }, 266 | "node_modules/finalhandler": { 267 | "version": "1.3.1", 268 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", 269 | "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", 270 | "license": "MIT", 271 | "dependencies": { 272 | "debug": "2.6.9", 273 | "encodeurl": "~2.0.0", 274 | "escape-html": "~1.0.3", 275 | "on-finished": "2.4.1", 276 | "parseurl": "~1.3.3", 277 | "statuses": "2.0.1", 278 | "unpipe": "~1.0.0" 279 | }, 280 | "engines": { 281 | "node": ">= 0.8" 282 | } 283 | }, 284 | "node_modules/forwarded": { 285 | "version": "0.2.0", 286 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 287 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 288 | "engines": { 289 | "node": ">= 0.6" 290 | } 291 | }, 292 | "node_modules/fresh": { 293 | "version": "0.5.2", 294 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 295 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 296 | "license": "MIT", 297 | "engines": { 298 | "node": ">= 0.6" 299 | } 300 | }, 301 | "node_modules/function-bind": { 302 | "version": "1.1.2", 303 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 304 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 305 | "license": "MIT", 306 | "funding": { 307 | "url": "https://github.com/sponsors/ljharb" 308 | } 309 | }, 310 | "node_modules/get-intrinsic": { 311 | "version": "1.2.4", 312 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", 313 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", 314 | "license": "MIT", 315 | "dependencies": { 316 | "es-errors": "^1.3.0", 317 | "function-bind": "^1.1.2", 318 | "has-proto": "^1.0.1", 319 | "has-symbols": "^1.0.3", 320 | "hasown": "^2.0.0" 321 | }, 322 | "engines": { 323 | "node": ">= 0.4" 324 | }, 325 | "funding": { 326 | "url": "https://github.com/sponsors/ljharb" 327 | } 328 | }, 329 | "node_modules/gopd": { 330 | "version": "1.1.0", 331 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.1.0.tgz", 332 | "integrity": "sha512-FQoVQnqcdk4hVM4JN1eromaun4iuS34oStkdlLENLdpULsuQcTyXj8w7ayhuUfPwEYZ1ZOooOTT6fdA9Vmx/RA==", 333 | "license": "MIT", 334 | "dependencies": { 335 | "get-intrinsic": "^1.2.4" 336 | }, 337 | "engines": { 338 | "node": ">= 0.4" 339 | }, 340 | "funding": { 341 | "url": "https://github.com/sponsors/ljharb" 342 | } 343 | }, 344 | "node_modules/has-property-descriptors": { 345 | "version": "1.0.2", 346 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", 347 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", 348 | "license": "MIT", 349 | "dependencies": { 350 | "es-define-property": "^1.0.0" 351 | }, 352 | "funding": { 353 | "url": "https://github.com/sponsors/ljharb" 354 | } 355 | }, 356 | "node_modules/has-proto": { 357 | "version": "1.1.0", 358 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.1.0.tgz", 359 | "integrity": "sha512-QLdzI9IIO1Jg7f9GT1gXpPpXArAn6cS31R1eEZqz08Gc+uQ8/XiqHWt17Fiw+2p6oTTIq5GXEpQkAlA88YRl/Q==", 360 | "license": "MIT", 361 | "dependencies": { 362 | "call-bind": "^1.0.7" 363 | }, 364 | "engines": { 365 | "node": ">= 0.4" 366 | }, 367 | "funding": { 368 | "url": "https://github.com/sponsors/ljharb" 369 | } 370 | }, 371 | "node_modules/has-symbols": { 372 | "version": "1.1.0", 373 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 374 | "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", 375 | "license": "MIT", 376 | "engines": { 377 | "node": ">= 0.4" 378 | }, 379 | "funding": { 380 | "url": "https://github.com/sponsors/ljharb" 381 | } 382 | }, 383 | "node_modules/hasown": { 384 | "version": "2.0.2", 385 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 386 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 387 | "license": "MIT", 388 | "dependencies": { 389 | "function-bind": "^1.1.2" 390 | }, 391 | "engines": { 392 | "node": ">= 0.4" 393 | } 394 | }, 395 | "node_modules/http-errors": { 396 | "version": "2.0.0", 397 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 398 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 399 | "dependencies": { 400 | "depd": "2.0.0", 401 | "inherits": "2.0.4", 402 | "setprototypeof": "1.2.0", 403 | "statuses": "2.0.1", 404 | "toidentifier": "1.0.1" 405 | }, 406 | "engines": { 407 | "node": ">= 0.8" 408 | } 409 | }, 410 | "node_modules/iconv-lite": { 411 | "version": "0.4.24", 412 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 413 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 414 | "license": "MIT", 415 | "dependencies": { 416 | "safer-buffer": ">= 2.1.2 < 3" 417 | }, 418 | "engines": { 419 | "node": ">=0.10.0" 420 | } 421 | }, 422 | "node_modules/inherits": { 423 | "version": "2.0.4", 424 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 425 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 426 | }, 427 | "node_modules/ipaddr.js": { 428 | "version": "1.9.1", 429 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 430 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 431 | "engines": { 432 | "node": ">= 0.10" 433 | } 434 | }, 435 | "node_modules/media-typer": { 436 | "version": "0.3.0", 437 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 438 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", 439 | "engines": { 440 | "node": ">= 0.6" 441 | } 442 | }, 443 | "node_modules/merge-descriptors": { 444 | "version": "1.0.3", 445 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", 446 | "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", 447 | "license": "MIT", 448 | "funding": { 449 | "url": "https://github.com/sponsors/sindresorhus" 450 | } 451 | }, 452 | "node_modules/methods": { 453 | "version": "1.1.2", 454 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 455 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", 456 | "engines": { 457 | "node": ">= 0.6" 458 | } 459 | }, 460 | "node_modules/mime": { 461 | "version": "1.6.0", 462 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 463 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 464 | "license": "MIT", 465 | "bin": { 466 | "mime": "cli.js" 467 | }, 468 | "engines": { 469 | "node": ">=4" 470 | } 471 | }, 472 | "node_modules/mime-db": { 473 | "version": "1.52.0", 474 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 475 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 476 | "engines": { 477 | "node": ">= 0.6" 478 | } 479 | }, 480 | "node_modules/mime-types": { 481 | "version": "2.1.35", 482 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 483 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 484 | "dependencies": { 485 | "mime-db": "1.52.0" 486 | }, 487 | "engines": { 488 | "node": ">= 0.6" 489 | } 490 | }, 491 | "node_modules/ms": { 492 | "version": "2.0.0", 493 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 494 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 495 | }, 496 | "node_modules/negotiator": { 497 | "version": "0.6.3", 498 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 499 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 500 | "engines": { 501 | "node": ">= 0.6" 502 | } 503 | }, 504 | "node_modules/object-inspect": { 505 | "version": "1.13.3", 506 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", 507 | "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", 508 | "license": "MIT", 509 | "engines": { 510 | "node": ">= 0.4" 511 | }, 512 | "funding": { 513 | "url": "https://github.com/sponsors/ljharb" 514 | } 515 | }, 516 | "node_modules/on-finished": { 517 | "version": "2.4.1", 518 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 519 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 520 | "dependencies": { 521 | "ee-first": "1.1.1" 522 | }, 523 | "engines": { 524 | "node": ">= 0.8" 525 | } 526 | }, 527 | "node_modules/parseurl": { 528 | "version": "1.3.3", 529 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 530 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 531 | "license": "MIT", 532 | "engines": { 533 | "node": ">= 0.8" 534 | } 535 | }, 536 | "node_modules/path-to-regexp": { 537 | "version": "0.1.12", 538 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", 539 | "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", 540 | "license": "MIT" 541 | }, 542 | "node_modules/proxy-addr": { 543 | "version": "2.0.7", 544 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 545 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 546 | "dependencies": { 547 | "forwarded": "0.2.0", 548 | "ipaddr.js": "1.9.1" 549 | }, 550 | "engines": { 551 | "node": ">= 0.10" 552 | } 553 | }, 554 | "node_modules/qs": { 555 | "version": "6.13.0", 556 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", 557 | "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", 558 | "license": "BSD-3-Clause", 559 | "dependencies": { 560 | "side-channel": "^1.0.6" 561 | }, 562 | "engines": { 563 | "node": ">=0.6" 564 | }, 565 | "funding": { 566 | "url": "https://github.com/sponsors/ljharb" 567 | } 568 | }, 569 | "node_modules/range-parser": { 570 | "version": "1.2.1", 571 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 572 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 573 | "license": "MIT", 574 | "engines": { 575 | "node": ">= 0.6" 576 | } 577 | }, 578 | "node_modules/raw-body": { 579 | "version": "2.5.2", 580 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", 581 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", 582 | "license": "MIT", 583 | "dependencies": { 584 | "bytes": "3.1.2", 585 | "http-errors": "2.0.0", 586 | "iconv-lite": "0.4.24", 587 | "unpipe": "1.0.0" 588 | }, 589 | "engines": { 590 | "node": ">= 0.8" 591 | } 592 | }, 593 | "node_modules/safe-buffer": { 594 | "version": "5.2.1", 595 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 596 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 597 | "funding": [ 598 | { 599 | "type": "github", 600 | "url": "https://github.com/sponsors/feross" 601 | }, 602 | { 603 | "type": "patreon", 604 | "url": "https://www.patreon.com/feross" 605 | }, 606 | { 607 | "type": "consulting", 608 | "url": "https://feross.org/support" 609 | } 610 | ] 611 | }, 612 | "node_modules/safer-buffer": { 613 | "version": "2.1.2", 614 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 615 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 616 | "license": "MIT" 617 | }, 618 | "node_modules/send": { 619 | "version": "0.19.0", 620 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", 621 | "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", 622 | "license": "MIT", 623 | "dependencies": { 624 | "debug": "2.6.9", 625 | "depd": "2.0.0", 626 | "destroy": "1.2.0", 627 | "encodeurl": "~1.0.2", 628 | "escape-html": "~1.0.3", 629 | "etag": "~1.8.1", 630 | "fresh": "0.5.2", 631 | "http-errors": "2.0.0", 632 | "mime": "1.6.0", 633 | "ms": "2.1.3", 634 | "on-finished": "2.4.1", 635 | "range-parser": "~1.2.1", 636 | "statuses": "2.0.1" 637 | }, 638 | "engines": { 639 | "node": ">= 0.8.0" 640 | } 641 | }, 642 | "node_modules/send/node_modules/encodeurl": { 643 | "version": "1.0.2", 644 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 645 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 646 | "license": "MIT", 647 | "engines": { 648 | "node": ">= 0.8" 649 | } 650 | }, 651 | "node_modules/send/node_modules/ms": { 652 | "version": "2.1.3", 653 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 654 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 655 | "license": "MIT" 656 | }, 657 | "node_modules/serve-static": { 658 | "version": "1.16.2", 659 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", 660 | "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", 661 | "license": "MIT", 662 | "dependencies": { 663 | "encodeurl": "~2.0.0", 664 | "escape-html": "~1.0.3", 665 | "parseurl": "~1.3.3", 666 | "send": "0.19.0" 667 | }, 668 | "engines": { 669 | "node": ">= 0.8.0" 670 | } 671 | }, 672 | "node_modules/set-function-length": { 673 | "version": "1.2.2", 674 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", 675 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", 676 | "license": "MIT", 677 | "dependencies": { 678 | "define-data-property": "^1.1.4", 679 | "es-errors": "^1.3.0", 680 | "function-bind": "^1.1.2", 681 | "get-intrinsic": "^1.2.4", 682 | "gopd": "^1.0.1", 683 | "has-property-descriptors": "^1.0.2" 684 | }, 685 | "engines": { 686 | "node": ">= 0.4" 687 | } 688 | }, 689 | "node_modules/setprototypeof": { 690 | "version": "1.2.0", 691 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 692 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 693 | }, 694 | "node_modules/side-channel": { 695 | "version": "1.0.6", 696 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", 697 | "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", 698 | "license": "MIT", 699 | "dependencies": { 700 | "call-bind": "^1.0.7", 701 | "es-errors": "^1.3.0", 702 | "get-intrinsic": "^1.2.4", 703 | "object-inspect": "^1.13.1" 704 | }, 705 | "engines": { 706 | "node": ">= 0.4" 707 | }, 708 | "funding": { 709 | "url": "https://github.com/sponsors/ljharb" 710 | } 711 | }, 712 | "node_modules/statuses": { 713 | "version": "2.0.1", 714 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 715 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 716 | "engines": { 717 | "node": ">= 0.8" 718 | } 719 | }, 720 | "node_modules/toidentifier": { 721 | "version": "1.0.1", 722 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 723 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 724 | "engines": { 725 | "node": ">=0.6" 726 | } 727 | }, 728 | "node_modules/type-is": { 729 | "version": "1.6.18", 730 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 731 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 732 | "dependencies": { 733 | "media-typer": "0.3.0", 734 | "mime-types": "~2.1.24" 735 | }, 736 | "engines": { 737 | "node": ">= 0.6" 738 | } 739 | }, 740 | "node_modules/unpipe": { 741 | "version": "1.0.0", 742 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 743 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 744 | "license": "MIT", 745 | "engines": { 746 | "node": ">= 0.8" 747 | } 748 | }, 749 | "node_modules/utils-merge": { 750 | "version": "1.0.1", 751 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 752 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", 753 | "engines": { 754 | "node": ">= 0.4.0" 755 | } 756 | }, 757 | "node_modules/vary": { 758 | "version": "1.1.2", 759 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 760 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", 761 | "engines": { 762 | "node": ">= 0.8" 763 | } 764 | } 765 | }, 766 | "dependencies": { 767 | "accepts": { 768 | "version": "1.3.8", 769 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 770 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 771 | "requires": { 772 | "mime-types": "~2.1.34", 773 | "negotiator": "0.6.3" 774 | } 775 | }, 776 | "array-flatten": { 777 | "version": "1.1.1", 778 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 779 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 780 | }, 781 | "body-parser": { 782 | "version": "1.20.3", 783 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", 784 | "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", 785 | "requires": { 786 | "bytes": "3.1.2", 787 | "content-type": "~1.0.5", 788 | "debug": "2.6.9", 789 | "depd": "2.0.0", 790 | "destroy": "1.2.0", 791 | "http-errors": "2.0.0", 792 | "iconv-lite": "0.4.24", 793 | "on-finished": "2.4.1", 794 | "qs": "6.13.0", 795 | "raw-body": "2.5.2", 796 | "type-is": "~1.6.18", 797 | "unpipe": "1.0.0" 798 | } 799 | }, 800 | "bytes": { 801 | "version": "3.1.2", 802 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 803 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" 804 | }, 805 | "call-bind": { 806 | "version": "1.0.7", 807 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", 808 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", 809 | "requires": { 810 | "es-define-property": "^1.0.0", 811 | "es-errors": "^1.3.0", 812 | "function-bind": "^1.1.2", 813 | "get-intrinsic": "^1.2.4", 814 | "set-function-length": "^1.2.1" 815 | } 816 | }, 817 | "content-disposition": { 818 | "version": "0.5.4", 819 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 820 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 821 | "requires": { 822 | "safe-buffer": "5.2.1" 823 | } 824 | }, 825 | "content-type": { 826 | "version": "1.0.5", 827 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 828 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" 829 | }, 830 | "cookie": { 831 | "version": "0.7.1", 832 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", 833 | "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==" 834 | }, 835 | "cookie-signature": { 836 | "version": "1.0.6", 837 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 838 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 839 | }, 840 | "debug": { 841 | "version": "2.6.9", 842 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 843 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 844 | "requires": { 845 | "ms": "2.0.0" 846 | } 847 | }, 848 | "define-data-property": { 849 | "version": "1.1.4", 850 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", 851 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", 852 | "requires": { 853 | "es-define-property": "^1.0.0", 854 | "es-errors": "^1.3.0", 855 | "gopd": "^1.0.1" 856 | } 857 | }, 858 | "depd": { 859 | "version": "2.0.0", 860 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 861 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" 862 | }, 863 | "destroy": { 864 | "version": "1.2.0", 865 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 866 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" 867 | }, 868 | "dotenv": { 869 | "version": "10.0.0", 870 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", 871 | "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==" 872 | }, 873 | "ee-first": { 874 | "version": "1.1.1", 875 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 876 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 877 | }, 878 | "encodeurl": { 879 | "version": "2.0.0", 880 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 881 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" 882 | }, 883 | "es-define-property": { 884 | "version": "1.0.0", 885 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", 886 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", 887 | "requires": { 888 | "get-intrinsic": "^1.2.4" 889 | } 890 | }, 891 | "es-errors": { 892 | "version": "1.3.0", 893 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 894 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" 895 | }, 896 | "escape-html": { 897 | "version": "1.0.3", 898 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 899 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 900 | }, 901 | "etag": { 902 | "version": "1.8.1", 903 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 904 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" 905 | }, 906 | "express": { 907 | "version": "4.21.2", 908 | "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", 909 | "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", 910 | "requires": { 911 | "accepts": "~1.3.8", 912 | "array-flatten": "1.1.1", 913 | "body-parser": "1.20.3", 914 | "content-disposition": "0.5.4", 915 | "content-type": "~1.0.4", 916 | "cookie": "0.7.1", 917 | "cookie-signature": "1.0.6", 918 | "debug": "2.6.9", 919 | "depd": "2.0.0", 920 | "encodeurl": "~2.0.0", 921 | "escape-html": "~1.0.3", 922 | "etag": "~1.8.1", 923 | "finalhandler": "1.3.1", 924 | "fresh": "0.5.2", 925 | "http-errors": "2.0.0", 926 | "merge-descriptors": "1.0.3", 927 | "methods": "~1.1.2", 928 | "on-finished": "2.4.1", 929 | "parseurl": "~1.3.3", 930 | "path-to-regexp": "0.1.12", 931 | "proxy-addr": "~2.0.7", 932 | "qs": "6.13.0", 933 | "range-parser": "~1.2.1", 934 | "safe-buffer": "5.2.1", 935 | "send": "0.19.0", 936 | "serve-static": "1.16.2", 937 | "setprototypeof": "1.2.0", 938 | "statuses": "2.0.1", 939 | "type-is": "~1.6.18", 940 | "utils-merge": "1.0.1", 941 | "vary": "~1.1.2" 942 | } 943 | }, 944 | "finalhandler": { 945 | "version": "1.3.1", 946 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", 947 | "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", 948 | "requires": { 949 | "debug": "2.6.9", 950 | "encodeurl": "~2.0.0", 951 | "escape-html": "~1.0.3", 952 | "on-finished": "2.4.1", 953 | "parseurl": "~1.3.3", 954 | "statuses": "2.0.1", 955 | "unpipe": "~1.0.0" 956 | } 957 | }, 958 | "forwarded": { 959 | "version": "0.2.0", 960 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 961 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" 962 | }, 963 | "fresh": { 964 | "version": "0.5.2", 965 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 966 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" 967 | }, 968 | "function-bind": { 969 | "version": "1.1.2", 970 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 971 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" 972 | }, 973 | "get-intrinsic": { 974 | "version": "1.2.4", 975 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", 976 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", 977 | "requires": { 978 | "es-errors": "^1.3.0", 979 | "function-bind": "^1.1.2", 980 | "has-proto": "^1.0.1", 981 | "has-symbols": "^1.0.3", 982 | "hasown": "^2.0.0" 983 | } 984 | }, 985 | "gopd": { 986 | "version": "1.1.0", 987 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.1.0.tgz", 988 | "integrity": "sha512-FQoVQnqcdk4hVM4JN1eromaun4iuS34oStkdlLENLdpULsuQcTyXj8w7ayhuUfPwEYZ1ZOooOTT6fdA9Vmx/RA==", 989 | "requires": { 990 | "get-intrinsic": "^1.2.4" 991 | } 992 | }, 993 | "has-property-descriptors": { 994 | "version": "1.0.2", 995 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", 996 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", 997 | "requires": { 998 | "es-define-property": "^1.0.0" 999 | } 1000 | }, 1001 | "has-proto": { 1002 | "version": "1.1.0", 1003 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.1.0.tgz", 1004 | "integrity": "sha512-QLdzI9IIO1Jg7f9GT1gXpPpXArAn6cS31R1eEZqz08Gc+uQ8/XiqHWt17Fiw+2p6oTTIq5GXEpQkAlA88YRl/Q==", 1005 | "requires": { 1006 | "call-bind": "^1.0.7" 1007 | } 1008 | }, 1009 | "has-symbols": { 1010 | "version": "1.1.0", 1011 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 1012 | "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" 1013 | }, 1014 | "hasown": { 1015 | "version": "2.0.2", 1016 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 1017 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 1018 | "requires": { 1019 | "function-bind": "^1.1.2" 1020 | } 1021 | }, 1022 | "http-errors": { 1023 | "version": "2.0.0", 1024 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 1025 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 1026 | "requires": { 1027 | "depd": "2.0.0", 1028 | "inherits": "2.0.4", 1029 | "setprototypeof": "1.2.0", 1030 | "statuses": "2.0.1", 1031 | "toidentifier": "1.0.1" 1032 | } 1033 | }, 1034 | "iconv-lite": { 1035 | "version": "0.4.24", 1036 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 1037 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 1038 | "requires": { 1039 | "safer-buffer": ">= 2.1.2 < 3" 1040 | } 1041 | }, 1042 | "inherits": { 1043 | "version": "2.0.4", 1044 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1045 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1046 | }, 1047 | "ipaddr.js": { 1048 | "version": "1.9.1", 1049 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 1050 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 1051 | }, 1052 | "media-typer": { 1053 | "version": "0.3.0", 1054 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 1055 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 1056 | }, 1057 | "merge-descriptors": { 1058 | "version": "1.0.3", 1059 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", 1060 | "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==" 1061 | }, 1062 | "methods": { 1063 | "version": "1.1.2", 1064 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 1065 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 1066 | }, 1067 | "mime": { 1068 | "version": "1.6.0", 1069 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 1070 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 1071 | }, 1072 | "mime-db": { 1073 | "version": "1.52.0", 1074 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 1075 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" 1076 | }, 1077 | "mime-types": { 1078 | "version": "2.1.35", 1079 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 1080 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 1081 | "requires": { 1082 | "mime-db": "1.52.0" 1083 | } 1084 | }, 1085 | "ms": { 1086 | "version": "2.0.0", 1087 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1088 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1089 | }, 1090 | "negotiator": { 1091 | "version": "0.6.3", 1092 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 1093 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" 1094 | }, 1095 | "object-inspect": { 1096 | "version": "1.13.3", 1097 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", 1098 | "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==" 1099 | }, 1100 | "on-finished": { 1101 | "version": "2.4.1", 1102 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 1103 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 1104 | "requires": { 1105 | "ee-first": "1.1.1" 1106 | } 1107 | }, 1108 | "parseurl": { 1109 | "version": "1.3.3", 1110 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1111 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 1112 | }, 1113 | "path-to-regexp": { 1114 | "version": "0.1.12", 1115 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", 1116 | "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" 1117 | }, 1118 | "proxy-addr": { 1119 | "version": "2.0.7", 1120 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 1121 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 1122 | "requires": { 1123 | "forwarded": "0.2.0", 1124 | "ipaddr.js": "1.9.1" 1125 | } 1126 | }, 1127 | "qs": { 1128 | "version": "6.13.0", 1129 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", 1130 | "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", 1131 | "requires": { 1132 | "side-channel": "^1.0.6" 1133 | } 1134 | }, 1135 | "range-parser": { 1136 | "version": "1.2.1", 1137 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1138 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 1139 | }, 1140 | "raw-body": { 1141 | "version": "2.5.2", 1142 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", 1143 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", 1144 | "requires": { 1145 | "bytes": "3.1.2", 1146 | "http-errors": "2.0.0", 1147 | "iconv-lite": "0.4.24", 1148 | "unpipe": "1.0.0" 1149 | } 1150 | }, 1151 | "safe-buffer": { 1152 | "version": "5.2.1", 1153 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1154 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 1155 | }, 1156 | "safer-buffer": { 1157 | "version": "2.1.2", 1158 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1159 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1160 | }, 1161 | "send": { 1162 | "version": "0.19.0", 1163 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", 1164 | "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", 1165 | "requires": { 1166 | "debug": "2.6.9", 1167 | "depd": "2.0.0", 1168 | "destroy": "1.2.0", 1169 | "encodeurl": "~1.0.2", 1170 | "escape-html": "~1.0.3", 1171 | "etag": "~1.8.1", 1172 | "fresh": "0.5.2", 1173 | "http-errors": "2.0.0", 1174 | "mime": "1.6.0", 1175 | "ms": "2.1.3", 1176 | "on-finished": "2.4.1", 1177 | "range-parser": "~1.2.1", 1178 | "statuses": "2.0.1" 1179 | }, 1180 | "dependencies": { 1181 | "encodeurl": { 1182 | "version": "1.0.2", 1183 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 1184 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" 1185 | }, 1186 | "ms": { 1187 | "version": "2.1.3", 1188 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1189 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 1190 | } 1191 | } 1192 | }, 1193 | "serve-static": { 1194 | "version": "1.16.2", 1195 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", 1196 | "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", 1197 | "requires": { 1198 | "encodeurl": "~2.0.0", 1199 | "escape-html": "~1.0.3", 1200 | "parseurl": "~1.3.3", 1201 | "send": "0.19.0" 1202 | } 1203 | }, 1204 | "set-function-length": { 1205 | "version": "1.2.2", 1206 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", 1207 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", 1208 | "requires": { 1209 | "define-data-property": "^1.1.4", 1210 | "es-errors": "^1.3.0", 1211 | "function-bind": "^1.1.2", 1212 | "get-intrinsic": "^1.2.4", 1213 | "gopd": "^1.0.1", 1214 | "has-property-descriptors": "^1.0.2" 1215 | } 1216 | }, 1217 | "setprototypeof": { 1218 | "version": "1.2.0", 1219 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1220 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 1221 | }, 1222 | "side-channel": { 1223 | "version": "1.0.6", 1224 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", 1225 | "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", 1226 | "requires": { 1227 | "call-bind": "^1.0.7", 1228 | "es-errors": "^1.3.0", 1229 | "get-intrinsic": "^1.2.4", 1230 | "object-inspect": "^1.13.1" 1231 | } 1232 | }, 1233 | "statuses": { 1234 | "version": "2.0.1", 1235 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 1236 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" 1237 | }, 1238 | "toidentifier": { 1239 | "version": "1.0.1", 1240 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1241 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" 1242 | }, 1243 | "type-is": { 1244 | "version": "1.6.18", 1245 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1246 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1247 | "requires": { 1248 | "media-typer": "0.3.0", 1249 | "mime-types": "~2.1.24" 1250 | } 1251 | }, 1252 | "unpipe": { 1253 | "version": "1.0.0", 1254 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1255 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" 1256 | }, 1257 | "utils-merge": { 1258 | "version": "1.0.1", 1259 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1260 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 1261 | }, 1262 | "vary": { 1263 | "version": "1.1.2", 1264 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1265 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 1266 | } 1267 | } 1268 | } 1269 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webhook-sample", 3 | "version": "2.0.0", 4 | "description": "Receive Zoom webhooks.", 5 | "author": "Zoom Video Communications, Inc.", 6 | "contributors": [ 7 | { 8 | "name": "Tommy Gaessler" 9 | }, 10 | { 11 | "name": "EkaanshArora" 12 | } 13 | ], 14 | "main": "index.js", 15 | "scripts": { 16 | "test": "echo \"Error: no test specified\" && exit 1", 17 | "start": "node index.js" 18 | }, 19 | "license": "ISC", 20 | "dependencies": { 21 | "body-parser": "^1.19.0", 22 | "dotenv": "^10.0.0", 23 | "express": "^4.17.1" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /render.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | - type: web 3 | name: Zoom Video SDK Auth Sample 4 | runtime: node 5 | buildCommand: npm install 6 | startCommand: npm start 7 | repo: https://github.com/zoom/webhook-sample 8 | rootDir: . 9 | plan: free 10 | envVars: 11 | - key: ZOOM_WEBHOOK_SECRET_TOKEN 12 | sync: false 13 | --------------------------------------------------------------------------------