node_modules ignore

This commit is contained in:
2025-05-08 23:43:47 +02:00
parent e19d52f172
commit 4574544c9f
65041 changed files with 10593536 additions and 0 deletions

367
server/node_modules/grant/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,367 @@
# Change Log
## v5.4.24 (2025/02/04)
- **Change:** Update deps
## v5.4.23 (2024/09/16)
- **New:** Official support for 1 new providers: `authentik`
- **New:** Official support for Openstreetmap OAuth 2.0 apps: `openstreetmap2` [quirks](https://github.com/simov/grant#provider-quirks)
## v5.4.22 (2023/10/06)
- **New:** Official support for 2 new providers: `osu`, `workos`
- **Change:** Updated 2 providers: `autodesk`, `withings`
- **Change:** Removed 2 discontinued providers: `flattr`, `flowdock`
## v5.4.21 (2022/03/09)
- **New:** Official support for 2 new providers: `authing`, `tiktok`
- **New:** Official support for Twitter OAuth 1.0a `x_auth_access_type` custom scope parameter: [quirks](https://github.com/simov/grant#provider-quirks)
## v5.4.20 (2022/01/23)
- **New:** Official support for Twitter OAuth 2.0 apps: `twitter2` [quirks](https://github.com/simov/grant#provider-quirks)
- **Change:** Updated 1 provider: `google` id_token `iss: accounts.google.com -> https://accounts.google.com`
## v5.4.19 (2022/01/03)
- **New:** Official support for 1 new provider: `surveysparrow`
- **Fix:** Vercel handler cookie handling
## v5.4.18 (2021/10/19)
- **New:** Official support for 2 new providers: `crossid`, `untappd`
## v5.4.17 (2021/09/04)
- **New:** Official support for 2 new providers: `trustpilot`, `unbounce`
- **Change:** Updated 1 provider: `yandex`
## v5.4.16 (2021/07/18)
- **New:** Official support for 2 new providers: `adobe`, `procore`
- **Change:** Updated 1 provider: `linkedin`
## v5.4.15 (2021/06/20)
- **New:** Official support for 2 new providers: `notion`, `sellsy`
## v5.4.14 (2021/05/16)
- **Change:** Return user profile for `apple`
## v5.4.13 (2021/04/18)
- **Change:** Updated 1 provider: `withings`
- **Fix:** Type definitions for TypeScript
## v5.4.12 (2021/03/20)
- **Fix:** Type definitions for TypeScript
## v5.4.11 (2021/03/20)
- **Fix:** Better support for JavaScript bundlers
- **Change:** Updated 1 provider: `wechat`
## v5.4.10 (2021/03/07)
- **New:** Official support for 3 new providers: `huddle`, `netlify`, `snowflake`
- **Change:** Removed 1 discontinued provider: `mixer`
- **Change:** Renamed provider `surveygizmo` to `alchemer`
- **Change:** Updated 4 providers: `discord`, `ibm`, `okta`, `twitch`
- **Fix:** Error on missing `state` and `nonce`
## v5.4.9 (2020/11/22)
- **Fix:** Type definitions for TypeScript
## v5.4.8 (2020/11/17)
- **Fix:** Type definitions for TypeScript
## v5.4.7 (2020/11/16)
- **Fix:** Type definitions for TypeScript
## v5.4.6 (2020/11/16)
- **New:** Type definitions for TypeScript
- **New:** Official support for 1 new provider: `keycloak`
## v5.4.5 (2020/10/11)
- **Fix:** Allow for more clock skew for the `iat` and `nbf` claims when using `private_key_jwt` authentication for the token endpoint
- **New:** HTTP Framework handler for Curveball
- **New:** Official support for 2 new providers: `figma`, `mendeley`
## v5.4.4 (2020/09/23)
- **New:** Support for `response_mode: form_post`
## v5.4.3 (2020/09/21)
- **Fix:** Path matching for `gcloud` handler - [docs](https://github.com/simov/grant-gcloud#routes)
## v5.4.2 (2020/09/17)
- **Fix:** Path matching for `aws` handler - [docs](https://github.com/simov/grant-aws#routes)
## v5.4.1 (2020/09/14)
- **Fix:** Improved path mathching for `aws` handler + support for event format v2
- **New:** Official support for 2 new providers: `autodesk`, `storyblok`
- **Change:** Renamed provider `zeit` to `vercel`
## v5.4.0 (2020/09/01)
- **New:** HTTP Framework handler for Fastify
## v5.3.0 (2020/08/09)
- **New:** Serverless handlers for [AWS Lambda](https://github.com/simov/grant-aws), [Azure Function](https://github.com/simov/grant-azure), [Google Cloud Function](https://github.com/simov/grant-gcloud) and [Vercel](https://github.com/simov/grant-vercel)
- **New:** RSA-SHA1 signature method support for OAuth1.0a
- **Fix:** OAuth2 support for `intuit`
- **Fix:** Profile endpoints for `qq` and `weibo`
## v5.2.0 (2020/06/07)
- **New:** Support for [request options](https://github.com/simov/grant#misc-request)
- **New:** Official support for 2 new providers: `apple`, `garmin`
## v5.1.1 (2020/05/25)
- **Fix:** The upcoming Grant constructor
## v5.1.0 (2020/05/25)
- **New:** Support for `private_key_jwt` client authentication
- **New:** `grant-profile` was deprecated as standalone module and is now [embedded](https://github.com/simov/grant#profile) into Grant
- **New:** Increase the random `state` and `nonce` size
- **New:** Official support for 4 new providers: `cas`, `cognito`, `fusionauth`, `logingov`
## v5.0.1 (2020/05/01)
- **Fix:** Fixed the path matching regexp for Express and Koa
## v5.0.0 (2020/04/18)
- **Breaking:** Drop support for Node v4 and v6
- **Breaking:** Return `id_token` as string by default
- **Breaking:** Change in the `response` configuration
- **New:** `origin` and `prefix` configuration
- **Deprecate:** Koa v1 and Hapi <= v16
- **Deprecate:** `protocol`, `host`, and `path` configuration
- **[Migration Guide: from v4 to v5](https://github.com/simov/grant/blob/master/MIGRATION.md)**
## v4.7.0 (2020/01/26)
- **New:** [PKCE](https://github.com/simov/grant/commit/3b04eb69a278165ae9be7ba7a06e8b85da21c5e5) support
- **New:** [input state](https://github.com/simov/grant/commit/3b04eb69a278165ae9be7ba7a06e8b85da21c5e5) overrides
- **New:** [output state](https://github.com/simov/grant/commit/3b04eb69a278165ae9be7ba7a06e8b85da21c5e5) transport
- **New:** user-agent header is set on all internal requests
## v4.6.6 (2020/01/01)
- **Fix:** Regression about race condition for [slow session stores](https://github.com/simov/grant/pull/122) in Express middleware
- **New:** Official support for 2 new providers: `livechat` and `zeit`
## v4.6.5 (2019/12/07)
- **Fix:** Support for `instagram` Graph API
## v4.6.4 (2019/10/27)
- **New:** Official support for 2 new providers: `line` and `naver`
- **Fix:** Updated 4 providers: `clio`, `concur`, `familysearch` and `fitbit`
## v4.6.3 (2019/09/07)
- **New:** Official support for 3 new providers: `atlassian`, `aweber`, `phantauth`
- **Change:** Removed 6 discontinued providers: `dailymile`, `everyplay`, `fluidsurveys`, `moves`, `mydigipass`, `producteev`
- **Change:** Renamed `letsfreckle` to `nokotime`
## v4.6.2 (2019/07/29)
- **New:** Official support for 3 new providers: `mailxpert`, `snapchat` and `zoom`
## v4.6.1 (2019/07/06)
- **Fix:** Support for `cookie-session` in Express middleware
## v4.6.0 (2019/06/23)
- **Fix:** Race condition for [slow session stores](https://github.com/simov/grant/pull/122) in Express middleware
- **New:** `koa-mount` no longer required for the Koa middleware
## v4.5.2 (2019/05/19)
- **Fix:** Support for **@hapi/hapi** namespace
## v4.5.1 (2019/04/07)
- **Fix:** Support for **Hapi >= 18**
## v4.5.0 (2019/03/04)
- **New:** Added [`token_endpoint_auth_method`](https://github.com/simov/grant#token-endpoint-auth-method) option
- **New:** Official support for 1 new provider: `wechat`
## v4.4.1 (2019/01/25)
- **Fix:** Accept array of `aud` claims when validating an `id_token`
- **New:** Official support for 1 new provider: `qq`
## v4.4.0 (2019/01/11)
- **New:** Added `response` option for limiting the response data
## v4.3.1 (2019/01/06)
- **Fix:** Nested static overrides filtering
## v4.3.0 (2019/01/02)
- **New:** Explicit `overrides` option for defining static overrides
- **New:** Official support for 2 new providers: `ibm`, `mention`
## v4.2.2 (2018/12/07)
- **New:** Official support for 2 new providers: `freelancer`, `hootsuite`
- **Change:** Removed 1 discontinued provider: `jawbone`
## v4.2.1 (2018/11/27)
- **Fix:** Regression regarding missing session in the callback route
## v4.2.0 (2018/11/10)
- **New:** [OpenID Connect](https://github.com/simov/grant#openid-connect) `id_token` and `nonce` support
- **New:** The `server` configuration option is now called `defaults` (`server` is still allowed)
- **New:** Explicit `dynamic` option to control the Dynamic Override feature
- **Change:** The Dynamic Override is now **disabled by default!** In case you rely on it you have to enable it explicitly. Use the [more granular](https://github.com/simov/grant#dynamic-override) configuration or the [proxy one](https://github.com/simov/grant#oauth-proxy)
- **New:** Official support for 2 new providers: `mastodon`, `onelogin`
- **Change:** Updated 4 providers: `bitbucket`, `strava`, `twitch`, `yahoo`
## v4.1.2 (2018/07/16)
- **New:** Official support for 4 new providers: `arcgis`, `nest`, `okta`, `typeform`
- **Change:** Updated 2 providers: `dropbox`, `withings`
## v4.1.1 (2018/04/22)
- **New:** Official support for 6 new providers: `auth0`, `bettlenet`, `mixer`, `nylas`, `timelyapp`, `viadeo`
- **Change:** Removed 5 discontinued providers: `appnet`, `codeplex`, `elance`, `odesk`, `rdio`
## v4.1.0 (2018/03/18)
- **New:** Support for **Hapi >= 17**
## v4.0.1 (2018/03/15)
- **Fix:** Minor fix in `request-compose`
## v4.0.0 (2018/03/14)
- **Change:** Officially **Node >= 4.0.0 required!**
- **Change:** Dropped the `request` dependency in favor of `request-compose`
- **Change:** Return errors more consistently based on the `transport` used (see below)
- **Change:** The internal session variable `step1` was renamed to `request`
- **Change:** The internal `_config` property is no longer exposed
```js
app.use(new Grant({server: {transport: 'session'}}))
app.get('/final_callback', (req, res) => {
if (req.query.error) {} // v3.x
if (req.session.grant.response.error) {} // v4.x
})
```
## v3.8.2 (2018/02/13)
- **Change:** Migrate all OAuth endpoints to HTTPS
## v3.8.1 (2017/12/13)
- **New:** Official support for 2 new providers: `authentiq` and `patreon`
## v3.8.0 (2017/06/07)
- **Change:** Hapi is now using the internal `config` object directly through the middleware instance
- **Fix:** Dynamic overrides support for Hapi >= 12.x
- **New:** Hapi middleware configuration can be passed in the constructor
- **New:** First class support for **Koa >= 2.x** using `async`/`await` **Node >= 8.0.0 required!**
- Koa 1.x and 0.x are still supported for Node 4, 6 and 8
## v3.7.2 (2017/04/20)
- **Change:** Removed 2 discontinued providers: `beatsmusic` and `copy`
- **New:** Official support for 5 new providers: `ebay`, `genius`, `jamendo`, `pinterest` and `unsplash`
## v3.7.1 (2017/03/06)
- **New:** Official support for 2 new providers: `discord` and `medium`
## v3.7.0 (2016/12/29)
- **Change:** Dropped node `0.10` and `0.12` as built targets in TravisCI
- **Change:** Added the advisory engines key in package.json for node `>=4.0.0`
- **New:** Official support for 6 new providers: `baidu`, `docusign`, `iconfinder`, `idme`, `mydigipass`, `venmo`
## v3.6.5 (2016/09/30)
- **Fix:** Added the required `user-agent` header for `discogs`
- **New:** Official support for 1 new provider: `homeaway`
## v3.6.4 (2016/08/30)
- **New:** Support for Koa 2.x
## v3.6.3 (2016/07/27)
- **Fix:** Expect oauth version to be string when passed as querystring
- **New:** Official support for 1 new provider: `lyft`
## v3.6.2 (2016/05/17)
- **New:** Added `scope_data` custom parameter for `amazon`
## v3.6.1 (2016/04/25)
- **New:** Official support for 2 new providers: `idonthis`, `smugmug`
## v3.6.0 (2016/03/27)
- **New:** [Path Prefix](https://github.com/simov/grant#path-prefix) configuration option
- **New:** Official support for 2 new providers: `microsoft`, `visualstudio`
## v3.5.5 (2016/01/17)
- **Fix:** Fix for `yar@6.0.0`
- **New:** Official support for 2 new providers: `gitbook`, `optimizely`
## v3.5.4 (2015/12/28)
- **New:** Official support for 11 new providers
## v3.5.3 (2015/11/28)
- **New:** Official support for 8 new providers
## v3.5.2 (2015/10/30)
- **New:** OAuth2 support for `fitbit2`
- **New:** Official support for 6 new providers
## v3.5.1 (2015/09/30)
- **New:** Docs about the [Alternative Require](https://github.com/simov/grant#alternative-require)
- **New:** Official support for 6 new providers
## v3.5.0 (2015/08/30)
- **Change:** Improved OAuth2 [random state string](https://github.com/simov/grant/commit/e1cf1e468846e5b2e75f65d8bdf4794a88619c37)
- **New:** Ability to override the [redirect_uri](https://github.com/simov/grant#sandbox-redirect-uri)
- **New:** Ability to configure Grant without having a `server` configuration key
- **New:** Generic error handler for missing or misconfigured provider
- **New:** Introduced `custom_params` option for safer way to configure [Custom Authorization Parameters](https://github.com/simov/grant#custom-parameters)
- **New:** Improved documentation about all configuration [Quirks](https://github.com/simov/grant#quirks)
- **New:** Official support for 5 new providers
## v3.4.0 (2015/07/20)
- **Change:** Improved configuration initialization
- **Change:** Migrated `rdio` to OAuth2
- **Change:** Updated `trakt` OAuth URLs
- **New:** Added `device_id` and `device_name` custom authorization parameters for `yandex`
- **New:** Docs about the [Programmatic Access](https://github.com/simov/grant#programmatic-access)
- **New:** Official support for 3 new providers
## v3.3.3 (2015/06/24)
- **New:** Official support for 9 new providers
## v3.3.2 (2015/06/05)
- **New:** Official support for 2 new providers
## v3.3.1 (2015/05/21)
- **New:** Official support for 10 new providers
## v3.3.0 (2015/05/17)
- **Change:** The Express middleware is no longer using the [express-session middleware](https://github.com/simov/grant#express) internally
- **Change:** The Express and Koa middlewares are no longer using their [body-parser middleware](https://github.com/simov/grant#dynamic-override) internally
- **Change:** Express is set as `peerDependency` in `grant-express`
- **Change:** Koa is set as `peerDependency` in `grant-koa`
- **Change:** Yar is no longer set as `peerDependency` in `grant-hapi`, though using session is still required
## v3.2.0 (2015/04/23)
- **Change:** Any of the [reserved keys](https://github.com/simov/grant/blob/master/config/reserved.json) can be overriden for a provider
- **Change:** Allow [Custom Provider](https://github.com/simov/grant#custom-providers) configuration
## v3.1.0 (2015/04/14)
- **New:** `transport` option that allows the response data to be returned in the final callback either as querystring or in the [session](https://github.com/simov/grant/blob/master/examples/session-transport/app.js)
- **New:** `state: true` option that enables auto generated random state string on each authorization attempt (OAuth2 only)
## v3.0.3 (2015/04/02)
- **Change:** Allow [any session store](https://github.com/simov/grant/tree/master/examples/koa-session) to be used with the Koa middleware
- **Change:** Using `koa-route` instead of `koa-router` internally in the Koa middleware
- **Change:** `grant-hapi` now uses `peerDependencies`
## v3.0.2 (2015/03/17)
- **Fix:** Removed default Express require left over in index.js
## v3.0.1 (2015/03/15)
- **Fix:** Examples
## v3.0.0 (2015/03/15)
- **Change:** Each [consumer middleware](https://github.com/simov/grant#express) now have its own module: `grant-express`, `grant-koa` and `grant-hapi`
## v2.0.1 (2015/03/02)
- **New:** Hapi middleware
- **New:** Docs about [Dynamic Overrides](https://github.com/simov/grant#dynamic-override) via `GET` request
- **New:** A bunch of [Examples](https://github.com/simov/grant/tree/master/examples)
## v2.0.0 (2015/01/06)
- **Change:** Complete rewrite of the module using [request](https://github.com/request/request)
- **New:** Koa middleware
- **Change:** The [Response Data](https://github.com/simov/grant#response-data) now contains a `raw` key in it
- **Change:** [Custom Authorization Parameters](https://github.com/simov/grant#custom-parameters) regarding token expiration are no longer part of the scope array
---
## v1.1.4 (2014/11/27)
- Version `1.x` is no longer supported, though most of the configuration data structure remains intact, so migration should be easy
## v1.0.0 (2014/06/22)
- Initial Release

21
server/node_modules/grant/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014-present, Simeon Velichkov <simeonvelichkov@gmail.com> (https://github.com/simov/grant)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

1222
server/node_modules/grant/README.md generated vendored Normal file

File diff suppressed because one or more lines are too long

1195
server/node_modules/grant/config/oauth.json generated vendored Normal file

File diff suppressed because it is too large Load Diff

644
server/node_modules/grant/config/profile.json generated vendored Normal file
View File

@@ -0,0 +1,644 @@
{
"23andme": {
"profile_url": "https://api.23andme.com/3/account/"
},
"500px": {
"profile_url": "https://api.500px.com/v1/users"
},
"acton": {
"profile_url": "https://restapi.actonsoftware.com/api/1/account"
},
"acuityscheduling": {
"profile_url": "https://acuityscheduling.com/api/v1/me"
},
"adobe": {
"profile_url": "https://ims-na1.adobelogin.com/ims/userinfo/v2"
},
"aha": {
"profile_url": "https://[subdomain].aha.io/api/v1/me"
},
"alchemer": {
"profile_url": "https://api.alchemer.com/v4/accountuser"
},
"amazon": {
"profile_url": "https://api.amazon.com/user/profile"
},
"angellist": {
"profile_url": "https://api.angel.co/1/me"
},
"apple": {
"profile_url": ""
},
"arcgis": {
"profile_url": "https://www.arcgis.com/sharing/rest/community/self"
},
"asana": {
"profile_url": "https://app.asana.com/api/1.0/users/me"
},
"assembla": {
"profile_url": "https://api.assembla.com/v1/user.json"
},
"atlassian": {
"profile_url": "https://api.atlassian.com/me"
},
"auth0": {
"profile_url": "https://[subdomain].auth0.com/userinfo"
},
"authentik": {
"profile_url": "https://[subdomain]/application/o/userinfo/"
},
"authentiq": {
"profile_url": "https://connect.authentiq.io/userinfo"
},
"authing": {
"profile_url": "https://[subdomain].authing.cn/oidc/me"
},
"autodesk": {
"profile_url": "https://developer.api.autodesk.com/userprofile/v1/users/@me"
},
"aweber": {
"profile_url": "https://api.aweber.com/1.0/accounts/me"
},
"axosoft": {
"profile_url": "https://[subdomain].axosoft.com/api/v5/me"
},
"baidu": {
"profile_url": "https://openapi.baidu.com/rest/2.0/passport/users/getLoggedInUser"
},
"basecamp": {
"profile_url": "https://launchpad.37signals.com/authorization.json"
},
"battlenet": {
"profile_url": "https://[subdomain].battle.net/oauth/userinfo"
},
"beatport": {
"profile_url": "https://oauth-api.beatport.com/identity/1/person"
},
"bitbucket": {
"profile_url": "https://api.bitbucket.org/2.0/user"
},
"bitly": {
"profile_url": "https://api-ssl.bitly.com/v4/user"
},
"box": {
"profile_url": "https://api.box.com/2.0/users/me"
},
"buffer": {
"profile_url": "https://api.bufferapp.com/1/user.json"
},
"campaignmonitor": {
"profile_url": "https://api.createsend.com/api/v3.1/clients.json"
},
"cas": {
"profile_url": "https://[subdomain]/oidc/profile"
},
"cheddar": {
"profile_url": "https://api.cheddarapp.com/v1/me"
},
"clio": {
"profile_url": "https://app.clio.com/api/v4/users/who_am_i.json"
},
"cognito": {
"profile_url": "https://[subdomain]/oauth2/userInfo"
},
"coinbase": {
"profile_url": "https://api.coinbase.com/v2/user"
},
"concur": {
"profile_url": "https://[subdomain].api.concursolutions.com/api/user/v1.0/user"
},
"constantcontact": {
"profile_url": "https://api.constantcontact.com/v2/account/info"
},
"coursera": {
"profile_url": "https://api.coursera.org/api/externalBasicProfiles.v1"
},
"crossid": {
"profile_url": "https://[subdomain].crossid.io/oauth2/userinfo"
},
"dailymotion": {
"profile_url": "https://api.dailymotion.com/user/me"
},
"deezer": {
"profile_url": "http://api.deezer.com/user/me"
},
"delivery": {
"profile_url": "https://api.delivery.com/customer/account"
},
"deputy": {
"profile_url": "https://[subdomain].deputy.com/api/v1/me"
},
"deviantart": {
"profile_url": "https://www.deviantart.com/api/v1/oauth2/user/whoami"
},
"digitalocean": {
"profile_url": "https://api.digitalocean.com/v2/account"
},
"discogs": {
"profile_url": "https://api.discogs.com/oauth/identity"
},
"discord": {
"profile_url": "https://discord.com/api/users/@me"
},
"disqus": {
"profile_url": "https://disqus.com/api/3.0/users/details.json"
},
"docusign": {
"profile_url": "https://account.docusign.com/oauth/userinfo"
},
"dribbble": {
"profile_url": "https://api.dribbble.com/v2/user"
},
"dropbox": {
"profile_url": "https://api.dropboxapi.com/2/users/get_current_account"
},
"ebay": {
"profile_url": ""
},
"echosign": {
"profile_url": "https://api.echosign.com/api/rest/v6/users"
},
"ecwid": {
"profile_url": ""
},
"edmodo": {
"profile_url": "https://api.edmodo.com/users/me"
},
"egnyte": {
"profile_url": "https://[subdomain].egnyte.com/puboauth/v1/userinfo"
},
"etsy": {
"profile_url": "https://openapi.etsy.com/v2/users/__SELF__"
},
"eventbrite": {
"profile_url": "https://www.eventbriteapi.com/v3/users/me/"
},
"evernote": {
"profile_url": ""
},
"eyeem": {
"profile_url": "https://api.eyeem.com/v2/users/me"
},
"facebook": {
"profile_url": "https://graph.facebook.com/me"
},
"familysearch": {
"profile_url": "https://api.familysearch.org/platform/users/current"
},
"feedly": {
"profile_url": "https://cloud.feedly.com/v3/profile"
},
"figma": {
"profile_url": "https://api.figma.com/v1/me"
},
"fitbit": {
"profile_url": "https://api.fitbit.com/1/user/-/profile.json"
},
"flickr": {
"profile_url": "https://api.flickr.com/services/rest/"
},
"formstack": {
"profile_url": ""
},
"foursquare": {
"profile_url": "https://api.foursquare.com/v2/users/self"
},
"freeagent": {
"profile_url": ""
},
"freelancer": {
"profile_url": ""
},
"freshbooks": {
"profile_url": "https://[subdomain].freshbooks.com/api/2.1/xml-in"
},
"fusionauth": {
"profile_url": "https://[subdomain]/oauth2/userinfo"
},
"geeklist": {
"profile_url": ""
},
"genius": {
"profile_url": ""
},
"getbase": {
"profile_url": ""
},
"getpocket": {
"profile_url": "https://getpocket.com/v3/users"
},
"gitbook": {
"profile_url": ""
},
"github": {
"profile_url": "https://api.github.com/user"
},
"gitlab": {
"profile_url": "https://gitlab.com/api/v3/user"
},
"gitter": {
"profile_url": "https://api.gitter.im/v1/user"
},
"goodreads": {
"profile_url": "https://www.goodreads.com/api/auth_user"
},
"google": {
"profile_url": "https://openidconnect.googleapis.com/v1/userinfo"
},
"groove": {
"profile_url": ""
},
"gumroad": {
"profile_url": ""
},
"harvest": {
"profile_url": "https://[subdomain].harvestapp.com/account/who_am_i"
},
"hellosign": {
"profile_url": ""
},
"heroku": {
"profile_url": "https://api.heroku.com/account"
},
"homeaway": {
"profile_url": ""
},
"hootsuite": {
"profile_url": ""
},
"huddle": {
"profile_url": ""
},
"ibm": {
"profile_url": "https://login.ibm.com/oidc/endpoint/default/userinfo"
},
"iconfinder": {
"profile_url": ""
},
"idme": {
"profile_url": ""
},
"idonethis": {
"profile_url": ""
},
"imgur": {
"profile_url": "https://api.imgur.com/3/account/me.json"
},
"infusionsoft": {
"profile_url": ""
},
"instagram": {
"profile_url": "https://graph.instagram.com/me"
},
"intuit": {
"profile_url": ""
},
"jamendo": {
"profile_url": ""
},
"jumplead": {
"profile_url": ""
},
"kakao": {
"profile_url": "https://kapi.kakao.com/v1/user/me"
},
"keycloak": {
"profile_url": "https://[subdomain]/protocol/openid-connect/userinfo"
},
"line": {
"profile_url": "https://api.line.me/v2/profile"
},
"linkedin": {
"profile_url": "https://api.linkedin.com/v2/me"
},
"live": {
"profile_url": "https://apis.live.net/v5.0/me"
},
"livechat": {
"profile_url": ""
},
"logingov": {
"profile_url": "https://idp.int.identitysandbox.gov/api/openid_connect/userinfo"
},
"lyft": {
"profile_url": ""
},
"mailchimp": {
"profile_url": "https://[subdomain].api.mailchimp.com/2.0/metadata.json"
},
"mailup": {
"profile_url": ""
},
"mailxpert": {
"profile_url": ""
},
"mapmyfitness": {
"profile_url": "https://oauth2-api.mapmyapi.com/v7.1/user/self"
},
"mastodon": {
"profile_url": ""
},
"medium": {
"profile_url": ""
},
"meetup": {
"profile_url": "https://api.meetup.com/2/members"
},
"mendeley": {
"profile_url": "https://api.mendeley.com/profiles/me"
},
"mention": {
"profile_url": ""
},
"microsoft": {
"profile_url": "https://graph.microsoft.com/oidc/userinfo"
},
"mixcloud": {
"profile_url": "https://api.mixcloud.com/me"
},
"moxtra": {
"profile_url": ""
},
"myob": {
"profile_url": ""
},
"naver": {
"profile_url": "https://openapi.naver.com/v1/nid/me"
},
"nest": {
"profile_url": ""
},
"netlify": {
"profile_url": "https://api.netlify.com/api/v1/user"
},
"nokotime": {
"profile_url": ""
},
"notion": {
"profile_url": ""
},
"nylas": {
"profile_url": ""
},
"okta": {
"profile_url": "https://[subdomain].okta.com/oauth2/v1/userinfo"
},
"onelogin": {
"profile_url": ""
},
"openstreetmap": {
"profile_url": "https://api.openstreetmap.org/api/0.6/user/details.json"
},
"openstreetmap2": {
"profile_url": "https://api.openstreetmap.org/api/0.6/user/details.json"
},
"optimizely": {
"profile_url": ""
},
"osu": {
"profile_url": "https://osu.ppy.sh/api/v2/me"
},
"patreon": {
"profile_url": ""
},
"paypal": {
"profile_url": ""
},
"phantauth": {
"profile_url": "https://phantauth.net/auth/userinfo"
},
"pinterest": {
"profile_url": ""
},
"plurk": {
"profile_url": "https://www.plurk.com/APP/Profile/getOwnProfile"
},
"podio": {
"profile_url": "https://api.podio.com/user"
},
"procore": {
"profile_url": "https://api.procore.com/rest/v1.0/me"
},
"producthunt": {
"profile_url": ""
},
"projectplace": {
"profile_url": ""
},
"projectplace2": {
"profile_url": ""
},
"pushbullet": {
"profile_url": ""
},
"qq": {
"profile_url": "https://graph.qq.com/oauth2.0/me"
},
"ravelry": {
"profile_url": ""
},
"redbooth": {
"profile_url": "https://redbooth.com/api/3/me"
},
"reddit": {
"profile_url": "https://oauth.reddit.com/api/v1/me"
},
"runkeeper": {
"profile_url": "https://api.runkeeper.com/user"
},
"salesforce": {
"profile_url": "https://login.salesforce.com/services/oauth2/userinfo"
},
"shoeboxed": {
"profile_url": "https://api.shoeboxed.com/v2/user"
},
"shopify": {
"profile_url": "https://[subdomain].myshopify.com/admin/shop.json"
},
"skyrock": {
"profile_url": "https://api.skyrock.com/v2/user/get.json"
},
"slack": {
"profile_url": "https://slack.com/api/auth.test"
},
"slice": {
"profile_url": "https://api.slice.com/api/v1/users/self"
},
"smartsheet": {
"profile_url": ""
},
"smugmug": {
"profile_url": ""
},
"snapchat": {
"profile_url": "https://kit.snapchat.com/v1/me"
},
"socialpilot": {
"profile_url": ""
},
"socrata": {
"profile_url": "https://[subdomain]/api/users/current.json"
},
"soundcloud": {
"profile_url": "https://api.soundcloud.com/me.json"
},
"spotify": {
"profile_url": "https://api.spotify.com/v1/me"
},
"square": {
"profile_url": "https://connect.squareup.com/v1/me"
},
"stackexchange": {
"profile_url": "https://api.stackexchange.com/2.2/me"
},
"stocktwits": {
"profile_url": "https://api.stocktwits.com/api/2/account/verify.json"
},
"stormz": {
"profile_url": "https://api.stormz.me/v1/user/me"
},
"storyblok": {
"profile_url": ""
},
"strava": {
"profile_url": "https://www.strava.com/api/v3/athlete"
},
"stripe": {
"profile_url": "https://api.stripe.com/v1/account"
},
"surveymonkey": {
"profile_url": "https://api.surveymonkey.net/v2/users/me"
},
"surveysparrow": {
"profile_url": ""
},
"thingiverse": {
"profile_url": "https://api.thingiverse.com/users/me"
},
"ticketbud": {
"profile_url": ""
},
"tiktok": {
"profile_url": "https://open-api.tiktok.com/user/info/"
},
"timelyapp": {
"profile_url": ""
},
"todoist": {
"profile_url": ""
},
"trakt": {
"profile_url": "https://api-v2launch.trakt.tv/users/me"
},
"traxo": {
"profile_url": "https://api.traxo.com/v2/me"
},
"trello": {
"profile_url": "https://api.trello.com/1/members/me"
},
"tripit": {
"profile_url": "https://api.tripit.com/v1/get/profile"
},
"tumblr": {
"profile_url": "http://api.tumblr.com/v2/user/info"
},
"twitch": {
"profile_url": "https://api.twitch.tv/helix/users"
},
"twitter": {
"profile_url": "https://api.twitter.com/1.1/users/show.json"
},
"twitter2": {
"profile_url": "https://api.twitter.com/2/users/me"
},
"typeform": {
"profile_url": ""
},
"uber": {
"profile_url": "https://[subdomain].uber.com/v1/me"
},
"unbounce": {
"profile_url": "https://api.unbounce.com/users/self"
},
"underarmour": {
"profile_url": "https://api.ua.com/v7.1/user/self"
},
"unsplash": {
"profile_url": ""
},
"untappd": {
"profile_url": ""
},
"upwork": {
"profile_url": "https://www.upwork.com/api/info.json"
},
"uservoice": {
"profile_url": "https://[subdomain].uservoice.com/api/v1/users/current.json"
},
"vend": {
"profile_url": "https://[subdomain].vendhq.com/api/users"
},
"venmo": {
"profile_url": ""
},
"vercel": {
"profile_url": "https://api.vercel.com/www/user"
},
"verticalresponse": {
"profile_url": ""
},
"viadeo": {
"profile_url": ""
},
"vimeo": {
"profile_url": "https://api.vimeo.com/me"
},
"visualstudio": {
"profile_url": "https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=6.0"
},
"vk": {
"profile_url": "https://api.vk.com/method/users.get"
},
"wechat": {
"profile_url": "https://api.weixin.qq.com/sns/userinfo"
},
"weekdone": {
"profile_url": ""
},
"weibo": {
"profile_url": "https://api.weibo.com/2/users/show.json"
},
"withings": {
"profile_url": "https://wbsapi.withings.net/v2/user"
},
"wordpress": {
"profile_url": "https://public-api.wordpress.com/rest/v1/me"
},
"workos": {
"profile_url": "https://api.workos.com/sso/profile"
},
"wrike": {
"profile_url": ""
},
"xero": {
"profile_url": ""
},
"xing": {
"profile_url": "https://api.xing.com/v1/users/me.json"
},
"yahoo": {
"profile_url": "https://api.login.yahoo.com/openid/v1/userinfo"
},
"yammer": {
"profile_url": "https://www.yammer.com/api/v1/users/current.json"
},
"yandex": {
"profile_url": "https://login.yandex.ru/info"
},
"zendesk": {
"profile_url": "https://[subdomain].zendesk.com/api/v2/users/me.json"
},
"zoom": {
"profile_url": "https://api.zoom.us/v2/users/me"
}
}

40
server/node_modules/grant/config/reserved.json generated vendored Normal file
View File

@@ -0,0 +1,40 @@
[
"request_url",
"authorize_url",
"access_url",
"oauth",
"scope_delimiter",
"token_endpoint_auth_method",
"token_endpoint_auth_signing_alg",
"origin",
"prefix",
"state",
"nonce",
"pkce",
"response",
"transport",
"callback",
"overrides",
"dynamic",
"public_key",
"private_key",
"protocol",
"host",
"path",
"key",
"secret",
"consumer_key",
"consumer_secret",
"client_id",
"client_secret",
"scope",
"custom_params",
"subdomain",
"name",
"redirect_uri",
"profile_url"
]

442
server/node_modules/grant/grant.d.ts generated vendored Normal file
View File

@@ -0,0 +1,442 @@
import {
RequestOptions as RequestComposeOptions,
} from 'request-compose'
// ----------------------------------------------------------------------------
/**
* Grant options
*/
export interface GrantOptions {
/**
* Handler name
*/
handler?: 'express' | 'koa' | 'hapi' | 'fastify' | 'curveball' |
'node' | 'aws' | 'azure' | 'gcloud' | 'vercel'
/**
* Grant configuration
*/
config?: GrantConfig
/**
* HTTP client options
*/
request?: RequestComposeOptions
/**
* Grant session options
*/
session?: GrantSessionConfig
// exclude
defaults?: never
}
/**
* Grant config
*/
export interface GrantConfig {
/**
* Default configuration for all providers
*/
defaults?: GrantProvider
/**
* Provider configuration
*/
[provider: string]: GrantProvider | undefined
// exclude
handler?: never
config?: never
request?: never
session?: never
}
/**
* Grant provider
*/
export interface GrantProvider {
// Authorization Server
/**
* OAuth 1.0a only, first step
*/
request_url?: string
/**
* OAuth 2.0 first step, OAuth 1.0a second step
*/
authorize_url?: string
/**
* OAuth 2.0 second step, OAuth 1.0a third step
*/
access_url?: string
/**
* OAuth version number
*/
oauth?: number
/**
* String delimiter used for concatenating multiple scopes
*/
scope_delimiter?: string
/**
* Authentication method for the token endpoint
*/
token_endpoint_auth_method?: string
/**
* Signing algorithm for the token endpoint
*/
token_endpoint_auth_signing_alg?: string
// Client Server
/**
* Where your client server can be reached
*/
origin?: string
/**
* Path prefix for the Grant internal routes
*/
prefix?: string
/**
* Random state string for OAuth 2.0
*/
state?: boolean | string
/**
* Random nonce string for OpenID Connect
*/
nonce?: boolean | string
/**
* Toggle PKCE support
*/
pkce?: boolean
/**
* Response data to receive
*/
response?: string[]
/**
* Transport type to deliver the response data
*/
transport?: string
/**
* Relative or absolute URL to receive the response data
*/
callback?: string
/**
* Static configuration overrides for a provider
*/
overrides?: {
[key: string]: Omit<GrantProvider, 'overrides'>
}
/**
* Configuration keys that can be overridden dynamically over HTTP
*/
dynamic?: boolean | string[]
// Client App
/**
* The client_id or consumer_key of your OAuth app
*/
key?: string
/**
* The client_id or consumer_key of your OAuth app
*/
client_id?: string
/**
* The client_id or consumer_key of your OAuth app
*/
consumer_key?: string
/**
* The client_secret or consumer_secret of your OAuth app
*/
secret?: string
/**
* The client_secret or consumer_secret of your OAuth app
*/
client_secret?: string
/**
* The client_secret or consumer_secret of your OAuth app
*/
consumer_secret?: string
/**
* List of scopes to request
*/
scope?: string | string[]
/**
* Custom authorization parameters and their values
*/
custom_params?: any
/**
* String to embed into the authorization server URLs
*/
subdomain?: string
/**
* Public PEM or JWK
*/
public_key?: any
/**
* Private PEM or JWK
*/
private_key?: any
/**
* Absolute redirect URL of the OAuth app
*/
redirect_uri?: string
/**
* User profile URL
*/
profile_url?: string
}
/**
* Grant session config
*/
export interface GrantSessionConfig {
/**
* Cookie name
*/
name?: string
/**
* Cookie secret
*/
secret: string
/**
* Cookie options
*/
cookie?: any
/**
* Session store
*/
store?: GrantSessionStore
}
/**
* Grant session store
*/
export interface GrantSessionStore {
/**
* Get item from session store
*/
get: (sid: string) => any
/**
* Set item in session store
*/
set: (sid: string, json: any) => void
/**
* Remove item from session store
*/
remove?: (sid: string) => void
}
// ----------------------------------------------------------------------------
/**
* Grant instance
*/
export interface GrantInstance {
/**
* Grant instance configuration
*/
config: any
}
/**
* Grant handler
*/
export type GrantHandler = (
/**
* Request object
*/
req: any,
/**
* Response object
*/
res?: any,
/**
* Grant dynamic state overrides
*/
state?: {dynamic: GrantProvider}
) => Promise<GrantHandlerResult>
/**
* Grant handler result
*/
export interface GrantHandlerResult {
/**
* Grant session store instance
*/
session: GrantSessionStore
/**
* HTTP redirect
*/
redirect?: any
/**
* Grant response
*/
response?: GrantResponse
}
// ----------------------------------------------------------------------------
/**
* Grant session
*/
export interface GrantSession {
/**
* The provider name used for this authorization
*/
provider: string
/**
* The static override name used for this authorization
*/
override?: string
/**
* The dynamic override configuration passed to this authorization
*/
dynamic?: any
/**
* OAuth 2.0 state string that was generated
*/
state?: string
/**
* OpenID Connect nonce string that was generated
*/
nonce?: string
/**
* The code verifier that was generated for PKCE
*/
code_verifier?: string
/**
* Data returned from the first request of the OAuth 1.0a flow
*/
request?: string
/**
* The final response data
*/
response?: GrantResponse
}
/**
* Grant response
*/
export interface GrantResponse {
/**
* OAuth 2.0 and OAuth 1.0a access secret
*/
access_token?: string
/**
* OAuth 2.0 refresh token
*/
refresh_token?: string
/**
* OpenID Connect id token
*/
id_token?: string
/**
* OAuth 1.0a access secret
*/
access_secret?: string
/**
* Raw response data
*/
raw?: any
/**
* Parsed id_token JWT
*/
jwt?: {
id_token?: {header: any, payload: any, signature: string}
}
/**
* User profile response
*/
profile?: any
/**
* Error response
*/
error?: any
}
// ----------------------------------------------------------------------------
/**
* Express middleware
*/
export type ExpressMiddleware = () => Promise<void>
/**
* Koa middleware
*/
export type KoaMiddleware = (ctx: any, next?: () => Promise<void>) => Promise<void>
/**
* Hapi middleware
*/
export interface HapiMiddleware {register: (server: any, options?: any) => void, pkg: any}
/**
* Fastify middleware
*/
export type FastifyMiddleware = (server: any, options: any, next: () => void) => void
/**
* Curveball middleware
*/
export type CurveballMiddleware = (ctx: any, next?: () => Promise<void>) => Promise<void>
// ----------------------------------------------------------------------------
/**
* Grant OAuth Proxy
*/
declare function grant(): (config: GrantConfig | GrantOptions) => any
declare function grant(config: GrantConfig | GrantOptions): any
/**
* Grant OAuth Proxy
*/
declare namespace grant {
/**
* Express handler
*/
function express(): (config: GrantConfig | GrantOptions) => ExpressMiddleware & GrantInstance
function express(config: GrantConfig | GrantOptions): ExpressMiddleware & GrantInstance
/**
* Koa handler
*/
function koa(): (config: GrantConfig | GrantOptions) => KoaMiddleware & GrantInstance
function koa(config: GrantConfig | GrantOptions): KoaMiddleware & GrantInstance
/**
* Hapi handler
*/
function hapi(): (config: GrantConfig | GrantOptions) => HapiMiddleware & GrantInstance
function hapi(config: GrantConfig | GrantOptions): HapiMiddleware & GrantInstance
/**
* Fastify handler
*/
function fastify(): (config: GrantConfig | GrantOptions) => FastifyMiddleware & GrantInstance
function fastify(config: GrantConfig | GrantOptions): FastifyMiddleware & GrantInstance
/**
* Curveball handler
*/
function curveball(): (config: GrantConfig | GrantOptions) => CurveballMiddleware & GrantInstance
function curveball(config: GrantConfig | GrantOptions): CurveballMiddleware & GrantInstance
/**
* Node handler
*/
function node(): (config: GrantConfig | GrantOptions) => GrantHandler & GrantInstance
function node(config: GrantConfig | GrantOptions): GrantHandler & GrantInstance
/**
* AWS Lambda handler
*/
function aws(): (config: GrantConfig | GrantOptions) => GrantHandler & GrantInstance
function aws(config: GrantConfig | GrantOptions): GrantHandler & GrantInstance
/**
* Azure Function handler
*/
function azure(): (config: GrantConfig | GrantOptions) => GrantHandler & GrantInstance
function azure(config: GrantConfig | GrantOptions): GrantHandler & GrantInstance
/**
* Google Cloud Function handler
*/
function gcloud(): (config: GrantConfig | GrantOptions) => GrantHandler & GrantInstance
function gcloud(config: GrantConfig | GrantOptions): GrantHandler & GrantInstance
/**
* Vercel Function handler
*/
function vercel(): (config: GrantConfig | GrantOptions) => GrantHandler & GrantInstance
function vercel(config: GrantConfig | GrantOptions): GrantHandler & GrantInstance
}
export default grant

139
server/node_modules/grant/grant.js generated vendored Normal file
View File

@@ -0,0 +1,139 @@
function grant ({handler, ...rest}) {
if (handler === 'express') {
return require('./lib/handler/express-4')(rest)
}
else if (handler === 'koa') {
try {
var pkg = require('koa/package.json')
}
catch (err) {}
var version = pkg ? parseInt(pkg.version.split('.')[0]) : 2
return version >= 2
? require('./lib/handler/koa-2')(rest)
: require('./lib/handler/koa-1')(rest)
}
else if (handler === 'hapi') {
try {
var pkg = require('@hapi/hapi/package.json')
}
catch (err) {
try {
var pkg = require('hapi/package.json')
}
catch (err) {}
}
var version = pkg ? parseInt(pkg.version.split('.')[0]) : 17
return version >= 17
? require('./lib/handler/hapi-17')(rest)
: require('./lib/handler/hapi-16')(rest)
}
else if (handler === 'express-4') {
return require('./lib/handler/express-4')(rest)
}
else if (handler === 'koa-2') {
return require('./lib/handler/koa-2')(rest)
}
else if (handler === 'koa-1') {
return require('./lib/handler/koa-1')(rest)
}
else if (handler === 'hapi-17') {
return require('./lib/handler/hapi-17')(rest)
}
else if (handler === 'hapi-16') {
return require('./lib/handler/hapi-16')(rest)
}
else if (handler === 'fastify') {
return require('./lib/handler/fastify')(rest)
}
else if (handler === 'curveball') {
return require('./lib/handler/curveball')(rest)
}
else if (handler === 'node') {
return require('./lib/handler/node')(rest)
}
else if (handler === 'aws') {
return require('./lib/handler/aws')(rest)
}
else if (handler === 'azure') {
return require('./lib/handler/azure')(rest)
}
else if (handler === 'gcloud') {
return require('./lib/handler/gcloud')(rest)
}
else if (handler === 'vercel') {
return require('./lib/handler/vercel')(rest)
}
}
grant.express = (options) => {
var handler = require('./lib/handler/express-4')
return options ? handler(options) : handler
}
grant.koa = (options) => {
try {
var pkg = require('koa/package.json')
}
catch (err) {}
var version = pkg ? parseInt(pkg.version.split('.')[0]) : 2
var handler = version >= 2
? require('./lib/handler/koa-2')
: require('./lib/handler/koa-1')
return options ? handler(options) : handler
}
grant.hapi = (options) => {
try {
var pkg = require('@hapi/hapi/package.json')
}
catch (err) {
try {
var pkg = require('hapi/package.json')
}
catch (err) {}
}
var version = pkg ? parseInt(pkg.version.split('.')[0]) : 17
var handler = version >= 17
? require('./lib/handler/hapi-17')
: require('./lib/handler/hapi-16')
return options ? handler(options) : handler
}
grant.fastify = (options) => {
var handler = require('./lib/handler/fastify')
return options ? handler(options) : handler
}
grant.curveball = (options) => {
var handler = require('./lib/handler/curveball')
return options ? handler(options) : handler
}
grant.node = (options) => {
var handler = require('./lib/handler/node')
return options ? handler(options) : handler
}
grant.aws = (options) => {
var handler = require('./lib/handler/aws')
return options ? handler(options) : handler
}
grant.azure = (options) => {
var handler = require('./lib/handler/azure')
return options ? handler(options) : handler
}
grant.gcloud = (options) => {
var handler = require('./lib/handler/gcloud')
return options ? handler(options) : handler
}
grant.vercel = (options) => {
var handler = require('./lib/handler/vercel')
return options ? handler(options) : handler
}
grant.default = grant
module.exports = grant

62
server/node_modules/grant/lib/client.js generated vendored Normal file
View File

@@ -0,0 +1,62 @@
var compose = require('request-compose')
var oauth = require('request-oauth')
var qs = require('qs')
var pkg = require('../package')
var defaults = (args) => () => {
var {options} = compose.Request.defaults(args)()
options.headers['user-agent'] = `simov/grant/${pkg.version}`
return {options}
}
var parse = () => ({options, res, res: {headers}, body, raw}) => {
raw = body
var header = Object.keys(headers)
.find((name) => name.toLowerCase() === 'content-type')
if (/json|javascript/.test(headers[header])) {
try {
body = JSON.parse(body)
}
catch (err) {}
}
else if (/application\/x-www-form-urlencoded/.test(headers[header])) {
try {
body = qs.parse(body) // use qs instead of querystring for nested objects
}
catch (err) {}
}
// some providers return incorrect content-type like text/html or text/plain
else {
try {
body = JSON.parse(body)
}
catch (err) {
body = qs.parse(body) // use qs instead of querystring for nested objects
}
}
log({parse: {res, body}})
return {options, res, body, raw}
}
var log = (data) => {
if (process.env.DEBUG) {
try {
require('request-logs')(data)
}
catch (err) {}
}
}
module.exports = compose.extend({
Request: {defaults, oauth},
Response: {parse}
}).client

220
server/node_modules/grant/lib/config.js generated vendored Normal file
View File

@@ -0,0 +1,220 @@
var crypto = require('crypto')
var oauth = require('../config/oauth.json')
var reserved = require('../config/reserved.json')
var profile = require('../config/profile.json')
var compose = (...fns) =>
fns.reduce((x, y) => (...args) => y(x(...args)))
var dcopy = (obj) =>
JSON.parse(JSON.stringify(obj))
var merge = (...args) =>
Object.assign(...args.filter(Boolean).map(dcopy))
var filter = (obj) => Object.keys(obj)
.filter((key) =>
// empty string
obj[key] !== '' && (
// provider name
key === obj.name ||
// reserved key
reserved.includes(key)
))
.reduce((all, key) => (all[key] = obj[key], all), {})
var format = {
oauth: ({oauth}) =>
parseInt(oauth) || undefined
,
key: ({oauth, key, consumer_key, client_id}) =>
oauth === 1
? key || consumer_key
: oauth === 2
? key || client_id
: undefined
,
secret: ({oauth, secret, consumer_secret, client_secret}) =>
oauth === 1
? secret || consumer_secret
: oauth === 2
? secret || client_secret
: undefined
,
scope: ({scope, scope_delimiter = ','}) =>
scope instanceof Array
? scope.filter(Boolean).join(scope_delimiter) || undefined
: typeof scope === 'object'
? JSON.stringify(scope)
: scope || undefined
,
state: ({state}) =>
state || undefined
,
nonce: ({nonce}) =>
nonce || undefined
,
redirect_uri: ({redirect_uri, origin, prefix, protocol, host, name}) =>
redirect_uri
? redirect_uri
: origin
? `${origin}${prefix}/${name}/callback`
: protocol && host
? `${protocol}://${host}${prefix}/${name}/callback`
: undefined
,
custom_params: (provider) => {
var params = provider.custom_params || {}
// remove falsy
params = Object.keys(params)
.filter((key) => params[key])
.reduce((all, key) => (all[key] = params[key], all), {})
return Object.keys(params).length ? params : undefined
},
overrides: (provider) => {
var overrides = provider.overrides || {}
delete provider.overrides
// remove nested
Object.keys(overrides).forEach((name) => {
overrides[name] = Object.keys(overrides[name])
.filter((key) => key !== 'overrides')
.reduce((all, key) => (all[key] = overrides[name][key], all), {})
})
overrides = Object.keys(overrides)
.reduce((all, key) => (all[key] = init(provider, overrides[key]), all), {})
return Object.keys(overrides).length ? overrides : undefined
},
}
var state = (provider, key = 'state', value = provider[key]) =>
value === true || value === 'true'
? crypto.randomBytes(20).toString('hex')
: value === 'false'
? undefined
: /string|number/.test(typeof value)
? value.toString()
: undefined
var pkce = (code_verifier = crypto.randomBytes(40).toString('hex')) => ({
code_verifier,
code_challenge: crypto.createHash('sha256')
.update(code_verifier).digest().toString('base64')
.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_')
})
var transform = (provider) => {
Object.keys(format)
.forEach((key) => provider[key] = format[key](provider))
// filter undefined
return dcopy(provider)
}
var init = compose(merge, filter, transform)
var compat = (config) =>
config.fitbit2 ? (Object.assign({}, config, {fitbit2: Object.assign({}, oauth.fitbit, profile.fitbit, config.fitbit2)})) :
config.linkedin2 ? (Object.assign({}, config, {linkedin2: Object.assign({}, oauth.linkedin, profile.linkedin, config.linkedin2)})) :
config.zeit ? (Object.assign({}, config, {zeit: Object.assign({}, oauth.vercel, profile.vercel, config.zeit)})) :
config
var defaults = ({path, prefix = '/connect', ...rest} = {}) => ({
...rest,
prefix: path ? `${path}${prefix}` : prefix
})
// init all configured providers
var ctor = ((_defaults) => (config = {}, defaults = _defaults(config.defaults)) =>
Object.keys(compat(config))
.filter((name) => !/defaults/.test(name))
.reduce((all, name) => (
all[name] = init(oauth[name], profile[name], defaults, config[name], {name, [name]: true}),
all
), {defaults})
)(defaults)
// get provider on connect
var provider = (config, session, _state = {}) => {
var name = session.provider
var provider = config[name]
if (!provider) {
if ((config.defaults || {}).dynamic !== true) {
return {}
}
provider = init(oauth[name], profile[name], config.defaults, {name, [name]: true})
}
if (session.override && provider.overrides) {
var override = provider.overrides[session.override]
if (override) {
provider = override
}
}
if ((session.dynamic && provider.dynamic) || _state.dynamic) {
var dynamic = Object.assign(
{},
_state.dynamic,
provider.dynamic === true
? session.dynamic
: Object.keys(session.dynamic || {})
.filter((key) => provider.dynamic.includes(key))
.reduce((all, key) => (all[key] = session.dynamic[key], all), {})
)
provider = init(provider, dynamic)
}
if (provider.state) {
provider = dcopy(provider)
provider.state = state(provider)
}
if (provider.nonce) {
provider = dcopy(provider)
provider.nonce = state(provider, 'nonce')
}
if (provider.pkce) {
provider = dcopy(provider)
;({
code_verifier: provider.code_verifier,
code_challenge: provider.code_challenge
} = pkce())
}
return provider
}
module.exports = Object.assign(ctor, {
compose, dcopy, merge, filter, format, state, pkce, transform, init, defaults, compat, provider
})

145
server/node_modules/grant/lib/flow/oauth1.js generated vendored Normal file
View File

@@ -0,0 +1,145 @@
var qs = require('qs')
var request = require('../client')
exports.request = ({request:client}) => async ({provider, input}) => {
var options = {
method: 'POST',
url: provider.request_url,
oauth: {
callback: provider.redirect_uri,
consumer_key: provider.key,
consumer_secret: provider.secret
}
}
if (provider.private_key) {
options.oauth.signature_method = 'RSA-SHA1'
options.oauth.private_key = provider.private_key
delete options.oauth.consumer_secret
}
if (provider.etsy || provider.linkedin) {
options.qs = {scope: provider.scope}
}
if (provider.getpocket) {
delete options.oauth
options.headers = {
'x-accept': 'application/x-www-form-urlencoded'
}
options.form = {
consumer_key: provider.key,
redirect_uri: provider.redirect_uri,
state: provider.state
}
}
if (provider.freshbooks) {
options.oauth.signature_method = 'PLAINTEXT'
}
if (provider.twitter) {
if (provider.scope) {
options.qs = {x_auth_access_type: [].concat(provider.scope).join()}
}
if (provider.custom_params) {
options.qs = {x_auth_access_type: provider.custom_params.x_auth_access_type}
}
}
if (provider.subdomain) {
options.url = options.url.replace('[subdomain]', provider.subdomain)
}
try {
var {body:output} = await request({...client, ...options})
if (provider.sellsy) {
output = qs.parse(output)
}
}
catch (err) {
var output = {error: err.body || err.message}
}
return {provider, input, output}
}
exports.authorize = async ({provider, input, output}) => {
if (!output.oauth_token && !output.code) {
output = Object.keys(output).length
? output : {error: 'Grant: OAuth1 missing oauth_token parameter'}
return {provider, input, output}
}
var url = provider.authorize_url
var params = {
oauth_token: output.oauth_token
}
if (provider.custom_params) {
for (var key in provider.custom_params) {
params[key] = provider.custom_params[key]
}
}
if (provider.flickr && provider.scope) {
params.perms = provider.scope
}
if (provider.getpocket) {
params = {
request_token: output.code,
redirect_uri: provider.redirect_uri
}
}
if (provider.ravelry || provider.trello) {
params.scope = provider.scope
}
if (provider.tripit) {
params.oauth_callback = provider.redirect_uri
}
if (provider.subdomain) {
url = url.replace('[subdomain]', provider.subdomain)
}
return {provider, input, output: `${url}?${qs.stringify(params)}`}
}
exports.access = ({request:client}) => async ({provider, input, input:{session, query}}) => {
if (!query.oauth_token && !session.request.code) {
var output = Object.keys(query).length
? query : {error: 'Grant: OAuth1 missing oauth_token parameter'}
return {provider, input, output}
}
var options = {
method: 'POST',
url: provider.access_url,
oauth: {
consumer_key: provider.key,
consumer_secret: provider.secret,
token: query.oauth_token,
token_secret: session.request.oauth_token_secret,
verifier: query.oauth_verifier
}
}
if (provider.private_key) {
options.oauth.signature_method = 'RSA-SHA1'
options.oauth.private_key = provider.private_key
delete options.oauth.consumer_secret
}
if (provider.freshbooks) {
options.oauth.signature_method = 'PLAINTEXT'
}
if (provider.getpocket) {
delete options.oauth
options.headers = {
'x-accept': 'application/x-www-form-urlencoded'
}
options.form = {
consumer_key: provider.key,
code: session.request.code
}
}
if (provider.goodreads || provider.tripit) {
delete options.oauth.verifier
}
if (provider.subdomain) {
options.url = options.url.replace('[subdomain]', provider.subdomain)
}
try {
var {body:output} = await request({...client, ...options})
}
catch (err) {
var output = {error: err.body || err.message}
}
return {provider, input, output}
}

220
server/node_modules/grant/lib/flow/oauth2.js generated vendored Normal file
View File

@@ -0,0 +1,220 @@
var crypto = require('crypto')
var qs = require('qs')
var request = require('../client')
exports.authorize = async ({provider, input}) => {
var url = provider.authorize_url
var params = {
client_id: provider.key,
response_type: 'code',
redirect_uri: provider.redirect_uri,
scope: provider.scope,
state: provider.state,
nonce: provider.nonce
}
if (provider.pkce) {
params.code_challenge_method = 'S256'
params.code_challenge = provider.code_challenge
}
if (provider.custom_params) {
for (var key in provider.custom_params) {
params[key] = provider.custom_params[key]
}
}
if (provider.basecamp) {
params.type = 'web_server'
}
if (provider.freelancer && params.scope) {
params.advanced_scopes = params.scope
delete params.scope
}
if (provider.instagram && /^\d+$/.test(provider.key)) {
params.app_id = params.client_id
delete params.client_id
params.scope = (params.scope || '').replace(/ /g, ',') || undefined
}
if (provider.optimizely && params.scope) {
params.scopes = params.scope
delete params.scope
}
if (provider.tiktok) {
params.client_key = params.client_id
delete params.client_id
}
if (provider.visualstudio) {
params.response_type = 'Assertion'
}
if (provider.wechat) {
params.appid = params.client_id
delete params.client_id
}
if (provider.subdomain) {
url = url.replace('[subdomain]', provider.subdomain)
}
var querystring = qs.stringify(params)
if (provider.unsplash && params.scope) {
var scope = params.scope
delete params.scope
querystring = qs.stringify(params) + '&scope=' + scope
}
return {provider, input, output: `${url}?${querystring}`}
}
exports.access = ({request:client}) => async ({provider, input, input:{query, body, session}}) => {
query = Object.keys(query).length ? query : body
if (!query.code) {
var output = Object.keys(query).length
? query : {error: 'Grant: OAuth2 missing code parameter'}
return {provider, input, output}
}
else if (session.state && (query.state !== session.state)) {
var output = {error: 'Grant: OAuth2 state mismatch'}
return {provider, input, output}
}
var options = {
method: 'POST',
url: provider.access_url,
form: {
grant_type: 'authorization_code',
code: query.code,
client_id: provider.key,
client_secret: provider.secret,
redirect_uri: provider.redirect_uri
}
}
if (provider.pkce) {
options.form.code_verifier = session.code_verifier
}
if (provider.basecamp) {
options.form.type = 'web_server'
}
if (provider.concur) {
delete options.form
options.qs = {
code: query.code,
client_id: provider.key,
client_secret: provider.secret
}
}
if (/autodesk|ebay|fitbit|homeaway|hootsuite|notion|reddit|trustpilot/.test(provider.name)
|| provider.token_endpoint_auth_method === 'client_secret_basic'
) {
delete options.form.client_id
delete options.form.client_secret
options.auth = {user: provider.key, pass: provider.secret}
}
if (/twitter/.test(provider.name)) {
options.form.client_id = provider.key
delete options.form.client_secret
options.auth = {user: provider.key, pass: provider.secret}
}
if (provider.token_endpoint_auth_method === 'private_key_jwt') {
var jwt = ({kid, x5t, secret}) => ({
header: {
typ: 'JWT',
alg: provider.token_endpoint_auth_signing_alg || 'RS256',
kid,
x5t
},
payload: {
iss: provider.key,
sub: provider.key,
aud: provider.access_url,
jti: crypto.randomBytes(20).toString('hex'),
exp: Math.round(Date.now() / 1000) + 300,
iat: Math.round(Date.now() / 1000) - 120,
nbf: Math.round(Date.now() / 1000) - 120
},
secret
})
var assertion = (() => {
var oidc = require('../oidc')
var {public_key, private_key} = provider
return oidc.sign(jwt({
kid: private_key.kty ? oidc.kid(private_key) : undefined,
x5t: public_key ? public_key.kty ? public_key.x5t : oidc.x5t(public_key) : undefined,
secret: private_key.kty ? oidc.pem(private_key) : private_key,
}))
})()
options.form.client_assertion_type = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
options.form.client_assertion = assertion
delete options.form.client_id
delete options.form.client_secret
}
if (provider.instagram && /^\d+$/.test(provider.key)) {
options.form.app_id = options.form.client_id
delete options.form.client_id
options.form.app_secret = options.form.client_secret
delete options.form.client_secret
}
if (provider.notion) {
options.json = options.form
delete options.form
}
if (provider.tiktok) {
options.form.client_key = options.form.client_id
delete options.form.client_id
}
if (provider.qq) {
options.method = 'GET'
options.qs = options.form
delete options.form
}
if (provider.untappd) {
options.method = 'GET'
options.qs = options.form
delete options.qs.grant_type
options.qs.response_type = 'code'
delete options.form
}
if (provider.wechat) {
options.method = 'GET'
options.qs = options.form
delete options.form
options.qs.appid = options.qs.client_id
options.qs.secret = options.qs.client_secret
delete options.qs.client_id
delete options.qs.client_secret
}
if (provider.smartsheet) {
delete options.form.client_secret
var hash = crypto.createHash('sha256')
hash.update(provider.secret + '|' + query.code)
options.form.hash = hash.digest('hex')
}
if (provider.surveymonkey) {
options.qs = {api_key: provider.custom_params.api_key}
}
if (provider.visualstudio) {
options.form = {
client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
client_assertion: provider.secret,
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: query.code,
redirect_uri: provider.redirect_uri
}
}
if (provider.withings) {
options.form.action = 'requesttoken'
}
if (provider.subdomain) {
options.url = options.url.replace('[subdomain]', provider.subdomain)
}
try {
var {body:output} = await request({...client, ...options})
if (provider.intuit) {
output.realmId = query.realmId
}
if (provider.withings) {
output = output.body
}
}
catch (err) {
var output = {error: err.body || err.message}
}
return {provider, input, output}
}

31
server/node_modules/grant/lib/grant.js generated vendored Normal file
View File

@@ -0,0 +1,31 @@
var {compose} = require('./util')
var {defaults, connect, callback} = require('./request')
var {data, transport} = require('./response')
var _config = require('./config')
module.exports = ({config, request, state, extend}) => {
config = _config(config)
if (!extend) {
extend = [require('./profile')]
}
var pipe = compose(
defaults(config),
({provider, input, input:{params}}) => params.override !== 'callback'
? connect({request})({provider, input})
: compose(
callback({request})({provider, input}),
data,
extend ? compose(...extend.map((fn) => fn({request, state}))) : (args) => ({...args})
)({provider, input}),
transport,
)
pipe.config = config
return pipe
}

89
server/node_modules/grant/lib/handler/aws.js generated vendored Normal file
View File

@@ -0,0 +1,89 @@
var qs = require('qs')
var Grant = require('../grant')
var Session = require('../session')
module.exports = function (args = {}) {
var grant = Grant(args.config ? args : {config: args})
app.config = grant.config
var regex = new RegExp([
'^',
app.config.defaults.prefix,
/(?:\/([^\/\?]+?))/.source, // /:provider
/(?:\/([^\/\?]+?))?/.source, // /:override?
/(?:\/$|\/?\?+.*)?$/.source, // querystring
].join(''), 'i')
var store = Session(args.session)
async function app (event, state) {
var req = params(event)
var session = store(req)
var match = regex.exec(req.path)
if (!match) {
return {session}
}
var {location, session:sess, state} = await grant({
method: req.method,
params: {provider: match[1], override: match[2]},
query: req.query,
body: req.body,
state,
session: (await session.get()).grant
})
await session.set({grant: sess})
return location
? {session, redirect: redirect(event, location, session)}
: {session, response: state.response || sess.response}
}
return app
}
var path = ({version, path, rawPath, requestContext:ctx} = event) =>
version === '2.0' ? rawPath :
version === '1.0' ? path : ctx.path
var body = ({body, isBase64Encoded} = event) =>
body
? isBase64Encoded ? Buffer.from(body, 'base64').toString()
: body : {}
var params = (event) =>
!event.version || event.version === '1.0' ?
{
method: event.httpMethod,
path: path(event),
query: qs.parse(event.queryStringParameters),
headers: event.headers,
body: qs.parse(body(event)),
}
: event.version === '2.0' ?
{
method: event.requestContext.http.method,
path: path(event),
query: qs.parse(event.rawQueryString),
headers: {...event.headers, Cookie: (event.cookies || []).join('; ')},
body: qs.parse(body(event)),
}
: {}
var redirect = (event, location, session) =>
!event.version || event.version === '1.0' ?
{
statusCode: 302,
headers: {location},
multiValueHeaders: {'set-cookie': session.headers['set-cookie']}
}
: event.version === '2.0' ?
{
statusCode: 302,
headers: {location},
cookies: session.headers['set-cookie']
}
: {}

53
server/node_modules/grant/lib/handler/azure.js generated vendored Normal file
View File

@@ -0,0 +1,53 @@
var qs = require('qs')
var Grant = require('../grant')
var Session = require('../session')
module.exports = function (args = {}) {
var grant = Grant(args.config ? args : {config: args})
app.config = grant.config
var regex = new RegExp([
/^https?:\/\/[^/]+/.source,
app.config.defaults.prefix,
/(?:\/([^\/\?]+?))/.source, // /:provider
/(?:\/([^\/\?]+?))?/.source, // /:override?
/(?:\/$|\/?\?+.*)?$/.source, // querystring
].join(''), 'i')
var store = Session(args.session)
async function app (req, state) {
var session = store(req)
var match = regex.exec(req.originalUrl)
if (!match) {
return {session}
}
var {location, session:sess, state} = await grant({
method: req.method,
params: {provider: match[1], override: match[2]},
query: {...req.query, code: req.query.oauth_code},
body: req.method === 'POST' ? req.body : {},
state,
session: (await session.get()).grant
})
await session.set({grant: sess})
return location
? {session, redirect: redirect(location, session)}
: {session, response: state.response || sess.response}
}
return app
}
var redirect = (location, session) => ({
status: 302,
headers: {
location,
'set-cookie': session.headers['set-cookie']
}
})

46
server/node_modules/grant/lib/handler/curveball.js generated vendored Normal file
View File

@@ -0,0 +1,46 @@
var qs = require('qs')
var Grant = require('../grant')
module.exports = function (args = {}) {
var grant = Grant(args.config ? args : {config: args})
app.config = grant.config
var regex = new RegExp([
'^',
app.config.defaults.prefix,
/(?:\/([^\/\?]+?))/.source, // /:provider
/(?:\/([^\/\?]+?))?/.source, // /:override?
/(?:\/$|\/?\?+.*)?$/.source, // querystring
].join(''), 'i')
async function app (ctx, next) {
var match = regex.exec(ctx.path)
if (!match) {
return next()
}
if (!ctx.state.session) {
throw new Error('Grant: mount session middleware first')
}
if (ctx.method === 'POST' && !ctx.request.body) {
throw new Error('Grant: mount body parser middleware first')
}
var {location, session, state} = await grant({
method: ctx.method,
params: {provider: match[1], override: match[2]},
query: qs.parse(ctx.request.query),
body: qs.parse(ctx.request.body),
state: ctx.state.grant,
session: ctx.state.session.grant,
})
ctx.state.session.grant = session
ctx.state.grant = state
location ? ctx.response.redirect(302, location) : await next()
}
return app
}

53
server/node_modules/grant/lib/handler/express-4.js generated vendored Normal file
View File

@@ -0,0 +1,53 @@
var Grant = require('../grant')
module.exports = function (args = {}) {
var grant = Grant(args.config ? args : {config: args})
app.config = grant.config
var regex = new RegExp([
'^',
app.config.defaults.prefix,
/(?:\/([^\/\?]+?))/.source, // /:provider
/(?:\/([^\/\?]+?))?/.source, // /:override?
/(?:\/$|\/?\?+.*)?$/.source, // querystring
].join(''), 'i')
async function app (req, res, next) {
var match = regex.exec(req.originalUrl)
if (!match) {
return next()
}
if (!req.session) {
next(new Error('Grant: mount session middleware first'))
return
}
if (req.method === 'POST' && !req.body) {
next(new Error('Grant: mount body parser middleware first'))
return
}
var {location, session, state} = await grant({
method: req.method,
params: {provider: match[1], override: match[2]},
query: req.query,
body: req.body,
state: res.locals.grant,
session: req.session.grant,
})
req.session.grant = session
res.locals.grant = state
location ? redirect(req, res, location) : next()
}
return app
}
var redirect = (req, res, location) =>
typeof req.session.save === 'function' &&
Object.getPrototypeOf(req.session).save.length
? req.session.save(() => res.redirect(location))
: res.redirect(location)

50
server/node_modules/grant/lib/handler/fastify.js generated vendored Normal file
View File

@@ -0,0 +1,50 @@
var qs = require('qs')
var Grant = require('../grant')
module.exports = function (args = {}) {
function app (server, options, next) {
args = args.config ? args : {config: args}
var grant = Grant(args)
app.config = grant.config
var prefix = app.config.defaults.prefix.replace(options.prefix, '')
server.route({
method: ['GET', 'POST'],
path: `${prefix}/:provider`,
handler
})
server.route({
method: ['GET', 'POST'],
path: `${prefix}/:provider/:override`,
handler
})
async function handler (req, res) {
if (!req.session) {
throw new Error('Grant: register session plugin first')
}
var {location, session, state} = await grant({
method: req.method,
params: req.params,
query: qs.parse(req.query),
body: qs.parse(req.body),
state: req.grant,
session: req.session.grant,
})
req.session.grant = session
res.grant = state
return location ? res.redirect(location) : res.send()
}
next()
}
return app
}

56
server/node_modules/grant/lib/handler/gcloud.js generated vendored Normal file
View File

@@ -0,0 +1,56 @@
var qs = require('qs')
var Grant = require('../grant')
var Session = require('../session')
module.exports = function (args = {}) {
var grant = Grant(args.config ? args : {config: args})
app.config = grant.config
var regex = new RegExp([
'^',
app.config.defaults.prefix,
/(?:\/([^\/\?]+?))/.source, // /:provider
/(?:\/([^\/\?]+?))?/.source, // /:override?
/(?:\/$|\/?\?+.*)?$/.source, // querystring
].join(''), 'i')
var store = Session(args.session)
async function app (req, res, state) {
var session = store(req, res)
var match = regex.exec(req.url)
if (!match) {
return {session}
}
var {location, session:sess, state} = await grant({
method: req.method,
params: {provider: match[1], override: match[2]},
query: qs.parse(req.query),
body: req.body,
state,
session: (await session.get()).grant
})
await session.set({grant: sess})
return location
? (redirect(res, location, session), {session, redirect: true})
: {session, response: state.response || sess.response}
}
return app
}
var redirect = (res, location, session) => {
res.setHeader('set-cookie', session.headers['set-cookie'])
setImmediate(() => {
if (!res.headersSent) {
res.statusCode = 302
res.setHeader('location', location)
res.end()
}
})
}

60
server/node_modules/grant/lib/handler/hapi-16.js generated vendored Normal file
View File

@@ -0,0 +1,60 @@
var url = require('url')
var qs = require('qs')
var Grant = require('../grant')
module.exports = function (args = {}) {
var app = {}
function register (server, options, next) {
args = args.config ? args : {config: args}
args.config = Object.keys(options).length ? options : args.config
var grant = Grant(args)
app.config = grant.config
var prefix = app.config.defaults.prefix
.replace(server.realm.modifiers.route.prefix, '')
server.route({
method: ['GET', 'POST'],
path: `${prefix}/{provider}/{override?}`,
handler: (req, res) => {
if (!(req.session || req.yar)) {
throw new Error('Grant: register session plugin first')
}
var query = (parseInt(server.version.split('.')[0]) >= 12)
? qs.parse(url.parse(req.url, false).query) // #2985
: req.query
var body = (parseInt(server.version.split('.')[0]) >= 12)
? qs.parse(req.payload) // #2985
: req.payload
grant({
method: req.method,
params: req.params,
query: query,
body: body,
state: req.plugins.grant,
session: (req.session || req.yar).get('grant'),
}).then(({location, session, state}) => {
;(req.session || req.yar).set('grant', session)
req.plugins.grant = state
location ? res.redirect(location) : res.continue()
})
}
})
next()
}
register.attributes = {
pkg: require('../../package.json')
}
app.register = register
return app
}

47
server/node_modules/grant/lib/handler/hapi-17.js generated vendored Normal file
View File

@@ -0,0 +1,47 @@
var qs = require('qs')
var Grant = require('../grant')
module.exports = function (args = {}) {
var app = {}
function register (server, options) {
args = args.config ? args : {config: args}
args.config = Object.keys(options).length ? options : args.config
var grant = Grant(args)
app.config = grant.config
var prefix = app.config.defaults.prefix
.replace(server.realm.modifiers.route.prefix, '')
server.route({
method: ['GET', 'POST'],
path: `${prefix}/{provider}/{override?}`,
handler: async (req, res) => {
if (!req.yar) {
throw new Error('Grant: register session plugin first')
}
var {location, session, state} = await grant({
method: req.method,
params: req.params,
query: qs.parse(req.query),
body: qs.parse(req.payload), // #2985
state: req.plugins.grant,
session: req.yar.get('grant'),
})
req.yar.set('grant', session)
req.plugins.grant = state
return location ? res.redirect(location) : res.continue
}
})
}
app.pkg = require('../../package.json')
app.register = register
return app
}

46
server/node_modules/grant/lib/handler/koa-1.js generated vendored Normal file
View File

@@ -0,0 +1,46 @@
var qs = require('qs')
var Grant = require('../grant')
module.exports = function (args) {
var grant = Grant((args || {}).config ? args : {config: args})
app.config = grant.config
var regex = new RegExp([
'^',
app.config.defaults.prefix,
/(?:\/([^\/\?]+?))/.source, // /:provider
/(?:\/([^\/\?]+?))?/.source, // /:override?
/(?:\/$|\/?\?+.*)?$/.source, // querystring
].join(''), 'i')
function* app (next) {
var match = regex.exec(this.request.originalUrl)
if (!match) {
return yield next
}
if (!this.session) {
throw new Error('Grant: mount session middleware first')
}
if (this.method === 'POST' && !this.request.body) {
throw new Error('Grant: mount body parser middleware first')
}
var result = yield grant({
method: this.method,
params: {provider: match[1], override: match[2]},
query: qs.parse(this.request.query),
body: this.request.body,
state: this.state.grant,
session: this.session.grant,
})
this.session.grant = result.session
this.state.grant = result.state
result.location ? this.response.redirect(result.location) : yield next
}
return app
}

46
server/node_modules/grant/lib/handler/koa-2.js generated vendored Normal file
View File

@@ -0,0 +1,46 @@
var qs = require('qs')
var Grant = require('../grant')
module.exports = function (args = {}) {
var grant = Grant(args.config ? args : {config: args})
app.config = grant.config
var regex = new RegExp([
'^',
app.config.defaults.prefix,
/(?:\/([^\/\?]+?))/.source, // /:provider
/(?:\/([^\/\?]+?))?/.source, // /:override?
/(?:\/$|\/?\?+.*)?$/.source, // querystring
].join(''), 'i')
async function app (ctx, next) {
var match = regex.exec(ctx.originalUrl)
if (!match) {
return next()
}
if (!ctx.session) {
ctx.throw(400, 'Grant: mount session middleware first')
}
if (ctx.method === 'POST' && !ctx.request.body) {
ctx.throw(400, 'Grant: mount body parser middleware first')
}
var {location, session, state} = await grant({
method: ctx.method,
params: {provider: match[1], override: match[2]},
query: qs.parse(ctx.request.query),
body: ctx.request.body,
state: ctx.state.grant,
session: ctx.session.grant,
})
ctx.session.grant = session
ctx.state.grant = state
location ? ctx.response.redirect(location) : await next()
}
return app
}

62
server/node_modules/grant/lib/handler/node.js generated vendored Normal file
View File

@@ -0,0 +1,62 @@
var qs = require('qs')
var Grant = require('../grant')
var Session = require('../session')
module.exports = function (args = {}) {
var grant = Grant(args.config ? args : {config: args})
app.config = grant.config
var regex = new RegExp([
'^',
app.config.defaults.prefix,
/(?:\/([^\/\?]+?))/.source, // /:provider
/(?:\/([^\/\?]+?))?/.source, // /:override?
/(?:\/$|\/?\?+(.*))?$/.source, // querystring
].join(''), 'i')
var store = Session(args.session)
async function app (req, res, state) {
var session = store(req, res)
var match = regex.exec(req.url)
if (!match) {
return {session}
}
var {location, session:sess, state} = await grant({
method: req.method,
params: {provider: match[1], override: match[2]},
query: qs.parse(match[3]),
body: req.method === 'POST' ? qs.parse(await buffer(req)) : {},
state,
session: (await session.get()).grant
})
await session.set({grant: sess})
return location
? (redirect(res, location, session), {session, redirect: true})
: {session, response: state.response || sess.response}
}
return app
}
var redirect = (res, location, session) => {
res.setHeader('set-cookie', session.headers['set-cookie'])
setImmediate(() => {
if (!res.headersSent) {
res.statusCode = 302
res.setHeader('location', location)
res.end()
}
})
}
var buffer = (req, body = []) => new Promise((resolve, reject) => req
.on('data', (chunk) => body.push(chunk))
.on('end', () => resolve(Buffer.concat(body).toString('utf8')))
.on('error', reject)
)

56
server/node_modules/grant/lib/handler/vercel.js generated vendored Normal file
View File

@@ -0,0 +1,56 @@
var qs = require('qs')
var Grant = require('../grant')
var Session = require('../session')
module.exports = function (args = {}) {
var grant = Grant(args.config ? args : {config: args})
app.config = grant.config
var regex = new RegExp([
'^',
app.config.defaults.prefix,
/(?:\/([^\/\?]+?))/.source, // /:provider
/(?:\/([^\/\?]+?))?/.source, // /:override?
/(?:\/$|\/?\?+.*)?$/.source, // querystring
].join(''), 'i')
var store = Session(args.session)
async function app (req, res, state) {
var session = store(req, res)
var match = regex.exec(req.url)
if (!match) {
return {session}
}
var {location, session:sess, state} = await grant({
method: req.method,
params: {provider: match[1], override: match[2]},
query: qs.parse(req.query),
body: req.body,
state,
session: (await session.get()).grant
})
await session.set({grant: sess})
return location
? (redirect(res, location, session), {session, redirect: true})
: {session, response: state.response || sess.response}
}
return app
}
var redirect = (res, location, session) => {
res.setHeader('set-cookie', session.headers['set-cookie'])
setImmediate(() => {
if (!res.headersSent) {
res.statusCode = 302
res.setHeader('location', location)
res.end()
}
})
}

47
server/node_modules/grant/lib/oidc.js generated vendored Normal file
View File

@@ -0,0 +1,47 @@
var crypto = require('crypto')
var base64url = (str) =>
str.toString('base64').replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_')
var kid = (jwk) => {
if (jwk.kid) {
return jwk.kid
}
var keys =
jwk.kty === 'RSA' ? {e: jwk.e, kty: jwk.kty, n: jwk.n} :
jwk.kty === 'EC' ? {crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y} :
jwk.kty === 'oct' ? {k: jwk.k, kty: jwk.kty} : undefined
return keys
? base64url(crypto.createHash('sha256').update(JSON.stringify(keys)).digest())
: undefined
}
var x5t = (cert) => {
var s1 = cert.replace(/(?:-----(?:BEGIN|END) CERTIFICATE-----|\s)/g, '')
var s2 = Buffer.from(s1, 'base64')
var s3 = crypto.createHash('sha1').update(s2).digest('hex').toUpperCase()
return base64url(Buffer.from(s3, 'hex'))
}
var pem = (jwk) => {
var pem = require('jwk-to-pem')
return pem(jwk, {private: true})
}
var sign = (jwt) => {
var jws = require('jws')
return jws.sign(jwt)
}
var jwt = (str) => {
var [header, payload, signature] = str.split('.')
return {
header: JSON.parse(Buffer.from(header, 'base64').toString('binary')),
payload: JSON.parse(Buffer.from(payload, 'base64').toString('utf8')),
signature,
}
}
module.exports = {base64url, kid, x5t, pem, sign, jwt}

102
server/node_modules/grant/lib/profile.js generated vendored Normal file
View File

@@ -0,0 +1,102 @@
var request = require('./client')
module.exports = ({request:client}) => async ({provider, input, output}) => {
if (!provider.response || !provider.response.includes('profile')) {
return {provider, input, output}
}
if (provider.apple && !provider.profile_url && input.body.user) {
output.profile = input.body.user
return {provider, input, output}
}
if (!provider.profile_url) {
output.profile = {error: 'Grant: No profile URL found!'}
return {provider, input, output}
}
var options = {
method: 'GET',
url: provider.profile_url,
headers: {},
}
if (provider.oauth === 2) {
options.headers.authorization = `Bearer ${output.access_token}`
}
else if (provider.oauth === 1) {
options.oauth = {
consumer_key: provider.key,
consumer_secret: provider.secret,
token: output.access_token,
token_secret: output.access_secret,
}
}
if (custom[provider.name]) {
Object.assign(options, custom[provider.name]({provider, output}))
}
if (provider.subdomain) {
options.url = options.url.replace('[subdomain]', provider.subdomain)
}
try {
var {body} = await request({...client, ...options})
// JSONP
if (provider.flickr) {
body = JSON.parse(/^.*\((.*)\)/.exec(body)[1])
}
// JSONP + secondary request
if (provider.qq) {
body = JSON.parse(/^.*\((.*)\)/.exec(Object.keys(body)[0])[1])
body = {...body, ...(await request({...client, ...options,
url: 'https://graph.qq.com/user/get_user_info',
qs: {
access_token: output.access_token,
oauth_consumer_key: provider.key,
openid: body.openid
}
})).body}
}
output.profile = body
}
catch (err) {
output.profile = {error: err.body || err.message}
}
return {provider, input, output}
}
var custom = {
arcgis: () => ({qs: {f: 'json'}}),
baidu: ({output}) => ({qs: {access_token: output.access_token}}),
constantcontact: ({provider}) => ({qs: {api_key: provider.key}}),
deezer: ({output}) => ({qs: {access_token: output.access_token}}),
disqus: ({provider}) => ({qs: {api_key: provider.key}}),
dropbox: () => ({method: 'POST'}),
echosign: ({output}) => ({headers: {'Access-Token': output.access_token}}),
flickr: ({provider}) => ({qs: {method: 'flickr.urls.getUserProfile', api_key: provider.key, format: 'json'}}),
foursquare: ({output}) => ({qs: {oauth_token: output.access_token}}),
getpocket: ({provider, output}) => ({json: {consumer_key: provider.key, access_token: output.access_token}}),
instagram: ({provider, output}) => /^\d+$/.test(provider.key) ? {qs: {fields: 'id,account_type,username'}} : {url: 'https://api.instagram.com/v1/users/self', qs: {access_token: output.access_token}},
mailchimp: ({output}) => ({qs: {apikey: output.access_token}}),
meetup: ({output}) => ({qs: {member_id: 'self'}}),
mixcloud: ({output}) => ({qs: {access_token: output.access_token}}),
qq: ({output}) => ({qs: {access_token: output.access_token}}),
shopify: ({output}) => ({headers: {'X-Shopify-Access-Token': output.access_token}}),
slack: ({output}) => ({qs: {token: output.access_token}}),
soundcloud: ({output}) => ({qs: {oauth_token: output.access_token}}),
stackexchange: ({output}) => ({qs: {key: output.access_token}}),
stocktwits: ({output}) => ({qs: {access_token: output.access_token}}),
tiktok: ({output}) => ({method: 'POST', json: {access_token: output.access_token, open_id: output.raw.open_id, fields: ['open_id', 'union_id', 'avatar_url', 'display_name']}}),
tumblr: ({output}) => ({qs: {api_key: output.access_token}}),
vk: ({output}) => ({qs: {access_token: output.access_token, v: '5.103'}}),
wechat: ({output}) => ({qs: {access_token: output.access_token, openid: output.raw.openid, lang: 'zh_CN'}}),
weibo: ({output}) => ({qs: {access_token: output.access_token, uid: output.raw.uid}}),
twitch: ({provider, output}) => ({headers: {'client-id': provider.key, authorization: `Bearer ${output.access_token}`}}),
twitter: ({output}) => ({qs: {user_id: output.raw.user_id}}),
}

69
server/node_modules/grant/lib/request.js generated vendored Normal file
View File

@@ -0,0 +1,69 @@
var {compose, dcopy} = require('./util')
var _config = require('./config')
var oauth1 = require('./flow/oauth1')
var oauth2 = require('./flow/oauth2')
var defaults = (config) => ({method, params, query, body, state, session}) => {
method = method.toUpperCase()
params = dcopy(params || {})
query = dcopy(query || {})
body = dcopy(body || {})
state = dcopy(state || {})
session = dcopy(params.override === 'callback' ? (session || {}) : {})
if (params.override !== 'callback') {
session.provider = params.provider
if (params.override) {
session.override = params.override
}
if (method === 'GET' && Object.keys(query).length) {
session.dynamic = query
}
else if (method === 'POST' && Object.keys(body).length) {
session.dynamic = body
}
}
var provider = _config.provider(config, session, state)
return {provider, input: {method, params, query, body, state, session}}
}
var connect = ({request}) => ({provider, input, input:{session}, output}) =>
provider.oauth === 1
? compose(
oauth1.request({request}),
({provider, input, input:{session}, output}) => (
session.request = output,
oauth1.authorize({provider, input, output})
)
)({provider, input})
: provider.oauth === 2
? (
session.state = provider.state,
session.nonce = provider.nonce,
session.code_verifier = provider.code_verifier,
oauth2.authorize({provider, input})
)
: (
output = {error: 'Grant: missing or misconfigured provider'},
{provider, input, output}
)
var callback = ({request}) => ({provider, input, output}) =>
provider.oauth === 1
? oauth1.access({request})
: provider.oauth === 2
? oauth2.access({request})
: ({provider, input, output}) => (
output = {error: 'Grant: missing session or misconfigured provider'},
{provider, input, output}
)
module.exports = {defaults, connect, callback}

124
server/node_modules/grant/lib/response.js generated vendored Normal file
View File

@@ -0,0 +1,124 @@
var qs = require('qs')
var tokens = (provider, response) => {
var data = {}
if (provider.concur) {
data.access_token = response.replace(
/[\s\S]+<Token>([^<]+)<\/Token>[\s\S]+/, '$1')
data.refresh_token = response.replace(
/[\s\S]+<Refresh_Token>([^<]+)<\/Refresh_Token>[\s\S]+/, '$1')
}
else if (provider.getpocket) {
data.access_token = response.access_token
}
else if (provider.yammer) {
data.access_token = response.access_token.token
}
else if (provider.oauth === 1) {
if (response.oauth_token) {
data.access_token = response.oauth_token
}
if (response.oauth_token_secret) {
data.access_secret = response.oauth_token_secret
}
}
else if (provider.oauth === 2) {
if (response.id_token) {
data.id_token = response.id_token
}
if (response.access_token) {
data.access_token = response.access_token
}
if (response.refresh_token) {
data.refresh_token = response.refresh_token
}
}
return data
}
var oidc = (provider, session, response) => {
if (!/^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/.test(response.id_token)) {
return {error: 'Grant: OpenID Connect invalid id_token format'}
}
var [header, payload, signature] = response.id_token.split('.')
try {
header = JSON.parse(Buffer.from(header, 'base64').toString('binary'))
payload = JSON.parse(Buffer.from(payload, 'base64').toString('utf8'))
}
catch (err) {
return {error: 'Grant: OpenID Connect error decoding id_token'}
}
if (![].concat(payload.aud).includes(provider.key)) {
return {error: 'Grant: OpenID Connect invalid id_token audience'}
}
else if (session.nonce && (payload.nonce !== session.nonce)) {
return {error: 'Grant: OpenID Connect nonce mismatch'}
}
return {header, payload, signature}
}
var data = ({provider, input, input:{session}, output}) => {
if (output.error) {
return {provider, input, output}
}
if (output.id_token) {
var jwt = oidc(provider, session, output)
if (jwt.error) {
return {provider, input, output: jwt}
}
}
if (!provider.response) {
var data = tokens(provider, output)
data.raw = output
}
else {
var data = {}
var response = [].concat(provider.response)
if (response.find((key) => /token/.test(key))) {
data = tokens(provider, output)
}
if (response.includes('jwt') && jwt) {
data.jwt = {id_token: jwt}
}
if (response.includes('raw')) {
data.raw = output
}
}
return {provider, input, output: data}
}
var transport = ({provider, input, input:{params, state, session}, output}) => ({
location:
(params.override !== 'callback' && !output.error)
? output
: (!provider.transport || provider.transport === 'querystring')
? `${provider.callback || '/'}?${qs.stringify(output)}`
: provider.transport === 'session'
? provider.callback
: undefined,
session: (
provider.transport === 'session' ? session.response = output : null,
session
),
state: (
provider.transport === 'state' ? state.response = output : null,
state
),
})
module.exports = {data, transport}

106
server/node_modules/grant/lib/session.js generated vendored Normal file
View File

@@ -0,0 +1,106 @@
var crypto = require('crypto')
var cookie = require('cookie')
var signature = require('cookie-signature')
module.exports = ({name, secret, cookie:options, store}) => {
name = name || 'grant'
options = options || {path: '/', httpOnly: true, secure: false, maxAge: null}
if (!secret) {
throw new Error('Grant: cookie secret is required')
}
var embed = !store
return (req) => {
var headers = Object.keys(req.headers)
.filter((key) => /(?:set-)?cookie/i.test(key))
.reduce((all, key) => (all[key.toLowerCase()] = req.headers[key], all), {})
headers['set-cookie'] =
headers['set-cookie'] ||
(req.multiValueHeaders && req.multiValueHeaders['Set-Cookie']) ||
[]
var cookies = {
input:
// vercel - parsed object
typeof req.cookies === 'object' && !(req.cookies instanceof Array) ? req.cookies :
cookie.parse(
headers.cookie ? headers.cookie :
// aws v2 event - array of key=value pairs
req.cookies ? req.cookies.join('; ') :
''
),
output: headers['set-cookie'].reduce((all, str) =>
(all[str.split(';')[0].split('=')[0]] = str, all), {})
}
var encode = (payload, opt = {}) => {
var data = embed
? Buffer.from(JSON.stringify(payload)).toString('base64')
: payload
var value = signature.sign(data, secret)
var output = cookie.serialize(name, value, {...options, ...opt})
cookies.output[name] = output
headers['set-cookie'] = Object.keys(cookies.output)
.map((name) => cookies.output[name])
}
var cookieStore = () => {
var session = (() => {
var payload = signature.unsign(cookies.input[name] || '', secret)
try {
return JSON.parse(Buffer.from(payload, 'base64').toString())
}
catch (err) {
return {grant: {}}
}
})()
var store = {
get: async (sid) => session,
set: async (sid, value) => session = value,
remove: async (sid) => session = {}
}
return {
get: async () => {
return store.get()
},
set: async (value) => {
encode(value)
return store.set(null, value)
},
remove: async () => {
encode('', {maxAge: 0})
await store.remove()
},
cookies,
headers,
}
}
var sessionStore = () => {
var sid = signature.unsign(cookies.input[name] || '', secret)
|| crypto.randomBytes(20).toString('hex')
return {
get: async () => {
return await store.get(sid) || {grant: {}}
},
set: async (value) => {
encode(sid)
return store.set(sid, value)
},
remove: async () => {
encode(sid, {maxAge: 0})
await store.remove(sid)
},
cookies,
headers,
}
}
return embed ? cookieStore() : sessionStore()
}
}

8
server/node_modules/grant/lib/util.js generated vendored Normal file
View File

@@ -0,0 +1,8 @@
var compose = (...fns) => (args) =>
fns.reduce((p, f) => p.then(f), Promise.resolve(args))
var dcopy = (obj) =>
JSON.parse(JSON.stringify(obj))
module.exports = {compose, dcopy}

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2015 D2L Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,71 @@
# jwk-to-pem
[![Build Status](https://travis-ci.org/Brightspace/node-jwk-to-pem.svg?branch=master)](https://travis-ci.org/Brightspace/node-jwk-to-pem) [![Coverage Status](https://coveralls.io/repos/Brightspace/node-jwk-to-pem/badge.svg)](https://coveralls.io/r/Brightspace/node-jwk-to-pem)
Convert a [json web key][jwk] to a PEM for use by OpenSSL or `crypto`.
## Install
```sh
npm install jwk-to-pem --save
```
## Usage
```js
var jwkToPem = require('jwk-to-pem'),
jwt = require('jsonwebtoken');
var jwk = { kty: 'EC', crv: 'P-256', x: '...', y: '...' },
pem = jwkToPem(jwk);
jwt.verify(token, pem);
```
### Support
key type | support level
---------|--------------
RSA | all RSA keys
EC | _P-256_, _P-384_, and _P-521_ curves
### API
---
#### `jwkToPem(Object jwk[, Object options])` -> `String`
The first parameter should be an Object representing the jwk, it may be public
or private. By default, either of the two will be made into a public PEM. The
call will throw if the input jwk is malformed or does not represent a valid
key.
##### Option: private `Boolean` _(false)_
You may optionally specify that you would like a private PEM. This can be done
by passing `true` to the `private` option. The call will throw if the necessary
private parameters are not available.
## Contributing
1. **Fork** the repository. Committing directly against this repository is
highly discouraged.
2. Make your modifications in a branch, updating and writing new unit tests
as necessary in the `spec` directory.
3. Ensure that all tests pass with `npm test`
4. `rebase` your changes against master. *Do not merge*.
5. Submit a pull request to this repository. Wait for tests to run and someone
to chime in.
### Code Style
This repository is configured with [EditorConfig][EditorConfig] and
[ESLint][ESLint] rules.
[algs]: https://tools.ietf.org/html/rfc7518#section-3.1
[jwk]: https://tools.ietf.org/html/rfc7517
[EditorConfig]: http://editorconfig.org/
[ESLint]: http://eslint.org

View File

@@ -0,0 +1,45 @@
{
"name": "jwk-to-pem",
"version": "2.0.7",
"description": "Convert a JSON Web Key to a PEM",
"main": "src/jwk-to-pem.js",
"files": [
"LICENSE",
"README.md",
"src"
],
"scripts": {
"check-style": "eslint .",
"pretest": "npm run check-style",
"test": "nyc --all --include src --reporter=text-summary -- mocha spec"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Brightspace/node-jwk-to-pem"
},
"keywords": [
"jwt",
"jwk",
"jwa",
"jsonwebtoken"
],
"author": "D2L Corporation",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/Brightspace/node-jwk-to-pem/issues"
},
"homepage": "https://github.com/Brightspace/node-jwk-to-pem#readme",
"dependencies": {
"asn1.js": "^5.3.0",
"elliptic": "^6.6.1",
"safe-buffer": "^5.0.1"
},
"devDependencies": {
"chai": "^4.2.0",
"eslint": "^6.0.1",
"eslint-config-brightspace": "^0.6.4",
"jwa": "^1.1.4",
"mocha": "^6.2.0",
"nyc": "^14.1.1"
}
}

View File

@@ -0,0 +1,8 @@
'use strict';
module.exports = require('asn1.js').define('AlgorithmIdentifer', /* @this */ function() {
this.seq().obj(
this.key('algorithm').objid(),
this.key('parameters').optional().any()
);
});

View File

@@ -0,0 +1,13 @@
'use strict';
var AlgorithmIdentifier = require('./algorithm-identifier');
var Version = require('./version');
module.exports = require('asn1.js').define('PrivateKeyInfo', /* @this */ function() {
this.seq().obj(
this.key('version').use(Version),
this.key('privateKeyAlgorithm').use(AlgorithmIdentifier),
this.key('privateKey').octstr(),
this.key('attributes').optional().any()
);
});

View File

@@ -0,0 +1,10 @@
'use strict';
var AlgorithmIdentifier = require('./algorithm-identifier');
module.exports = require('asn1.js').define('PublicKeyInfo', /* @this */ function() {
this.seq().obj(
this.key('algorithm').use(AlgorithmIdentifier),
this.key('PublicKey').bitstr()
);
});

View File

@@ -0,0 +1,5 @@
'use strict';
module.exports = require('asn1.js').define('Version', /* @this */ function() {
this.int();
});

View File

@@ -0,0 +1,13 @@
'use strict';
var BN = require('asn1.js').bignum,
Buffer = require('safe-buffer').Buffer;
module.exports = function base64ToBigNum(val, zero) {
var buf = Buffer.from(val, 'base64');
var bn = val = new BN(buf, 10, 'be').iabs();
if (zero) {
buf.fill(0);
}
return bn;
};

View File

@@ -0,0 +1,156 @@
'use strict';
var asn1 = require('asn1.js'),
Buffer = require('safe-buffer').Buffer,
EC = require('elliptic').ec;
var b64ToBn = require('./b64-to-bn');
var PublicKeyInfo = require('./asn1/public-key-info'),
PrivateKeyInfo = require('./asn1/private-key-info'),
Version = require('./asn1/version');
var ECParameters = asn1.define('ECParameters', /* @this */ function() {
this.choice({
namedCurve: this.objid()
});
});
var ecPrivkeyVer1 = 1;
var ECPrivateKey = asn1.define('ECPrivateKey', /* @this */ function() {
this.seq().obj(
this.key('version').use(Version),
this.key('privateKey').octstr(),
this.key('parameters').explicit(0).optional().any(),
this.key('publicKey').explicit(1).optional().bitstr()
);
});
var curves = {
'P-256': 'p256',
'P-384': 'p384',
'P-521': 'p521'
};
var oids = {
'P-256': [1, 2, 840, 10045, 3, 1, 7],
'P-384': [1, 3, 132, 0, 34],
'P-521': [1, 3, 132, 0, 35]
};
var parameters = {};
var algorithms = {};
Object.keys(oids).forEach(function(crv) {
parameters[crv] = ECParameters.encode({
type: 'namedCurve',
value: oids[crv]
}, 'der');
algorithms[crv] = {
algorithm: [1, 2, 840, 10045, 2, 1],
parameters: parameters[crv]
};
});
oids = null;
function ecJwkToBuffer(jwk, opts) {
if ('string' !== typeof jwk.crv) {
throw new TypeError('Expected "jwk.crv" to be a String');
}
var hasD = 'string' === typeof jwk.d;
var xyTypes = hasD
? ['undefined', 'string']
: ['string'];
if (-1 === xyTypes.indexOf(typeof jwk.x)) {
throw new TypeError('Expected "jwk.x" to be a String');
}
if (-1 === xyTypes.indexOf(typeof jwk.y)) {
throw new TypeError('Expected "jwk.y" to be a String');
}
if (opts.private && !hasD) {
throw new TypeError('Expected "jwk.d" to be a String');
}
var curveName = curves[jwk.crv];
if (!curveName) {
throw new Error('Unsupported curve "' + jwk.crv + '"');
}
var curve = new EC(curveName);
var key = {};
var hasPub = jwk.x && jwk.y;
if (hasPub) {
key.pub = {
x: b64ToBn(jwk.x, false),
y: b64ToBn(jwk.y, false)
};
}
if (opts.private || !hasPub) {
key.priv = b64ToBn(jwk.d, true);
}
key = curve.keyPair(key);
var keyValidation = key.validate();
if (!keyValidation.result) {
throw new Error('Invalid key for curve: "' + keyValidation.reason + '"');
}
var result = keyToPem(jwk.crv, key, opts);
return result;
}
function keyToPem(crv, key, opts) {
var compact = false;
var publicKey = key.getPublic(compact, 'hex');
publicKey = Buffer.from(publicKey, 'hex');
publicKey = {
unused: 0,
data: publicKey
};
var result;
if (opts.private) {
var privateKey = key.getPrivate('hex');
privateKey = Buffer.from(privateKey, 'hex');
result = PrivateKeyInfo.encode({
version: 0,
privateKeyAlgorithm: algorithms[crv],
privateKey: ECPrivateKey.encode({
version: ecPrivkeyVer1,
privateKey: privateKey,
parameters: parameters[crv],
publicKey: publicKey
}, 'der')
}, 'pem', {
label: 'PRIVATE KEY'
});
privateKey.fill(0);
} else {
result = PublicKeyInfo.encode({
algorithm: algorithms[crv],
PublicKey: publicKey
}, 'pem', {
label: 'PUBLIC KEY'
});
}
// This is in an if incase asn1.js adds a trailing \n
// istanbul ignore else
if ('\n' !== result.slice(-1)) {
result += '\n';
}
return result;
}
module.exports = ecJwkToBuffer;

View File

@@ -0,0 +1,38 @@
'use strict';
var ec = require('./ec'),
rsa = require('./rsa');
/**
*
* @param {{kty:'EC', crv:string, d:string, x?:string, y?:string} | {kty:'EC', crv:string, x:string, y:string} | {kty:'RSA', e:string, n:string, d?:string, p?:string, q?:string, dp?:string, dq?:string, qi?:string}} jwk
* @param {{private:boolean}=} opts
* @returns {string}
*/
function jwkToBuffer(jwk, opts) {
if ('object' !== typeof jwk || null === jwk) {
throw new TypeError('Expected "jwk" to be an Object');
}
var kty = jwk.kty;
if ('string' !== typeof kty) {
throw new TypeError('Expected "jwk.kty" to be a String');
}
opts = opts || {};
opts.private = opts.private === true;
switch (kty) {
case 'EC': {
return ec(jwk, opts);
}
case 'RSA': {
return rsa(jwk, opts);
}
default: {
throw new Error('Unsupported key type "' + kty + '"');
}
}
}
module.exports = jwkToBuffer;

View File

@@ -0,0 +1,115 @@
'use strict';
var asn1 = require('asn1.js');
var b64ToBn = require('./b64-to-bn');
var PublicKeyInfo = require('./asn1/public-key-info'),
PrivateKeyInfo = require('./asn1/private-key-info'),
Version = require('./asn1/version');
var RSAPrivateKey = asn1.define('RSAPrivateKey', /* @this */ function() {
this.seq().obj(
this.key('version').use(Version),
this.key('modulus').int(),
this.key('publicExponent').int(),
this.key('privateExponent').int(),
this.key('prime1').int(),
this.key('prime2').int(),
this.key('exponent1').int(),
this.key('exponent2').int(),
this.key('coefficient').int()
);
});
var RSAPublicKey = asn1.define('RSAPublicKey', /* @this */ function() {
this.seq().obj(
this.key('modulus').int(),
this.key('publicExponent').int()
);
});
var algorithm = {
algorithm: [1, 2, 840, 113549, 1, 1, 1],
parameters: [5, 0]
};
function rsaJwkToBuffer(jwk, opts) {
if ('string' !== typeof jwk.e) {
throw new TypeError('Expected "jwk.e" to be a String');
}
if ('string' !== typeof jwk.n) {
throw new TypeError('Expected "jwk.n" to be a String');
}
if (opts.private) {
if ('string' !== typeof jwk.d) {
throw new TypeError('Expected "jwk.d" to be a String');
}
if ('string' !== typeof jwk.p) {
throw new TypeError('Expected "jwk.p" to be a String');
}
if ('string' !== typeof jwk.q) {
throw new TypeError('Expected "jwk.q" to be a String');
}
if ('string' !== typeof jwk.dp) {
throw new TypeError('Expected "jwk.dp" to be a String');
}
if ('string' !== typeof jwk.dq) {
throw new TypeError('Expected "jwk.dq" to be a String');
}
if ('string' !== typeof jwk.qi) {
throw new TypeError('Expected "jwk.qi" to be a String');
}
}
var pem;
if (opts.private) {
pem = PrivateKeyInfo.encode({
version: 0,
privateKeyAlgorithm: algorithm,
privateKey: RSAPrivateKey.encode({
version: 0,
modulus: b64ToBn(jwk.n, false),
publicExponent: b64ToBn(jwk.e, false),
privateExponent: b64ToBn(jwk.d, true),
prime1: b64ToBn(jwk.p, true),
prime2: b64ToBn(jwk.q, true),
exponent1: b64ToBn(jwk.dp, true),
exponent2: b64ToBn(jwk.dq, true),
coefficient: b64ToBn(jwk.qi, true)
}, 'der')
}, 'pem', {
label: 'PRIVATE KEY'
});
} else {
pem = PublicKeyInfo.encode({
algorithm: algorithm,
PublicKey: {
unused: 0,
data: RSAPublicKey.encode({
modulus: b64ToBn(jwk.n, false),
publicExponent: b64ToBn(jwk.e, false)
}, 'der')
}
}, 'pem', {
label: 'PUBLIC KEY'
});
}
// This is in an if incase asn1.js adds a trailing \n
// istanbul ignore else
if ('\n' !== pem.slice(-1)) {
pem += '\n';
}
return pem;
}
module.exports = rsaJwkToBuffer;

View File

@@ -0,0 +1,46 @@
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 160
quote_type = single
[test/*]
max_line_length = off
[LICENSE.md]
indent_size = off
[*.md]
max_line_length = off
[*.json]
max_line_length = off
[Makefile]
max_line_length = off
[CHANGELOG.md]
indent_style = space
indent_size = 2
[LICENSE]
indent_size = 2
max_line_length = off
[coverage/**/*]
indent_size = off
indent_style = off
indent = off
max_line_length = off
[.nycrc]
indent_style = tab
[tea.yaml]
indent_size = 2

39
server/node_modules/grant/node_modules/qs/.eslintrc generated vendored Normal file
View File

@@ -0,0 +1,39 @@
{
"root": true,
"extends": "@ljharb",
"ignorePatterns": [
"dist/",
],
"rules": {
"complexity": 0,
"consistent-return": 1,
"func-name-matching": 0,
"id-length": [2, { "min": 1, "max": 25, "properties": "never" }],
"indent": [2, 4],
"max-lines": 0,
"max-lines-per-function": [2, { "max": 150 }],
"max-params": [2, 18],
"max-statements": [2, 100],
"multiline-comment-style": 0,
"no-continue": 1,
"no-magic-numbers": 0,
"no-restricted-syntax": [2, "BreakStatement", "DebuggerStatement", "ForInStatement", "LabeledStatement", "WithStatement"],
},
"overrides": [
{
"files": "test/**",
"rules": {
"function-paren-newline": 0,
"max-lines-per-function": 0,
"max-statements": 0,
"no-buffer-constructor": 0,
"no-extend-native": 0,
"no-throw-literal": 0,
},
},
],
}

View File

@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: [ljharb]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: npm/qs
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with a single custom sponsorship URL

13
server/node_modules/grant/node_modules/qs/.nycrc generated vendored Normal file
View File

@@ -0,0 +1,13 @@
{
"all": true,
"check-coverage": false,
"reporter": ["text-summary", "text", "html", "json"],
"lines": 86,
"statements": 85.93,
"functions": 82.43,
"branches": 76.06,
"exclude": [
"coverage",
"dist"
]
}

622
server/node_modules/grant/node_modules/qs/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,622 @@
## **6.14.0**
- [New] `parse`: add `throwOnParameterLimitExceeded` option (#517)
- [Refactor] `parse`: use `utils.combine` more
- [patch] `parse`: add explicit `throwOnLimitExceeded` default
- [actions] use shared action; re-add finishers
- [meta] Fix changelog formatting bug
- [Deps] update `side-channel`
- [Dev Deps] update `es-value-fixtures`, `has-bigints`, `has-proto`, `has-symbols`
- [Tests] increase coverage
## **6.13.1**
- [Fix] `stringify`: avoid a crash when a `filter` key is `null`
- [Fix] `utils.merge`: functions should not be stringified into keys
- [Fix] `parse`: avoid a crash with interpretNumericEntities: true, comma: true, and iso charset
- [Fix] `stringify`: ensure a non-string `filter` does not crash
- [Refactor] use `__proto__` syntax instead of `Object.create` for null objects
- [Refactor] misc cleanup
- [Tests] `utils.merge`: add some coverage
- [Tests] fix a test case
- [actions] split out node 10-20, and 20+
- [Dev Deps] update `es-value-fixtures`, `mock-property`, `object-inspect`, `tape`
## **6.13.0**
- [New] `parse`: add `strictDepth` option (#511)
- [Tests] use `npm audit` instead of `aud`
## **6.12.3**
- [Fix] `parse`: properly account for `strictNullHandling` when `allowEmptyArrays`
- [meta] fix changelog indentation
## **6.12.2**
- [Fix] `parse`: parse encoded square brackets (#506)
- [readme] add CII best practices badge
## **6.12.1**
- [Fix] `parse`: Disable `decodeDotInKeys` by default to restore previous behavior (#501)
- [Performance] `utils`: Optimize performance under large data volumes, reduce memory usage, and speed up processing (#502)
- [Refactor] `utils`: use `+=`
- [Tests] increase coverage
## **6.12.0**
- [New] `parse`/`stringify`: add `decodeDotInKeys`/`encodeDotKeys` options (#488)
- [New] `parse`: add `duplicates` option
- [New] `parse`/`stringify`: add `allowEmptyArrays` option to allow [] in object values (#487)
- [Refactor] `parse`/`stringify`: move allowDots config logic to its own variable
- [Refactor] `stringify`: move option-handling code into `normalizeStringifyOptions`
- [readme] update readme, add logos (#484)
- [readme] `stringify`: clarify default `arrayFormat` behavior
- [readme] fix line wrapping
- [readme] remove dead badges
- [Deps] update `side-channel`
- [meta] make the dist build 50% smaller
- [meta] add `sideEffects` flag
- [meta] run build in prepack, not prepublish
- [Tests] `parse`: remove useless tests; add coverage
- [Tests] `stringify`: increase coverage
- [Tests] use `mock-property`
- [Tests] `stringify`: improve coverage
- [Dev Deps] update `@ljharb/eslint-config `, `aud`, `has-override-mistake`, `has-property-descriptors`, `mock-property`, `npmignore`, `object-inspect`, `tape`
- [Dev Deps] pin `glob`, since v10.3.8+ requires a broken `jackspeak`
- [Dev Deps] pin `jackspeak` since 2.1.2+ depends on npm aliases, which kill the install process in npm < 6
## **6.11.2**
- [Fix] `parse`: Fix parsing when the global Object prototype is frozen (#473)
- [Tests] add passing test cases with empty keys (#473)
## **6.11.1**
- [Fix] `stringify`: encode comma values more consistently (#463)
- [readme] add usage of `filter` option for injecting custom serialization, i.e. of custom types (#447)
- [meta] remove extraneous code backticks (#457)
- [meta] fix changelog markdown
- [actions] update checkout action
- [actions] restrict action permissions
- [Dev Deps] update `@ljharb/eslint-config`, `aud`, `object-inspect`, `tape`
## **6.11.0**
- [New] [Fix] `stringify`: revert 0e903c0; add `commaRoundTrip` option (#442)
- [readme] fix version badge
## **6.10.5**
- [Fix] `stringify`: with `arrayFormat: comma`, properly include an explicit `[]` on a single-item array (#434)
## **6.10.4**
- [Fix] `stringify`: with `arrayFormat: comma`, include an explicit `[]` on a single-item array (#441)
- [meta] use `npmignore` to autogenerate an npmignore file
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `has-symbol`, `object-inspect`, `tape`
## **6.10.3**
- [Fix] `parse`: ignore `__proto__` keys (#428)
- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
- [actions] reuse common workflows
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `object-inspect`, `tape`
## **6.10.2**
- [Fix] `stringify`: actually fix cyclic references (#426)
- [Fix] `stringify`: avoid encoding arrayformat comma when `encodeValuesOnly = true` (#424)
- [readme] remove travis badge; add github actions/codecov badges; update URLs
- [Docs] add note and links for coercing primitive values (#408)
- [actions] update codecov uploader
- [actions] update workflows
- [Tests] clean up stringify tests slightly
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `object-inspect`, `safe-publish-latest`, `tape`
## **6.10.1**
- [Fix] `stringify`: avoid exception on repeated object values (#402)
## **6.10.0**
- [New] `stringify`: throw on cycles, instead of an infinite loop (#395, #394, #393)
- [New] `parse`: add `allowSparse` option for collapsing arrays with missing indices (#312)
- [meta] fix README.md (#399)
- [meta] only run `npm run dist` in publish, not install
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `has-symbols`, `tape`
- [Tests] fix tests on node v0.6
- [Tests] use `ljharb/actions/node/install` instead of `ljharb/actions/node/run`
- [Tests] Revert "[meta] ignore eclint transitive audit warning"
## **6.9.7**
- [Fix] `parse`: ignore `__proto__` keys (#428)
- [Fix] `stringify`: avoid encoding arrayformat comma when `encodeValuesOnly = true` (#424)
- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
- [readme] remove travis badge; add github actions/codecov badges; update URLs
- [Docs] add note and links for coercing primitive values (#408)
- [Tests] clean up stringify tests slightly
- [meta] fix README.md (#399)
- Revert "[meta] ignore eclint transitive audit warning"
- [actions] backport actions from main
- [Dev Deps] backport updates from main
## **6.9.6**
- [Fix] restore `dist` dir; mistakenly removed in d4f6c32
## **6.9.5**
- [Fix] `stringify`: do not encode parens for RFC1738
- [Fix] `stringify`: fix arrayFormat comma with empty array/objects (#350)
- [Refactor] `format`: remove `util.assign` call
- [meta] add "Allow Edits" workflow; update rebase workflow
- [actions] switch Automatic Rebase workflow to `pull_request_target` event
- [Tests] `stringify`: add tests for #378
- [Tests] migrate tests to Github Actions
- [Tests] run `nyc` on all tests; use `tape` runner
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `browserify`, `mkdirp`, `object-inspect`, `tape`; add `aud`
## **6.9.4**
- [Fix] `stringify`: when `arrayFormat` is `comma`, respect `serializeDate` (#364)
- [Refactor] `stringify`: reduce branching (part of #350)
- [Refactor] move `maybeMap` to `utils`
- [Dev Deps] update `browserify`, `tape`
## **6.9.3**
- [Fix] proper comma parsing of URL-encoded commas (#361)
- [Fix] parses comma delimited array while having percent-encoded comma treated as normal text (#336)
## **6.9.2**
- [Fix] `parse`: Fix parsing array from object with `comma` true (#359)
- [Fix] `parse`: throw a TypeError instead of an Error for bad charset (#349)
- [meta] ignore eclint transitive audit warning
- [meta] fix indentation in package.json
- [meta] add tidelift marketing copy
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `object-inspect`, `has-symbols`, `tape`, `mkdirp`, `iconv-lite`
- [actions] add automatic rebasing / merge commit blocking
## **6.9.1**
- [Fix] `parse`: with comma true, handle field that holds an array of arrays (#335)
- [Fix] `parse`: with comma true, do not split non-string values (#334)
- [meta] add `funding` field
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`
- [Tests] use shared travis-ci config
## **6.9.0**
- [New] `parse`/`stringify`: Pass extra key/value argument to `decoder` (#333)
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `evalmd`
- [Tests] `parse`: add passing `arrayFormat` tests
- [Tests] add `posttest` using `npx aud` to run `npm audit` without a lockfile
- [Tests] up to `node` `v12.10`, `v11.15`, `v10.16`, `v8.16`
- [Tests] `Buffer.from` in node v5.0-v5.9 and v4.0-v4.4 requires a TypedArray
## **6.8.3**
- [Fix] `parse`: ignore `__proto__` keys (#428)
- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
- [Fix] `stringify`: avoid encoding arrayformat comma when `encodeValuesOnly = true` (#424)
- [readme] remove travis badge; add github actions/codecov badges; update URLs
- [Tests] clean up stringify tests slightly
- [Docs] add note and links for coercing primitive values (#408)
- [meta] fix README.md (#399)
- [actions] backport actions from main
- [Dev Deps] backport updates from main
- [Refactor] `stringify`: reduce branching
- [meta] do not publish workflow files
## **6.8.2**
- [Fix] proper comma parsing of URL-encoded commas (#361)
- [Fix] parses comma delimited array while having percent-encoded comma treated as normal text (#336)
## **6.8.1**
- [Fix] `parse`: Fix parsing array from object with `comma` true (#359)
- [Fix] `parse`: throw a TypeError instead of an Error for bad charset (#349)
- [Fix] `parse`: with comma true, handle field that holds an array of arrays (#335)
- [fix] `parse`: with comma true, do not split non-string values (#334)
- [meta] add tidelift marketing copy
- [meta] add `funding` field
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `tape`, `safe-publish-latest`, `evalmd`, `has-symbols`, `iconv-lite`, `mkdirp`, `object-inspect`
- [Tests] `parse`: add passing `arrayFormat` tests
- [Tests] use shared travis-ci configs
- [Tests] `Buffer.from` in node v5.0-v5.9 and v4.0-v4.4 requires a TypedArray
- [actions] add automatic rebasing / merge commit blocking
## **6.8.0**
- [New] add `depth=false` to preserve the original key; [Fix] `depth=0` should preserve the original key (#326)
- [New] [Fix] stringify symbols and bigints
- [Fix] ensure node 0.12 can stringify Symbols
- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
- [Refactor] `formats`: tiny bit of cleanup.
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `browserify`, `safe-publish-latest`, `iconv-lite`, `tape`
- [Tests] add tests for `depth=0` and `depth=false` behavior, both current and intuitive/intended (#326)
- [Tests] use `eclint` instead of `editorconfig-tools`
- [docs] readme: add security note
- [meta] add github sponsorship
- [meta] add FUNDING.yml
- [meta] Clean up license text so its properly detected as BSD-3-Clause
## **6.7.3**
- [Fix] `parse`: ignore `__proto__` keys (#428)
- [Fix] `stringify`: avoid encoding arrayformat comma when `encodeValuesOnly = true` (#424)
- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
- [readme] remove travis badge; add github actions/codecov badges; update URLs
- [Docs] add note and links for coercing primitive values (#408)
- [meta] fix README.md (#399)
- [meta] do not publish workflow files
- [actions] backport actions from main
- [Dev Deps] backport updates from main
- [Tests] use `nyc` for coverage
- [Tests] clean up stringify tests slightly
## **6.7.2**
- [Fix] proper comma parsing of URL-encoded commas (#361)
- [Fix] parses comma delimited array while having percent-encoded comma treated as normal text (#336)
## **6.7.1**
- [Fix] `parse`: Fix parsing array from object with `comma` true (#359)
- [Fix] `parse`: with comma true, handle field that holds an array of arrays (#335)
- [fix] `parse`: with comma true, do not split non-string values (#334)
- [Fix] `parse`: throw a TypeError instead of an Error for bad charset (#349)
- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
- [Refactor] `formats`: tiny bit of cleanup.
- readme: add security note
- [meta] add tidelift marketing copy
- [meta] add `funding` field
- [meta] add FUNDING.yml
- [meta] Clean up license text so its properly detected as BSD-3-Clause
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `tape`, `safe-publish-latest`, `evalmd`, `iconv-lite`, `mkdirp`, `object-inspect`, `browserify`
- [Tests] `parse`: add passing `arrayFormat` tests
- [Tests] use shared travis-ci configs
- [Tests] `Buffer.from` in node v5.0-v5.9 and v4.0-v4.4 requires a TypedArray
- [Tests] add tests for `depth=0` and `depth=false` behavior, both current and intuitive/intended
- [Tests] use `eclint` instead of `editorconfig-tools`
- [actions] add automatic rebasing / merge commit blocking
## **6.7.0**
- [New] `stringify`/`parse`: add `comma` as an `arrayFormat` option (#276, #219)
- [Fix] correctly parse nested arrays (#212)
- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source, also with an array source
- [Robustness] `stringify`: cache `Object.prototype.hasOwnProperty`
- [Refactor] `utils`: `isBuffer`: small tweak; add tests
- [Refactor] use cached `Array.isArray`
- [Refactor] `parse`/`stringify`: make a function to normalize the options
- [Refactor] `utils`: reduce observable [[Get]]s
- [Refactor] `stringify`/`utils`: cache `Array.isArray`
- [Tests] always use `String(x)` over `x.toString()`
- [Tests] fix Buffer tests to work in node < 4.5 and node < 5.10
- [Tests] temporarily allow coverage to fail
## **6.6.1**
- [Fix] `parse`: ignore `__proto__` keys (#428)
- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
- [Fix] `utils.merge`: avoid a crash with a null target and an array source
- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
- [Fix] correctly parse nested arrays
- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
- [Robustness] `stringify`: cache `Object.prototype.hasOwnProperty`
- [Refactor] `formats`: tiny bit of cleanup.
- [Refactor] `utils`: `isBuffer`: small tweak; add tests
- [Refactor]: `stringify`/`utils`: cache `Array.isArray`
- [Refactor] `utils`: reduce observable [[Get]]s
- [Refactor] use cached `Array.isArray`
- [Refactor] `parse`/`stringify`: make a function to normalize the options
- [readme] remove travis badge; add github actions/codecov badges; update URLs
- [Docs] Clarify the need for "arrayLimit" option
- [meta] fix README.md (#399)
- [meta] do not publish workflow files
- [meta] Clean up license text so its properly detected as BSD-3-Clause
- [meta] add FUNDING.yml
- [meta] Fixes typo in CHANGELOG.md
- [actions] backport actions from main
- [Tests] fix Buffer tests to work in node < 4.5 and node < 5.10
- [Tests] always use `String(x)` over `x.toString()`
- [Dev Deps] backport from main
## **6.6.0**
- [New] Add support for iso-8859-1, utf8 "sentinel" and numeric entities (#268)
- [New] move two-value combine to a `utils` function (#189)
- [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279)
- [Fix] when `parseArrays` is false, properly handle keys ending in `[]` (#260)
- [Fix] `stringify`: do not crash in an obscure combo of `interpretNumericEntities`, a bad custom `decoder`, & `iso-8859-1`
- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
- [refactor] `stringify`: Avoid arr = arr.concat(...), push to the existing instance (#269)
- [Refactor] `parse`: only need to reassign the var once
- [Refactor] `parse`/`stringify`: clean up `charset` options checking; fix defaults
- [Refactor] add missing defaults
- [Refactor] `parse`: one less `concat` call
- [Refactor] `utils`: `compactQueue`: make it explicitly side-effecting
- [Dev Deps] update `browserify`, `eslint`, `@ljharb/eslint-config`, `iconv-lite`, `safe-publish-latest`, `tape`
- [Tests] up to `node` `v10.10`, `v9.11`, `v8.12`, `v6.14`, `v4.9`; pin included builds to LTS
## **6.5.3**
- [Fix] `parse`: ignore `__proto__` keys (#428)
- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
- [Fix] correctly parse nested arrays
- [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279)
- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
- [Fix] when `parseArrays` is false, properly handle keys ending in `[]`
- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
- [Fix] `utils.merge`: avoid a crash with a null target and an array source
- [Refactor] `utils`: reduce observable [[Get]]s
- [Refactor] use cached `Array.isArray`
- [Refactor] `stringify`: Avoid arr = arr.concat(...), push to the existing instance (#269)
- [Refactor] `parse`: only need to reassign the var once
- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
- [readme] remove travis badge; add github actions/codecov badges; update URLs
- [Docs] Clean up license text so its properly detected as BSD-3-Clause
- [Docs] Clarify the need for "arrayLimit" option
- [meta] fix README.md (#399)
- [meta] add FUNDING.yml
- [actions] backport actions from main
- [Tests] always use `String(x)` over `x.toString()`
- [Tests] remove nonexistent tape option
- [Dev Deps] backport from main
## **6.5.2**
- [Fix] use `safer-buffer` instead of `Buffer` constructor
- [Refactor] utils: `module.exports` one thing, instead of mutating `exports` (#230)
- [Dev Deps] update `browserify`, `eslint`, `iconv-lite`, `safer-buffer`, `tape`, `browserify`
## **6.5.1**
- [Fix] Fix parsing & compacting very deep objects (#224)
- [Refactor] name utils functions
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `tape`
- [Tests] up to `node` `v8.4`; use `nvm install-latest-npm` so newer npm doesnt break older node
- [Tests] Use precise dist for Node.js 0.6 runtime (#225)
- [Tests] make 0.6 required, now that its passing
- [Tests] on `node` `v8.2`; fix npm on node 0.6
## **6.5.0**
- [New] add `utils.assign`
- [New] pass default encoder/decoder to custom encoder/decoder functions (#206)
- [New] `parse`/`stringify`: add `ignoreQueryPrefix`/`addQueryPrefix` options, respectively (#213)
- [Fix] Handle stringifying empty objects with addQueryPrefix (#217)
- [Fix] do not mutate `options` argument (#207)
- [Refactor] `parse`: cache index to reuse in else statement (#182)
- [Docs] add various badges to readme (#208)
- [Dev Deps] update `eslint`, `browserify`, `iconv-lite`, `tape`
- [Tests] up to `node` `v8.1`, `v7.10`, `v6.11`; npm v4.6 breaks on node < v1; npm v5+ breaks on node < v4
- [Tests] add `editorconfig-tools`
## **6.4.1**
- [Fix] `parse`: ignore `__proto__` keys (#428)
- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
- [Fix] use `safer-buffer` instead of `Buffer` constructor
- [Fix] `utils.merge`: avoid a crash with a null target and an array source
- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
- [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279)
- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
- [Fix] when `parseArrays` is false, properly handle keys ending in `[]`
- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
- [Refactor] use cached `Array.isArray`
- [Refactor] `stringify`: Avoid arr = arr.concat(...), push to the existing instance (#269)
- [readme] remove travis badge; add github actions/codecov badges; update URLs
- [Docs] Clarify the need for "arrayLimit" option
- [meta] fix README.md (#399)
- [meta] Clean up license text so its properly detected as BSD-3-Clause
- [meta] add FUNDING.yml
- [actions] backport actions from main
- [Tests] remove nonexistent tape option
- [Dev Deps] backport from main
## **6.4.0**
- [New] `qs.stringify`: add `encodeValuesOnly` option
- [Fix] follow `allowPrototypes` option during merge (#201, #201)
- [Fix] support keys starting with brackets (#202, #200)
- [Fix] chmod a-x
- [Dev Deps] update `eslint`
- [Tests] up to `node` `v7.7`, `v6.10`,` v4.8`; disable osx builds since they block linux builds
- [eslint] reduce warnings
## **6.3.3**
- [Fix] `parse`: ignore `__proto__` keys (#428)
- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
- [Fix] `utils.merge`: avoid a crash with a null target and an array source
- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
- [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279)
- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
- [Fix] when `parseArrays` is false, properly handle keys ending in `[]`
- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
- [Refactor] use cached `Array.isArray`
- [Refactor] `stringify`: Avoid arr = arr.concat(...), push to the existing instance (#269)
- [Docs] Clarify the need for "arrayLimit" option
- [meta] fix README.md (#399)
- [meta] Clean up license text so its properly detected as BSD-3-Clause
- [meta] add FUNDING.yml
- [actions] backport actions from main
- [Tests] use `safer-buffer` instead of `Buffer` constructor
- [Tests] remove nonexistent tape option
- [Dev Deps] backport from main
## **6.3.2**
- [Fix] follow `allowPrototypes` option during merge (#201, #200)
- [Dev Deps] update `eslint`
- [Fix] chmod a-x
- [Fix] support keys starting with brackets (#202, #200)
- [Tests] up to `node` `v7.7`, `v6.10`,` v4.8`; disable osx builds since they block linux builds
## **6.3.1**
- [Fix] ensure that `allowPrototypes: false` does not ever shadow Object.prototype properties (thanks, @snyk!)
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `browserify`, `iconv-lite`, `qs-iconv`, `tape`
- [Tests] on all node minors; improve test matrix
- [Docs] document stringify option `allowDots` (#195)
- [Docs] add empty object and array values example (#195)
- [Docs] Fix minor inconsistency/typo (#192)
- [Docs] document stringify option `sort` (#191)
- [Refactor] `stringify`: throw faster with an invalid encoder
- [Refactor] remove unnecessary escapes (#184)
- Remove contributing.md, since `qs` is no longer part of `hapi` (#183)
## **6.3.0**
- [New] Add support for RFC 1738 (#174, #173)
- [New] `stringify`: Add `serializeDate` option to customize Date serialization (#159)
- [Fix] ensure `utils.merge` handles merging two arrays
- [Refactor] only constructors should be capitalized
- [Refactor] capitalized var names are for constructors only
- [Refactor] avoid using a sparse array
- [Robustness] `formats`: cache `String#replace`
- [Dev Deps] update `browserify`, `eslint`, `@ljharb/eslint-config`; add `safe-publish-latest`
- [Tests] up to `node` `v6.8`, `v4.6`; improve test matrix
- [Tests] flesh out arrayLimit/arrayFormat tests (#107)
- [Tests] skip Object.create tests when null objects are not available
- [Tests] Turn on eslint for test files (#175)
## **6.2.4**
- [Fix] `parse`: ignore `__proto__` keys (#428)
- [Fix] `utils.merge`: avoid a crash with a null target and an array source
- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
- [Fix] when `parseArrays` is false, properly handle keys ending in `[]`
- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
- [Refactor] use cached `Array.isArray`
- [Docs] Clarify the need for "arrayLimit" option
- [meta] fix README.md (#399)
- [meta] Clean up license text so its properly detected as BSD-3-Clause
- [meta] add FUNDING.yml
- [actions] backport actions from main
- [Tests] use `safer-buffer` instead of `Buffer` constructor
- [Tests] remove nonexistent tape option
- [Dev Deps] backport from main
## **6.2.3**
- [Fix] follow `allowPrototypes` option during merge (#201, #200)
- [Fix] chmod a-x
- [Fix] support keys starting with brackets (#202, #200)
- [Tests] up to `node` `v7.7`, `v6.10`,` v4.8`; disable osx builds since they block linux builds
## **6.2.2**
- [Fix] ensure that `allowPrototypes: false` does not ever shadow Object.prototype properties
## **6.2.1**
- [Fix] ensure `key[]=x&key[]&key[]=y` results in 3, not 2, values
- [Refactor] Be explicit and use `Object.prototype.hasOwnProperty.call`
- [Tests] remove `parallelshell` since it does not reliably report failures
- [Tests] up to `node` `v6.3`, `v5.12`
- [Dev Deps] update `tape`, `eslint`, `@ljharb/eslint-config`, `qs-iconv`
## [**6.2.0**](https://github.com/ljharb/qs/issues?milestone=36&state=closed)
- [New] pass Buffers to the encoder/decoder directly (#161)
- [New] add "encoder" and "decoder" options, for custom param encoding/decoding (#160)
- [Fix] fix compacting of nested sparse arrays (#150)
## **6.1.2**
- [Fix] follow `allowPrototypes` option during merge (#201, #200)
- [Fix] chmod a-x
- [Fix] support keys starting with brackets (#202, #200)
- [Tests] up to `node` `v7.7`, `v6.10`,` v4.8`; disable osx builds since they block linux builds
## **6.1.1**
- [Fix] ensure that `allowPrototypes: false` does not ever shadow Object.prototype properties
## [**6.1.0**](https://github.com/ljharb/qs/issues?milestone=35&state=closed)
- [New] allowDots option for `stringify` (#151)
- [Fix] "sort" option should work at a depth of 3 or more (#151)
- [Fix] Restore `dist` directory; will be removed in v7 (#148)
## **6.0.4**
- [Fix] follow `allowPrototypes` option during merge (#201, #200)
- [Fix] chmod a-x
- [Fix] support keys starting with brackets (#202, #200)
- [Tests] up to `node` `v7.7`, `v6.10`,` v4.8`; disable osx builds since they block linux builds
## **6.0.3**
- [Fix] ensure that `allowPrototypes: false` does not ever shadow Object.prototype properties
- [Fix] Restore `dist` directory; will be removed in v7 (#148)
## [**6.0.2**](https://github.com/ljharb/qs/issues?milestone=33&state=closed)
- Revert ES6 requirement and restore support for node down to v0.8.
## [**6.0.1**](https://github.com/ljharb/qs/issues?milestone=32&state=closed)
- [**#127**](https://github.com/ljharb/qs/pull/127) Fix engines definition in package.json
## [**6.0.0**](https://github.com/ljharb/qs/issues?milestone=31&state=closed)
- [**#124**](https://github.com/ljharb/qs/issues/124) Use ES6 and drop support for node < v4
## **5.2.1**
- [Fix] ensure `key[]=x&key[]&key[]=y` results in 3, not 2, values
## [**5.2.0**](https://github.com/ljharb/qs/issues?milestone=30&state=closed)
- [**#64**](https://github.com/ljharb/qs/issues/64) Add option to sort object keys in the query string
## [**5.1.0**](https://github.com/ljharb/qs/issues?milestone=29&state=closed)
- [**#117**](https://github.com/ljharb/qs/issues/117) make URI encoding stringified results optional
- [**#106**](https://github.com/ljharb/qs/issues/106) Add flag `skipNulls` to optionally skip null values in stringify
## [**5.0.0**](https://github.com/ljharb/qs/issues?milestone=28&state=closed)
- [**#114**](https://github.com/ljharb/qs/issues/114) default allowDots to false
- [**#100**](https://github.com/ljharb/qs/issues/100) include dist to npm
## [**4.0.0**](https://github.com/ljharb/qs/issues?milestone=26&state=closed)
- [**#98**](https://github.com/ljharb/qs/issues/98) make returning plain objects and allowing prototype overwriting properties optional
## [**3.1.0**](https://github.com/ljharb/qs/issues?milestone=24&state=closed)
- [**#89**](https://github.com/ljharb/qs/issues/89) Add option to disable "Transform dot notation to bracket notation"
## [**3.0.0**](https://github.com/ljharb/qs/issues?milestone=23&state=closed)
- [**#80**](https://github.com/ljharb/qs/issues/80) qs.parse silently drops properties
- [**#77**](https://github.com/ljharb/qs/issues/77) Perf boost
- [**#60**](https://github.com/ljharb/qs/issues/60) Add explicit option to disable array parsing
- [**#74**](https://github.com/ljharb/qs/issues/74) Bad parse when turning array into object
- [**#81**](https://github.com/ljharb/qs/issues/81) Add a `filter` option
- [**#68**](https://github.com/ljharb/qs/issues/68) Fixed issue with recursion and passing strings into objects.
- [**#66**](https://github.com/ljharb/qs/issues/66) Add mixed array and object dot notation support Closes: #47
- [**#76**](https://github.com/ljharb/qs/issues/76) RFC 3986
- [**#85**](https://github.com/ljharb/qs/issues/85) No equal sign
- [**#84**](https://github.com/ljharb/qs/issues/84) update license attribute
## [**2.4.1**](https://github.com/ljharb/qs/issues?milestone=20&state=closed)
- [**#73**](https://github.com/ljharb/qs/issues/73) Property 'hasOwnProperty' of object #<Object> is not a function
## [**2.4.0**](https://github.com/ljharb/qs/issues?milestone=19&state=closed)
- [**#70**](https://github.com/ljharb/qs/issues/70) Add arrayFormat option
## [**2.3.3**](https://github.com/ljharb/qs/issues?milestone=18&state=closed)
- [**#59**](https://github.com/ljharb/qs/issues/59) make sure array indexes are >= 0, closes #57
- [**#58**](https://github.com/ljharb/qs/issues/58) make qs usable for browser loader
## [**2.3.2**](https://github.com/ljharb/qs/issues?milestone=17&state=closed)
- [**#55**](https://github.com/ljharb/qs/issues/55) allow merging a string into an object
## [**2.3.1**](https://github.com/ljharb/qs/issues?milestone=16&state=closed)
- [**#52**](https://github.com/ljharb/qs/issues/52) Return "undefined" and "false" instead of throwing "TypeError".
## [**2.3.0**](https://github.com/ljharb/qs/issues?milestone=15&state=closed)
- [**#50**](https://github.com/ljharb/qs/issues/50) add option to omit array indices, closes #46
## [**2.2.5**](https://github.com/ljharb/qs/issues?milestone=14&state=closed)
- [**#39**](https://github.com/ljharb/qs/issues/39) Is there an alternative to Buffer.isBuffer?
- [**#49**](https://github.com/ljharb/qs/issues/49) refactor utils.merge, fixes #45
- [**#41**](https://github.com/ljharb/qs/issues/41) avoid browserifying Buffer, for #39
## [**2.2.4**](https://github.com/ljharb/qs/issues?milestone=13&state=closed)
- [**#38**](https://github.com/ljharb/qs/issues/38) how to handle object keys beginning with a number
## [**2.2.3**](https://github.com/ljharb/qs/issues?milestone=12&state=closed)
- [**#37**](https://github.com/ljharb/qs/issues/37) parser discards first empty value in array
- [**#36**](https://github.com/ljharb/qs/issues/36) Update to lab 4.x
## [**2.2.2**](https://github.com/ljharb/qs/issues?milestone=11&state=closed)
- [**#33**](https://github.com/ljharb/qs/issues/33) Error when plain object in a value
- [**#34**](https://github.com/ljharb/qs/issues/34) use Object.prototype.hasOwnProperty.call instead of obj.hasOwnProperty
- [**#24**](https://github.com/ljharb/qs/issues/24) Changelog? Semver?
## [**2.2.1**](https://github.com/ljharb/qs/issues?milestone=10&state=closed)
- [**#32**](https://github.com/ljharb/qs/issues/32) account for circular references properly, closes #31
- [**#31**](https://github.com/ljharb/qs/issues/31) qs.parse stackoverflow on circular objects
## [**2.2.0**](https://github.com/ljharb/qs/issues?milestone=9&state=closed)
- [**#26**](https://github.com/ljharb/qs/issues/26) Don't use Buffer global if it's not present
- [**#30**](https://github.com/ljharb/qs/issues/30) Bug when merging non-object values into arrays
- [**#29**](https://github.com/ljharb/qs/issues/29) Don't call Utils.clone at the top of Utils.merge
- [**#23**](https://github.com/ljharb/qs/issues/23) Ability to not limit parameters?
## [**2.1.0**](https://github.com/ljharb/qs/issues?milestone=8&state=closed)
- [**#22**](https://github.com/ljharb/qs/issues/22) Enable using a RegExp as delimiter
## [**2.0.0**](https://github.com/ljharb/qs/issues?milestone=7&state=closed)
- [**#18**](https://github.com/ljharb/qs/issues/18) Why is there arrayLimit?
- [**#20**](https://github.com/ljharb/qs/issues/20) Configurable parametersLimit
- [**#21**](https://github.com/ljharb/qs/issues/21) make all limits optional, for #18, for #20
## [**1.2.2**](https://github.com/ljharb/qs/issues?milestone=6&state=closed)
- [**#19**](https://github.com/ljharb/qs/issues/19) Don't overwrite null values
## [**1.2.1**](https://github.com/ljharb/qs/issues?milestone=5&state=closed)
- [**#16**](https://github.com/ljharb/qs/issues/16) ignore non-string delimiters
- [**#15**](https://github.com/ljharb/qs/issues/15) Close code block
## [**1.2.0**](https://github.com/ljharb/qs/issues?milestone=4&state=closed)
- [**#12**](https://github.com/ljharb/qs/issues/12) Add optional delim argument
- [**#13**](https://github.com/ljharb/qs/issues/13) fix #11: flattened keys in array are now correctly parsed
## [**1.1.0**](https://github.com/ljharb/qs/issues?milestone=3&state=closed)
- [**#7**](https://github.com/ljharb/qs/issues/7) Empty values of a POST array disappear after being submitted
- [**#9**](https://github.com/ljharb/qs/issues/9) Should not omit equals signs (=) when value is null
- [**#6**](https://github.com/ljharb/qs/issues/6) Minor grammar fix in README
## [**1.0.2**](https://github.com/ljharb/qs/issues?milestone=2&state=closed)
- [**#5**](https://github.com/ljharb/qs/issues/5) array holes incorrectly copied into object on large index

29
server/node_modules/grant/node_modules/qs/LICENSE.md generated vendored Normal file
View File

@@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2014, Nathan LaFreniere and other [contributors](https://github.com/ljharb/qs/graphs/contributors)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

733
server/node_modules/grant/node_modules/qs/README.md generated vendored Normal file
View File

@@ -0,0 +1,733 @@
<p align="center">
<img alt="qs" src="./logos/banner_default.png" width="800" />
</p>
# qs <sup>[![Version Badge][npm-version-svg]][package-url]</sup>
[![github actions][actions-image]][actions-url]
[![coverage][codecov-image]][codecov-url]
[![License][license-image]][license-url]
[![Downloads][downloads-image]][downloads-url]
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/9058/badge)](https://bestpractices.coreinfrastructure.org/projects/9058)
[![npm badge][npm-badge-png]][package-url]
A querystring parsing and stringifying library with some added security.
Lead Maintainer: [Jordan Harband](https://github.com/ljharb)
The **qs** module was originally created and maintained by [TJ Holowaychuk](https://github.com/visionmedia/node-querystring).
## Usage
```javascript
var qs = require('qs');
var assert = require('assert');
var obj = qs.parse('a=c');
assert.deepEqual(obj, { a: 'c' });
var str = qs.stringify(obj);
assert.equal(str, 'a=c');
```
### Parsing Objects
[](#preventEval)
```javascript
qs.parse(string, [options]);
```
**qs** allows you to create nested objects within your query strings, by surrounding the name of sub-keys with square brackets `[]`.
For example, the string `'foo[bar]=baz'` converts to:
```javascript
assert.deepEqual(qs.parse('foo[bar]=baz'), {
foo: {
bar: 'baz'
}
});
```
When using the `plainObjects` option the parsed value is returned as a null object, created via `{ __proto__: null }` and as such you should be aware that prototype methods will not exist on it and a user may set those names to whatever value they like:
```javascript
var nullObject = qs.parse('a[hasOwnProperty]=b', { plainObjects: true });
assert.deepEqual(nullObject, { a: { hasOwnProperty: 'b' } });
```
By default parameters that would overwrite properties on the object prototype are ignored, if you wish to keep the data from those fields either use `plainObjects` as mentioned above, or set `allowPrototypes` to `true` which will allow user input to overwrite those properties.
*WARNING* It is generally a bad idea to enable this option as it can cause problems when attempting to use the properties that have been overwritten.
Always be careful with this option.
```javascript
var protoObject = qs.parse('a[hasOwnProperty]=b', { allowPrototypes: true });
assert.deepEqual(protoObject, { a: { hasOwnProperty: 'b' } });
```
URI encoded strings work too:
```javascript
assert.deepEqual(qs.parse('a%5Bb%5D=c'), {
a: { b: 'c' }
});
```
You can also nest your objects, like `'foo[bar][baz]=foobarbaz'`:
```javascript
assert.deepEqual(qs.parse('foo[bar][baz]=foobarbaz'), {
foo: {
bar: {
baz: 'foobarbaz'
}
}
});
```
By default, when nesting objects **qs** will only parse up to 5 children deep.
This means if you attempt to parse a string like `'a[b][c][d][e][f][g][h][i]=j'` your resulting object will be:
```javascript
var expected = {
a: {
b: {
c: {
d: {
e: {
f: {
'[g][h][i]': 'j'
}
}
}
}
}
}
};
var string = 'a[b][c][d][e][f][g][h][i]=j';
assert.deepEqual(qs.parse(string), expected);
```
This depth can be overridden by passing a `depth` option to `qs.parse(string, [options])`:
```javascript
var deep = qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1 });
assert.deepEqual(deep, { a: { b: { '[c][d][e][f][g][h][i]': 'j' } } });
```
You can configure **qs** to throw an error when parsing nested input beyond this depth using the `strictDepth` option (defaulted to false):
```javascript
try {
qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1, strictDepth: true });
} catch (err) {
assert(err instanceof RangeError);
assert.strictEqual(err.message, 'Input depth exceeded depth option of 1 and strictDepth is true');
}
```
The depth limit helps mitigate abuse when **qs** is used to parse user input, and it is recommended to keep it a reasonably small number. The strictDepth option adds a layer of protection by throwing an error when the limit is exceeded, allowing you to catch and handle such cases.
For similar reasons, by default **qs** will only parse up to 1000 parameters. This can be overridden by passing a `parameterLimit` option:
```javascript
var limited = qs.parse('a=b&c=d', { parameterLimit: 1 });
assert.deepEqual(limited, { a: 'b' });
```
If you want an error to be thrown whenever the a limit is exceeded (eg, `parameterLimit`, `arrayLimit`), set the `throwOnLimitExceeded` option to `true`. This option will generate a descriptive error if the query string exceeds a configured limit.
```javascript
try {
qs.parse('a=1&b=2&c=3&d=4', { parameterLimit: 3, throwOnLimitExceeded: true });
} catch (err) {
assert(err instanceof Error);
assert.strictEqual(err.message, 'Parameter limit exceeded. Only 3 parameters allowed.');
}
```
When `throwOnLimitExceeded` is set to `false` (default), **qs** will parse up to the specified `parameterLimit` and ignore the rest without throwing an error.
To bypass the leading question mark, use `ignoreQueryPrefix`:
```javascript
var prefixed = qs.parse('?a=b&c=d', { ignoreQueryPrefix: true });
assert.deepEqual(prefixed, { a: 'b', c: 'd' });
```
An optional delimiter can also be passed:
```javascript
var delimited = qs.parse('a=b;c=d', { delimiter: ';' });
assert.deepEqual(delimited, { a: 'b', c: 'd' });
```
Delimiters can be a regular expression too:
```javascript
var regexed = qs.parse('a=b;c=d,e=f', { delimiter: /[;,]/ });
assert.deepEqual(regexed, { a: 'b', c: 'd', e: 'f' });
```
Option `allowDots` can be used to enable dot notation:
```javascript
var withDots = qs.parse('a.b=c', { allowDots: true });
assert.deepEqual(withDots, { a: { b: 'c' } });
```
Option `decodeDotInKeys` can be used to decode dots in keys
Note: it implies `allowDots`, so `parse` will error if you set `decodeDotInKeys` to `true`, and `allowDots` to `false`.
```javascript
var withDots = qs.parse('name%252Eobj.first=John&name%252Eobj.last=Doe', { decodeDotInKeys: true });
assert.deepEqual(withDots, { 'name.obj': { first: 'John', last: 'Doe' }});
```
Option `allowEmptyArrays` can be used to allowing empty array values in object
```javascript
var withEmptyArrays = qs.parse('foo[]&bar=baz', { allowEmptyArrays: true });
assert.deepEqual(withEmptyArrays, { foo: [], bar: 'baz' });
```
Option `duplicates` can be used to change the behavior when duplicate keys are encountered
```javascript
assert.deepEqual(qs.parse('foo=bar&foo=baz'), { foo: ['bar', 'baz'] });
assert.deepEqual(qs.parse('foo=bar&foo=baz', { duplicates: 'combine' }), { foo: ['bar', 'baz'] });
assert.deepEqual(qs.parse('foo=bar&foo=baz', { duplicates: 'first' }), { foo: 'bar' });
assert.deepEqual(qs.parse('foo=bar&foo=baz', { duplicates: 'last' }), { foo: 'baz' });
```
If you have to deal with legacy browsers or services, there's also support for decoding percent-encoded octets as iso-8859-1:
```javascript
var oldCharset = qs.parse('a=%A7', { charset: 'iso-8859-1' });
assert.deepEqual(oldCharset, { a: '§' });
```
Some services add an initial `utf8=✓` value to forms so that old Internet Explorer versions are more likely to submit the form as utf-8.
Additionally, the server can check the value against wrong encodings of the checkmark character and detect that a query string or `application/x-www-form-urlencoded` body was *not* sent as utf-8, eg. if the form had an `accept-charset` parameter or the containing page had a different character set.
**qs** supports this mechanism via the `charsetSentinel` option.
If specified, the `utf8` parameter will be omitted from the returned object.
It will be used to switch to `iso-8859-1`/`utf-8` mode depending on how the checkmark is encoded.
**Important**: When you specify both the `charset` option and the `charsetSentinel` option, the `charset` will be overridden when the request contains a `utf8` parameter from which the actual charset can be deduced.
In that sense the `charset` will behave as the default charset rather than the authoritative charset.
```javascript
var detectedAsUtf8 = qs.parse('utf8=%E2%9C%93&a=%C3%B8', {
charset: 'iso-8859-1',
charsetSentinel: true
});
assert.deepEqual(detectedAsUtf8, { a: 'ø' });
// Browsers encode the checkmark as &#10003; when submitting as iso-8859-1:
var detectedAsIso8859_1 = qs.parse('utf8=%26%2310003%3B&a=%F8', {
charset: 'utf-8',
charsetSentinel: true
});
assert.deepEqual(detectedAsIso8859_1, { a: 'ø' });
```
If you want to decode the `&#...;` syntax to the actual character, you can specify the `interpretNumericEntities` option as well:
```javascript
var detectedAsIso8859_1 = qs.parse('a=%26%239786%3B', {
charset: 'iso-8859-1',
interpretNumericEntities: true
});
assert.deepEqual(detectedAsIso8859_1, { a: '☺' });
```
It also works when the charset has been detected in `charsetSentinel` mode.
### Parsing Arrays
**qs** can also parse arrays using a similar `[]` notation:
```javascript
var withArray = qs.parse('a[]=b&a[]=c');
assert.deepEqual(withArray, { a: ['b', 'c'] });
```
You may specify an index as well:
```javascript
var withIndexes = qs.parse('a[1]=c&a[0]=b');
assert.deepEqual(withIndexes, { a: ['b', 'c'] });
```
Note that the only difference between an index in an array and a key in an object is that the value between the brackets must be a number to create an array.
When creating arrays with specific indices, **qs** will compact a sparse array to only the existing values preserving their order:
```javascript
var noSparse = qs.parse('a[1]=b&a[15]=c');
assert.deepEqual(noSparse, { a: ['b', 'c'] });
```
You may also use `allowSparse` option to parse sparse arrays:
```javascript
var sparseArray = qs.parse('a[1]=2&a[3]=5', { allowSparse: true });
assert.deepEqual(sparseArray, { a: [, '2', , '5'] });
```
Note that an empty string is also a value, and will be preserved:
```javascript
var withEmptyString = qs.parse('a[]=&a[]=b');
assert.deepEqual(withEmptyString, { a: ['', 'b'] });
var withIndexedEmptyString = qs.parse('a[0]=b&a[1]=&a[2]=c');
assert.deepEqual(withIndexedEmptyString, { a: ['b', '', 'c'] });
```
**qs** will also limit specifying indices in an array to a maximum index of `20`.
Any array members with an index of greater than `20` will instead be converted to an object with the index as the key.
This is needed to handle cases when someone sent, for example, `a[999999999]` and it will take significant time to iterate over this huge array.
```javascript
var withMaxIndex = qs.parse('a[100]=b');
assert.deepEqual(withMaxIndex, { a: { '100': 'b' } });
```
This limit can be overridden by passing an `arrayLimit` option:
```javascript
var withArrayLimit = qs.parse('a[1]=b', { arrayLimit: 0 });
assert.deepEqual(withArrayLimit, { a: { '1': 'b' } });
```
If you want to throw an error whenever the array limit is exceeded, set the `throwOnLimitExceeded` option to `true`. This option will generate a descriptive error if the query string exceeds a configured limit.
```javascript
try {
qs.parse('a[1]=b', { arrayLimit: 0, throwOnLimitExceeded: true });
} catch (err) {
assert(err instanceof Error);
assert.strictEqual(err.message, 'Array limit exceeded. Only 0 elements allowed in an array.');
}
```
When `throwOnLimitExceeded` is set to `false` (default), **qs** will parse up to the specified `arrayLimit` and if the limit is exceeded, the array will instead be converted to an object with the index as the key
To disable array parsing entirely, set `parseArrays` to `false`.
```javascript
var noParsingArrays = qs.parse('a[]=b', { parseArrays: false });
assert.deepEqual(noParsingArrays, { a: { '0': 'b' } });
```
If you mix notations, **qs** will merge the two items into an object:
```javascript
var mixedNotation = qs.parse('a[0]=b&a[b]=c');
assert.deepEqual(mixedNotation, { a: { '0': 'b', b: 'c' } });
```
You can also create arrays of objects:
```javascript
var arraysOfObjects = qs.parse('a[][b]=c');
assert.deepEqual(arraysOfObjects, { a: [{ b: 'c' }] });
```
Some people use comma to join array, **qs** can parse it:
```javascript
var arraysOfObjects = qs.parse('a=b,c', { comma: true })
assert.deepEqual(arraysOfObjects, { a: ['b', 'c'] })
```
(_this cannot convert nested objects, such as `a={b:1},{c:d}`_)
### Parsing primitive/scalar values (numbers, booleans, null, etc)
By default, all values are parsed as strings.
This behavior will not change and is explained in [issue #91](https://github.com/ljharb/qs/issues/91).
```javascript
var primitiveValues = qs.parse('a=15&b=true&c=null');
assert.deepEqual(primitiveValues, { a: '15', b: 'true', c: 'null' });
```
If you wish to auto-convert values which look like numbers, booleans, and other values into their primitive counterparts, you can use the [query-types Express JS middleware](https://github.com/xpepermint/query-types) which will auto-convert all request query parameters.
### Stringifying
[](#preventEval)
```javascript
qs.stringify(object, [options]);
```
When stringifying, **qs** by default URI encodes output. Objects are stringified as you would expect:
```javascript
assert.equal(qs.stringify({ a: 'b' }), 'a=b');
assert.equal(qs.stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c');
```
This encoding can be disabled by setting the `encode` option to `false`:
```javascript
var unencoded = qs.stringify({ a: { b: 'c' } }, { encode: false });
assert.equal(unencoded, 'a[b]=c');
```
Encoding can be disabled for keys by setting the `encodeValuesOnly` option to `true`:
```javascript
var encodedValues = qs.stringify(
{ a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] },
{ encodeValuesOnly: true }
);
assert.equal(encodedValues,'a=b&c[0]=d&c[1]=e%3Df&f[0][0]=g&f[1][0]=h');
```
This encoding can also be replaced by a custom encoding method set as `encoder` option:
```javascript
var encoded = qs.stringify({ a: { b: 'c' } }, { encoder: function (str) {
// Passed in values `a`, `b`, `c`
return // Return encoded string
}})
```
_(Note: the `encoder` option does not apply if `encode` is `false`)_
Analogue to the `encoder` there is a `decoder` option for `parse` to override decoding of properties and values:
```javascript
var decoded = qs.parse('x=z', { decoder: function (str) {
// Passed in values `x`, `z`
return // Return decoded string
}})
```
You can encode keys and values using different logic by using the type argument provided to the encoder:
```javascript
var encoded = qs.stringify({ a: { b: 'c' } }, { encoder: function (str, defaultEncoder, charset, type) {
if (type === 'key') {
return // Encoded key
} else if (type === 'value') {
return // Encoded value
}
}})
```
The type argument is also provided to the decoder:
```javascript
var decoded = qs.parse('x=z', { decoder: function (str, defaultDecoder, charset, type) {
if (type === 'key') {
return // Decoded key
} else if (type === 'value') {
return // Decoded value
}
}})
```
Examples beyond this point will be shown as though the output is not URI encoded for clarity.
Please note that the return values in these cases *will* be URI encoded during real usage.
When arrays are stringified, they follow the `arrayFormat` option, which defaults to `indices`:
```javascript
qs.stringify({ a: ['b', 'c', 'd'] });
// 'a[0]=b&a[1]=c&a[2]=d'
```
You may override this by setting the `indices` option to `false`, or to be more explicit, the `arrayFormat` option to `repeat`:
```javascript
qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false });
// 'a=b&a=c&a=d'
```
You may use the `arrayFormat` option to specify the format of the output array:
```javascript
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' })
// 'a[0]=b&a[1]=c'
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' })
// 'a[]=b&a[]=c'
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' })
// 'a=b&a=c'
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'comma' })
// 'a=b,c'
```
Note: when using `arrayFormat` set to `'comma'`, you can also pass the `commaRoundTrip` option set to `true` or `false`, to append `[]` on single-item arrays, so that they can round trip through a parse.
When objects are stringified, by default they use bracket notation:
```javascript
qs.stringify({ a: { b: { c: 'd', e: 'f' } } });
// 'a[b][c]=d&a[b][e]=f'
```
You may override this to use dot notation by setting the `allowDots` option to `true`:
```javascript
qs.stringify({ a: { b: { c: 'd', e: 'f' } } }, { allowDots: true });
// 'a.b.c=d&a.b.e=f'
```
You may encode the dot notation in the keys of object with option `encodeDotInKeys` by setting it to `true`:
Note: it implies `allowDots`, so `stringify` will error if you set `decodeDotInKeys` to `true`, and `allowDots` to `false`.
Caveat: when `encodeValuesOnly` is `true` as well as `encodeDotInKeys`, only dots in keys and nothing else will be encoded.
```javascript
qs.stringify({ "name.obj": { "first": "John", "last": "Doe" } }, { allowDots: true, encodeDotInKeys: true })
// 'name%252Eobj.first=John&name%252Eobj.last=Doe'
```
You may allow empty array values by setting the `allowEmptyArrays` option to `true`:
```javascript
qs.stringify({ foo: [], bar: 'baz' }, { allowEmptyArrays: true });
// 'foo[]&bar=baz'
```
Empty strings and null values will omit the value, but the equals sign (=) remains in place:
```javascript
assert.equal(qs.stringify({ a: '' }), 'a=');
```
Key with no values (such as an empty object or array) will return nothing:
```javascript
assert.equal(qs.stringify({ a: [] }), '');
assert.equal(qs.stringify({ a: {} }), '');
assert.equal(qs.stringify({ a: [{}] }), '');
assert.equal(qs.stringify({ a: { b: []} }), '');
assert.equal(qs.stringify({ a: { b: {}} }), '');
```
Properties that are set to `undefined` will be omitted entirely:
```javascript
assert.equal(qs.stringify({ a: null, b: undefined }), 'a=');
```
The query string may optionally be prepended with a question mark:
```javascript
assert.equal(qs.stringify({ a: 'b', c: 'd' }, { addQueryPrefix: true }), '?a=b&c=d');
```
The delimiter may be overridden with stringify as well:
```javascript
assert.equal(qs.stringify({ a: 'b', c: 'd' }, { delimiter: ';' }), 'a=b;c=d');
```
If you only want to override the serialization of `Date` objects, you can provide a `serializeDate` option:
```javascript
var date = new Date(7);
assert.equal(qs.stringify({ a: date }), 'a=1970-01-01T00:00:00.007Z'.replace(/:/g, '%3A'));
assert.equal(
qs.stringify({ a: date }, { serializeDate: function (d) { return d.getTime(); } }),
'a=7'
);
```
You may use the `sort` option to affect the order of parameter keys:
```javascript
function alphabeticalSort(a, b) {
return a.localeCompare(b);
}
assert.equal(qs.stringify({ a: 'c', z: 'y', b : 'f' }, { sort: alphabeticalSort }), 'a=c&b=f&z=y');
```
Finally, you can use the `filter` option to restrict which keys will be included in the stringified output.
If you pass a function, it will be called for each key to obtain the replacement value.
Otherwise, if you pass an array, it will be used to select properties and array indices for stringification:
```javascript
function filterFunc(prefix, value) {
if (prefix == 'b') {
// Return an `undefined` value to omit a property.
return;
}
if (prefix == 'e[f]') {
return value.getTime();
}
if (prefix == 'e[g][0]') {
return value * 2;
}
return value;
}
qs.stringify({ a: 'b', c: 'd', e: { f: new Date(123), g: [2] } }, { filter: filterFunc });
// 'a=b&c=d&e[f]=123&e[g][0]=4'
qs.stringify({ a: 'b', c: 'd', e: 'f' }, { filter: ['a', 'e'] });
// 'a=b&e=f'
qs.stringify({ a: ['b', 'c', 'd'], e: 'f' }, { filter: ['a', 0, 2] });
// 'a[0]=b&a[2]=d'
```
You could also use `filter` to inject custom serialization for user defined types.
Consider you're working with some api that expects query strings of the format for ranges:
```
https://domain.com/endpoint?range=30...70
```
For which you model as:
```javascript
class Range {
constructor(from, to) {
this.from = from;
this.to = to;
}
}
```
You could _inject_ a custom serializer to handle values of this type:
```javascript
qs.stringify(
{
range: new Range(30, 70),
},
{
filter: (prefix, value) => {
if (value instanceof Range) {
return `${value.from}...${value.to}`;
}
// serialize the usual way
return value;
},
}
);
// range=30...70
```
### Handling of `null` values
By default, `null` values are treated like empty strings:
```javascript
var withNull = qs.stringify({ a: null, b: '' });
assert.equal(withNull, 'a=&b=');
```
Parsing does not distinguish between parameters with and without equal signs.
Both are converted to empty strings.
```javascript
var equalsInsensitive = qs.parse('a&b=');
assert.deepEqual(equalsInsensitive, { a: '', b: '' });
```
To distinguish between `null` values and empty strings use the `strictNullHandling` flag. In the result string the `null`
values have no `=` sign:
```javascript
var strictNull = qs.stringify({ a: null, b: '' }, { strictNullHandling: true });
assert.equal(strictNull, 'a&b=');
```
To parse values without `=` back to `null` use the `strictNullHandling` flag:
```javascript
var parsedStrictNull = qs.parse('a&b=', { strictNullHandling: true });
assert.deepEqual(parsedStrictNull, { a: null, b: '' });
```
To completely skip rendering keys with `null` values, use the `skipNulls` flag:
```javascript
var nullsSkipped = qs.stringify({ a: 'b', c: null}, { skipNulls: true });
assert.equal(nullsSkipped, 'a=b');
```
If you're communicating with legacy systems, you can switch to `iso-8859-1` using the `charset` option:
```javascript
var iso = qs.stringify({ æ: 'æ' }, { charset: 'iso-8859-1' });
assert.equal(iso, '%E6=%E6');
```
Characters that don't exist in `iso-8859-1` will be converted to numeric entities, similar to what browsers do:
```javascript
var numeric = qs.stringify({ a: '☺' }, { charset: 'iso-8859-1' });
assert.equal(numeric, 'a=%26%239786%3B');
```
You can use the `charsetSentinel` option to announce the character by including an `utf8=✓` parameter with the proper encoding if the checkmark, similar to what Ruby on Rails and others do when submitting forms.
```javascript
var sentinel = qs.stringify({ a: '☺' }, { charsetSentinel: true });
assert.equal(sentinel, 'utf8=%E2%9C%93&a=%E2%98%BA');
var isoSentinel = qs.stringify({ a: 'æ' }, { charsetSentinel: true, charset: 'iso-8859-1' });
assert.equal(isoSentinel, 'utf8=%26%2310003%3B&a=%E6');
```
### Dealing with special character sets
By default the encoding and decoding of characters is done in `utf-8`, and `iso-8859-1` support is also built in via the `charset` parameter.
If you wish to encode querystrings to a different character set (i.e.
[Shift JIS](https://en.wikipedia.org/wiki/Shift_JIS)) you can use the
[`qs-iconv`](https://github.com/martinheidegger/qs-iconv) library:
```javascript
var encoder = require('qs-iconv/encoder')('shift_jis');
var shiftJISEncoded = qs.stringify({ a: 'こんにちは!' }, { encoder: encoder });
assert.equal(shiftJISEncoded, 'a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I');
```
This also works for decoding of query strings:
```javascript
var decoder = require('qs-iconv/decoder')('shift_jis');
var obj = qs.parse('a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I', { decoder: decoder });
assert.deepEqual(obj, { a: 'こんにちは!' });
```
### RFC 3986 and RFC 1738 space encoding
RFC3986 used as default option and encodes ' ' to *%20* which is backward compatible.
In the same time, output can be stringified as per RFC1738 with ' ' equal to '+'.
```
assert.equal(qs.stringify({ a: 'b c' }), 'a=b%20c');
assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC3986' }), 'a=b%20c');
assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC1738' }), 'a=b+c');
```
## Security
Please email [@ljharb](https://github.com/ljharb) or see https://tidelift.com/security if you have a potential security vulnerability to report.
## qs for enterprise
Available as part of the Tidelift Subscription
The maintainers of qs and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications.
Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use.
[Learn more.](https://tidelift.com/subscription/pkg/npm-qs?utm_source=npm-qs&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
[package-url]: https://npmjs.org/package/qs
[npm-version-svg]: https://versionbadg.es/ljharb/qs.svg
[deps-svg]: https://david-dm.org/ljharb/qs.svg
[deps-url]: https://david-dm.org/ljharb/qs
[dev-deps-svg]: https://david-dm.org/ljharb/qs/dev-status.svg
[dev-deps-url]: https://david-dm.org/ljharb/qs#info=devDependencies
[npm-badge-png]: https://nodei.co/npm/qs.png?downloads=true&stars=true
[license-image]: https://img.shields.io/npm/l/qs.svg
[license-url]: LICENSE
[downloads-image]: https://img.shields.io/npm/dm/qs.svg
[downloads-url]: https://npm-stat.com/charts.html?package=qs
[codecov-image]: https://codecov.io/gh/ljharb/qs/branch/main/graphs/badge.svg
[codecov-url]: https://app.codecov.io/gh/ljharb/qs/
[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/qs
[actions-url]: https://github.com/ljharb/qs/actions
## Acknowledgements
qs logo by [NUMI](https://github.com/numi-hq/open-design):
[<img src="https://raw.githubusercontent.com/numi-hq/open-design/main/assets/numi-lockup.png" alt="NUMI Logo" style="width: 200px;"/>](https://numi.tech/?ref=qs)

141
server/node_modules/grant/node_modules/qs/dist/qs.js generated vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,23 @@
'use strict';
var replace = String.prototype.replace;
var percentTwenties = /%20/g;
var Format = {
RFC1738: 'RFC1738',
RFC3986: 'RFC3986'
};
module.exports = {
'default': Format.RFC3986,
formatters: {
RFC1738: function (value) {
return replace.call(value, percentTwenties, '+');
},
RFC3986: function (value) {
return String(value);
}
},
RFC1738: Format.RFC1738,
RFC3986: Format.RFC3986
};

11
server/node_modules/grant/node_modules/qs/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,11 @@
'use strict';
var stringify = require('./stringify');
var parse = require('./parse');
var formats = require('./formats');
module.exports = {
formats: formats,
parse: parse,
stringify: stringify
};

328
server/node_modules/grant/node_modules/qs/lib/parse.js generated vendored Normal file
View File

@@ -0,0 +1,328 @@
'use strict';
var utils = require('./utils');
var has = Object.prototype.hasOwnProperty;
var isArray = Array.isArray;
var defaults = {
allowDots: false,
allowEmptyArrays: false,
allowPrototypes: false,
allowSparse: false,
arrayLimit: 20,
charset: 'utf-8',
charsetSentinel: false,
comma: false,
decodeDotInKeys: false,
decoder: utils.decode,
delimiter: '&',
depth: 5,
duplicates: 'combine',
ignoreQueryPrefix: false,
interpretNumericEntities: false,
parameterLimit: 1000,
parseArrays: true,
plainObjects: false,
strictDepth: false,
strictNullHandling: false,
throwOnLimitExceeded: false
};
var interpretNumericEntities = function (str) {
return str.replace(/&#(\d+);/g, function ($0, numberStr) {
return String.fromCharCode(parseInt(numberStr, 10));
});
};
var parseArrayValue = function (val, options, currentArrayLength) {
if (val && typeof val === 'string' && options.comma && val.indexOf(',') > -1) {
return val.split(',');
}
if (options.throwOnLimitExceeded && currentArrayLength >= options.arrayLimit) {
throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
}
return val;
};
// This is what browsers will submit when the ✓ character occurs in an
// application/x-www-form-urlencoded body and the encoding of the page containing
// the form is iso-8859-1, or when the submitted form has an accept-charset
// attribute of iso-8859-1. Presumably also with other charsets that do not contain
// the ✓ character, such as us-ascii.
var isoSentinel = 'utf8=%26%2310003%3B'; // encodeURIComponent('&#10003;')
// These are the percent-encoded utf-8 octets representing a checkmark, indicating that the request actually is utf-8 encoded.
var charsetSentinel = 'utf8=%E2%9C%93'; // encodeURIComponent('✓')
var parseValues = function parseQueryStringValues(str, options) {
var obj = { __proto__: null };
var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str;
cleanStr = cleanStr.replace(/%5B/gi, '[').replace(/%5D/gi, ']');
var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit;
var parts = cleanStr.split(
options.delimiter,
options.throwOnLimitExceeded ? limit + 1 : limit
);
if (options.throwOnLimitExceeded && parts.length > limit) {
throw new RangeError('Parameter limit exceeded. Only ' + limit + ' parameter' + (limit === 1 ? '' : 's') + ' allowed.');
}
var skipIndex = -1; // Keep track of where the utf8 sentinel was found
var i;
var charset = options.charset;
if (options.charsetSentinel) {
for (i = 0; i < parts.length; ++i) {
if (parts[i].indexOf('utf8=') === 0) {
if (parts[i] === charsetSentinel) {
charset = 'utf-8';
} else if (parts[i] === isoSentinel) {
charset = 'iso-8859-1';
}
skipIndex = i;
i = parts.length; // The eslint settings do not allow break;
}
}
}
for (i = 0; i < parts.length; ++i) {
if (i === skipIndex) {
continue;
}
var part = parts[i];
var bracketEqualsPos = part.indexOf(']=');
var pos = bracketEqualsPos === -1 ? part.indexOf('=') : bracketEqualsPos + 1;
var key;
var val;
if (pos === -1) {
key = options.decoder(part, defaults.decoder, charset, 'key');
val = options.strictNullHandling ? null : '';
} else {
key = options.decoder(part.slice(0, pos), defaults.decoder, charset, 'key');
val = utils.maybeMap(
parseArrayValue(
part.slice(pos + 1),
options,
isArray(obj[key]) ? obj[key].length : 0
),
function (encodedVal) {
return options.decoder(encodedVal, defaults.decoder, charset, 'value');
}
);
}
if (val && options.interpretNumericEntities && charset === 'iso-8859-1') {
val = interpretNumericEntities(String(val));
}
if (part.indexOf('[]=') > -1) {
val = isArray(val) ? [val] : val;
}
var existing = has.call(obj, key);
if (existing && options.duplicates === 'combine') {
obj[key] = utils.combine(obj[key], val);
} else if (!existing || options.duplicates === 'last') {
obj[key] = val;
}
}
return obj;
};
var parseObject = function (chain, val, options, valuesParsed) {
var currentArrayLength = 0;
if (chain.length > 0 && chain[chain.length - 1] === '[]') {
var parentKey = chain.slice(0, -1).join('');
currentArrayLength = Array.isArray(val) && val[parentKey] ? val[parentKey].length : 0;
}
var leaf = valuesParsed ? val : parseArrayValue(val, options, currentArrayLength);
for (var i = chain.length - 1; i >= 0; --i) {
var obj;
var root = chain[i];
if (root === '[]' && options.parseArrays) {
obj = options.allowEmptyArrays && (leaf === '' || (options.strictNullHandling && leaf === null))
? []
: utils.combine([], leaf);
} else {
obj = options.plainObjects ? { __proto__: null } : {};
var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root;
var decodedRoot = options.decodeDotInKeys ? cleanRoot.replace(/%2E/g, '.') : cleanRoot;
var index = parseInt(decodedRoot, 10);
if (!options.parseArrays && decodedRoot === '') {
obj = { 0: leaf };
} else if (
!isNaN(index)
&& root !== decodedRoot
&& String(index) === decodedRoot
&& index >= 0
&& (options.parseArrays && index <= options.arrayLimit)
) {
obj = [];
obj[index] = leaf;
} else if (decodedRoot !== '__proto__') {
obj[decodedRoot] = leaf;
}
}
leaf = obj;
}
return leaf;
};
var parseKeys = function parseQueryStringKeys(givenKey, val, options, valuesParsed) {
if (!givenKey) {
return;
}
// Transform dot notation to bracket notation
var key = options.allowDots ? givenKey.replace(/\.([^.[]+)/g, '[$1]') : givenKey;
// The regex chunks
var brackets = /(\[[^[\]]*])/;
var child = /(\[[^[\]]*])/g;
// Get the parent
var segment = options.depth > 0 && brackets.exec(key);
var parent = segment ? key.slice(0, segment.index) : key;
// Stash the parent if it exists
var keys = [];
if (parent) {
// If we aren't using plain objects, optionally prefix keys that would overwrite object prototype properties
if (!options.plainObjects && has.call(Object.prototype, parent)) {
if (!options.allowPrototypes) {
return;
}
}
keys.push(parent);
}
// Loop through children appending to the array until we hit depth
var i = 0;
while (options.depth > 0 && (segment = child.exec(key)) !== null && i < options.depth) {
i += 1;
if (!options.plainObjects && has.call(Object.prototype, segment[1].slice(1, -1))) {
if (!options.allowPrototypes) {
return;
}
}
keys.push(segment[1]);
}
// If there's a remainder, check strictDepth option for throw, else just add whatever is left
if (segment) {
if (options.strictDepth === true) {
throw new RangeError('Input depth exceeded depth option of ' + options.depth + ' and strictDepth is true');
}
keys.push('[' + key.slice(segment.index) + ']');
}
return parseObject(keys, val, options, valuesParsed);
};
var normalizeParseOptions = function normalizeParseOptions(opts) {
if (!opts) {
return defaults;
}
if (typeof opts.allowEmptyArrays !== 'undefined' && typeof opts.allowEmptyArrays !== 'boolean') {
throw new TypeError('`allowEmptyArrays` option can only be `true` or `false`, when provided');
}
if (typeof opts.decodeDotInKeys !== 'undefined' && typeof opts.decodeDotInKeys !== 'boolean') {
throw new TypeError('`decodeDotInKeys` option can only be `true` or `false`, when provided');
}
if (opts.decoder !== null && typeof opts.decoder !== 'undefined' && typeof opts.decoder !== 'function') {
throw new TypeError('Decoder has to be a function.');
}
if (typeof opts.charset !== 'undefined' && opts.charset !== 'utf-8' && opts.charset !== 'iso-8859-1') {
throw new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined');
}
if (typeof opts.throwOnLimitExceeded !== 'undefined' && typeof opts.throwOnLimitExceeded !== 'boolean') {
throw new TypeError('`throwOnLimitExceeded` option must be a boolean');
}
var charset = typeof opts.charset === 'undefined' ? defaults.charset : opts.charset;
var duplicates = typeof opts.duplicates === 'undefined' ? defaults.duplicates : opts.duplicates;
if (duplicates !== 'combine' && duplicates !== 'first' && duplicates !== 'last') {
throw new TypeError('The duplicates option must be either combine, first, or last');
}
var allowDots = typeof opts.allowDots === 'undefined' ? opts.decodeDotInKeys === true ? true : defaults.allowDots : !!opts.allowDots;
return {
allowDots: allowDots,
allowEmptyArrays: typeof opts.allowEmptyArrays === 'boolean' ? !!opts.allowEmptyArrays : defaults.allowEmptyArrays,
allowPrototypes: typeof opts.allowPrototypes === 'boolean' ? opts.allowPrototypes : defaults.allowPrototypes,
allowSparse: typeof opts.allowSparse === 'boolean' ? opts.allowSparse : defaults.allowSparse,
arrayLimit: typeof opts.arrayLimit === 'number' ? opts.arrayLimit : defaults.arrayLimit,
charset: charset,
charsetSentinel: typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel,
comma: typeof opts.comma === 'boolean' ? opts.comma : defaults.comma,
decodeDotInKeys: typeof opts.decodeDotInKeys === 'boolean' ? opts.decodeDotInKeys : defaults.decodeDotInKeys,
decoder: typeof opts.decoder === 'function' ? opts.decoder : defaults.decoder,
delimiter: typeof opts.delimiter === 'string' || utils.isRegExp(opts.delimiter) ? opts.delimiter : defaults.delimiter,
// eslint-disable-next-line no-implicit-coercion, no-extra-parens
depth: (typeof opts.depth === 'number' || opts.depth === false) ? +opts.depth : defaults.depth,
duplicates: duplicates,
ignoreQueryPrefix: opts.ignoreQueryPrefix === true,
interpretNumericEntities: typeof opts.interpretNumericEntities === 'boolean' ? opts.interpretNumericEntities : defaults.interpretNumericEntities,
parameterLimit: typeof opts.parameterLimit === 'number' ? opts.parameterLimit : defaults.parameterLimit,
parseArrays: opts.parseArrays !== false,
plainObjects: typeof opts.plainObjects === 'boolean' ? opts.plainObjects : defaults.plainObjects,
strictDepth: typeof opts.strictDepth === 'boolean' ? !!opts.strictDepth : defaults.strictDepth,
strictNullHandling: typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling,
throwOnLimitExceeded: typeof opts.throwOnLimitExceeded === 'boolean' ? opts.throwOnLimitExceeded : false
};
};
module.exports = function (str, opts) {
var options = normalizeParseOptions(opts);
if (str === '' || str === null || typeof str === 'undefined') {
return options.plainObjects ? { __proto__: null } : {};
}
var tempObj = typeof str === 'string' ? parseValues(str, options) : str;
var obj = options.plainObjects ? { __proto__: null } : {};
// Iterate over the keys and setup the new object
var keys = Object.keys(tempObj);
for (var i = 0; i < keys.length; ++i) {
var key = keys[i];
var newObj = parseKeys(key, tempObj[key], options, typeof str === 'string');
obj = utils.merge(obj, newObj, options);
}
if (options.allowSparse === true) {
return obj;
}
return utils.compact(obj);
};

View File

@@ -0,0 +1,356 @@
'use strict';
var getSideChannel = require('side-channel');
var utils = require('./utils');
var formats = require('./formats');
var has = Object.prototype.hasOwnProperty;
var arrayPrefixGenerators = {
brackets: function brackets(prefix) {
return prefix + '[]';
},
comma: 'comma',
indices: function indices(prefix, key) {
return prefix + '[' + key + ']';
},
repeat: function repeat(prefix) {
return prefix;
}
};
var isArray = Array.isArray;
var push = Array.prototype.push;
var pushToArray = function (arr, valueOrArray) {
push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
};
var toISO = Date.prototype.toISOString;
var defaultFormat = formats['default'];
var defaults = {
addQueryPrefix: false,
allowDots: false,
allowEmptyArrays: false,
arrayFormat: 'indices',
charset: 'utf-8',
charsetSentinel: false,
commaRoundTrip: false,
delimiter: '&',
encode: true,
encodeDotInKeys: false,
encoder: utils.encode,
encodeValuesOnly: false,
filter: void undefined,
format: defaultFormat,
formatter: formats.formatters[defaultFormat],
// deprecated
indices: false,
serializeDate: function serializeDate(date) {
return toISO.call(date);
},
skipNulls: false,
strictNullHandling: false
};
var isNonNullishPrimitive = function isNonNullishPrimitive(v) {
return typeof v === 'string'
|| typeof v === 'number'
|| typeof v === 'boolean'
|| typeof v === 'symbol'
|| typeof v === 'bigint';
};
var sentinel = {};
var stringify = function stringify(
object,
prefix,
generateArrayPrefix,
commaRoundTrip,
allowEmptyArrays,
strictNullHandling,
skipNulls,
encodeDotInKeys,
encoder,
filter,
sort,
allowDots,
serializeDate,
format,
formatter,
encodeValuesOnly,
charset,
sideChannel
) {
var obj = object;
var tmpSc = sideChannel;
var step = 0;
var findFlag = false;
while ((tmpSc = tmpSc.get(sentinel)) !== void undefined && !findFlag) {
// Where object last appeared in the ref tree
var pos = tmpSc.get(object);
step += 1;
if (typeof pos !== 'undefined') {
if (pos === step) {
throw new RangeError('Cyclic object value');
} else {
findFlag = true; // Break while
}
}
if (typeof tmpSc.get(sentinel) === 'undefined') {
step = 0;
}
}
if (typeof filter === 'function') {
obj = filter(prefix, obj);
} else if (obj instanceof Date) {
obj = serializeDate(obj);
} else if (generateArrayPrefix === 'comma' && isArray(obj)) {
obj = utils.maybeMap(obj, function (value) {
if (value instanceof Date) {
return serializeDate(value);
}
return value;
});
}
if (obj === null) {
if (strictNullHandling) {
return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset, 'key', format) : prefix;
}
obj = '';
}
if (isNonNullishPrimitive(obj) || utils.isBuffer(obj)) {
if (encoder) {
var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset, 'key', format);
return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset, 'value', format))];
}
return [formatter(prefix) + '=' + formatter(String(obj))];
}
var values = [];
if (typeof obj === 'undefined') {
return values;
}
var objKeys;
if (generateArrayPrefix === 'comma' && isArray(obj)) {
// we need to join elements in
if (encodeValuesOnly && encoder) {
obj = utils.maybeMap(obj, encoder);
}
objKeys = [{ value: obj.length > 0 ? obj.join(',') || null : void undefined }];
} else if (isArray(filter)) {
objKeys = filter;
} else {
var keys = Object.keys(obj);
objKeys = sort ? keys.sort(sort) : keys;
}
var encodedPrefix = encodeDotInKeys ? String(prefix).replace(/\./g, '%2E') : String(prefix);
var adjustedPrefix = commaRoundTrip && isArray(obj) && obj.length === 1 ? encodedPrefix + '[]' : encodedPrefix;
if (allowEmptyArrays && isArray(obj) && obj.length === 0) {
return adjustedPrefix + '[]';
}
for (var j = 0; j < objKeys.length; ++j) {
var key = objKeys[j];
var value = typeof key === 'object' && key && typeof key.value !== 'undefined'
? key.value
: obj[key];
if (skipNulls && value === null) {
continue;
}
var encodedKey = allowDots && encodeDotInKeys ? String(key).replace(/\./g, '%2E') : String(key);
var keyPrefix = isArray(obj)
? typeof generateArrayPrefix === 'function' ? generateArrayPrefix(adjustedPrefix, encodedKey) : adjustedPrefix
: adjustedPrefix + (allowDots ? '.' + encodedKey : '[' + encodedKey + ']');
sideChannel.set(object, step);
var valueSideChannel = getSideChannel();
valueSideChannel.set(sentinel, sideChannel);
pushToArray(values, stringify(
value,
keyPrefix,
generateArrayPrefix,
commaRoundTrip,
allowEmptyArrays,
strictNullHandling,
skipNulls,
encodeDotInKeys,
generateArrayPrefix === 'comma' && encodeValuesOnly && isArray(obj) ? null : encoder,
filter,
sort,
allowDots,
serializeDate,
format,
formatter,
encodeValuesOnly,
charset,
valueSideChannel
));
}
return values;
};
var normalizeStringifyOptions = function normalizeStringifyOptions(opts) {
if (!opts) {
return defaults;
}
if (typeof opts.allowEmptyArrays !== 'undefined' && typeof opts.allowEmptyArrays !== 'boolean') {
throw new TypeError('`allowEmptyArrays` option can only be `true` or `false`, when provided');
}
if (typeof opts.encodeDotInKeys !== 'undefined' && typeof opts.encodeDotInKeys !== 'boolean') {
throw new TypeError('`encodeDotInKeys` option can only be `true` or `false`, when provided');
}
if (opts.encoder !== null && typeof opts.encoder !== 'undefined' && typeof opts.encoder !== 'function') {
throw new TypeError('Encoder has to be a function.');
}
var charset = opts.charset || defaults.charset;
if (typeof opts.charset !== 'undefined' && opts.charset !== 'utf-8' && opts.charset !== 'iso-8859-1') {
throw new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined');
}
var format = formats['default'];
if (typeof opts.format !== 'undefined') {
if (!has.call(formats.formatters, opts.format)) {
throw new TypeError('Unknown format option provided.');
}
format = opts.format;
}
var formatter = formats.formatters[format];
var filter = defaults.filter;
if (typeof opts.filter === 'function' || isArray(opts.filter)) {
filter = opts.filter;
}
var arrayFormat;
if (opts.arrayFormat in arrayPrefixGenerators) {
arrayFormat = opts.arrayFormat;
} else if ('indices' in opts) {
arrayFormat = opts.indices ? 'indices' : 'repeat';
} else {
arrayFormat = defaults.arrayFormat;
}
if ('commaRoundTrip' in opts && typeof opts.commaRoundTrip !== 'boolean') {
throw new TypeError('`commaRoundTrip` must be a boolean, or absent');
}
var allowDots = typeof opts.allowDots === 'undefined' ? opts.encodeDotInKeys === true ? true : defaults.allowDots : !!opts.allowDots;
return {
addQueryPrefix: typeof opts.addQueryPrefix === 'boolean' ? opts.addQueryPrefix : defaults.addQueryPrefix,
allowDots: allowDots,
allowEmptyArrays: typeof opts.allowEmptyArrays === 'boolean' ? !!opts.allowEmptyArrays : defaults.allowEmptyArrays,
arrayFormat: arrayFormat,
charset: charset,
charsetSentinel: typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel,
commaRoundTrip: !!opts.commaRoundTrip,
delimiter: typeof opts.delimiter === 'undefined' ? defaults.delimiter : opts.delimiter,
encode: typeof opts.encode === 'boolean' ? opts.encode : defaults.encode,
encodeDotInKeys: typeof opts.encodeDotInKeys === 'boolean' ? opts.encodeDotInKeys : defaults.encodeDotInKeys,
encoder: typeof opts.encoder === 'function' ? opts.encoder : defaults.encoder,
encodeValuesOnly: typeof opts.encodeValuesOnly === 'boolean' ? opts.encodeValuesOnly : defaults.encodeValuesOnly,
filter: filter,
format: format,
formatter: formatter,
serializeDate: typeof opts.serializeDate === 'function' ? opts.serializeDate : defaults.serializeDate,
skipNulls: typeof opts.skipNulls === 'boolean' ? opts.skipNulls : defaults.skipNulls,
sort: typeof opts.sort === 'function' ? opts.sort : null,
strictNullHandling: typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling
};
};
module.exports = function (object, opts) {
var obj = object;
var options = normalizeStringifyOptions(opts);
var objKeys;
var filter;
if (typeof options.filter === 'function') {
filter = options.filter;
obj = filter('', obj);
} else if (isArray(options.filter)) {
filter = options.filter;
objKeys = filter;
}
var keys = [];
if (typeof obj !== 'object' || obj === null) {
return '';
}
var generateArrayPrefix = arrayPrefixGenerators[options.arrayFormat];
var commaRoundTrip = generateArrayPrefix === 'comma' && options.commaRoundTrip;
if (!objKeys) {
objKeys = Object.keys(obj);
}
if (options.sort) {
objKeys.sort(options.sort);
}
var sideChannel = getSideChannel();
for (var i = 0; i < objKeys.length; ++i) {
var key = objKeys[i];
var value = obj[key];
if (options.skipNulls && value === null) {
continue;
}
pushToArray(keys, stringify(
value,
key,
generateArrayPrefix,
commaRoundTrip,
options.allowEmptyArrays,
options.strictNullHandling,
options.skipNulls,
options.encodeDotInKeys,
options.encode ? options.encoder : null,
options.filter,
options.sort,
options.allowDots,
options.serializeDate,
options.format,
options.formatter,
options.encodeValuesOnly,
options.charset,
sideChannel
));
}
var joined = keys.join(options.delimiter);
var prefix = options.addQueryPrefix === true ? '?' : '';
if (options.charsetSentinel) {
if (options.charset === 'iso-8859-1') {
// encodeURIComponent('&#10003;'), the "numeric entity" representation of a checkmark
prefix += 'utf8=%26%2310003%3B&';
} else {
// encodeURIComponent('✓')
prefix += 'utf8=%E2%9C%93&';
}
}
return joined.length > 0 ? prefix + joined : '';
};

268
server/node_modules/grant/node_modules/qs/lib/utils.js generated vendored Normal file
View File

@@ -0,0 +1,268 @@
'use strict';
var formats = require('./formats');
var has = Object.prototype.hasOwnProperty;
var isArray = Array.isArray;
var hexTable = (function () {
var array = [];
for (var i = 0; i < 256; ++i) {
array.push('%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase());
}
return array;
}());
var compactQueue = function compactQueue(queue) {
while (queue.length > 1) {
var item = queue.pop();
var obj = item.obj[item.prop];
if (isArray(obj)) {
var compacted = [];
for (var j = 0; j < obj.length; ++j) {
if (typeof obj[j] !== 'undefined') {
compacted.push(obj[j]);
}
}
item.obj[item.prop] = compacted;
}
}
};
var arrayToObject = function arrayToObject(source, options) {
var obj = options && options.plainObjects ? { __proto__: null } : {};
for (var i = 0; i < source.length; ++i) {
if (typeof source[i] !== 'undefined') {
obj[i] = source[i];
}
}
return obj;
};
var merge = function merge(target, source, options) {
/* eslint no-param-reassign: 0 */
if (!source) {
return target;
}
if (typeof source !== 'object' && typeof source !== 'function') {
if (isArray(target)) {
target.push(source);
} else if (target && typeof target === 'object') {
if (
(options && (options.plainObjects || options.allowPrototypes))
|| !has.call(Object.prototype, source)
) {
target[source] = true;
}
} else {
return [target, source];
}
return target;
}
if (!target || typeof target !== 'object') {
return [target].concat(source);
}
var mergeTarget = target;
if (isArray(target) && !isArray(source)) {
mergeTarget = arrayToObject(target, options);
}
if (isArray(target) && isArray(source)) {
source.forEach(function (item, i) {
if (has.call(target, i)) {
var targetItem = target[i];
if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') {
target[i] = merge(targetItem, item, options);
} else {
target.push(item);
}
} else {
target[i] = item;
}
});
return target;
}
return Object.keys(source).reduce(function (acc, key) {
var value = source[key];
if (has.call(acc, key)) {
acc[key] = merge(acc[key], value, options);
} else {
acc[key] = value;
}
return acc;
}, mergeTarget);
};
var assign = function assignSingleSource(target, source) {
return Object.keys(source).reduce(function (acc, key) {
acc[key] = source[key];
return acc;
}, target);
};
var decode = function (str, defaultDecoder, charset) {
var strWithoutPlus = str.replace(/\+/g, ' ');
if (charset === 'iso-8859-1') {
// unescape never throws, no try...catch needed:
return strWithoutPlus.replace(/%[0-9a-f]{2}/gi, unescape);
}
// utf-8
try {
return decodeURIComponent(strWithoutPlus);
} catch (e) {
return strWithoutPlus;
}
};
var limit = 1024;
/* eslint operator-linebreak: [2, "before"] */
var encode = function encode(str, defaultEncoder, charset, kind, format) {
// This code was originally written by Brian White (mscdex) for the io.js core querystring library.
// It has been adapted here for stricter adherence to RFC 3986
if (str.length === 0) {
return str;
}
var string = str;
if (typeof str === 'symbol') {
string = Symbol.prototype.toString.call(str);
} else if (typeof str !== 'string') {
string = String(str);
}
if (charset === 'iso-8859-1') {
return escape(string).replace(/%u[0-9a-f]{4}/gi, function ($0) {
return '%26%23' + parseInt($0.slice(2), 16) + '%3B';
});
}
var out = '';
for (var j = 0; j < string.length; j += limit) {
var segment = string.length >= limit ? string.slice(j, j + limit) : string;
var arr = [];
for (var i = 0; i < segment.length; ++i) {
var c = segment.charCodeAt(i);
if (
c === 0x2D // -
|| c === 0x2E // .
|| c === 0x5F // _
|| c === 0x7E // ~
|| (c >= 0x30 && c <= 0x39) // 0-9
|| (c >= 0x41 && c <= 0x5A) // a-z
|| (c >= 0x61 && c <= 0x7A) // A-Z
|| (format === formats.RFC1738 && (c === 0x28 || c === 0x29)) // ( )
) {
arr[arr.length] = segment.charAt(i);
continue;
}
if (c < 0x80) {
arr[arr.length] = hexTable[c];
continue;
}
if (c < 0x800) {
arr[arr.length] = hexTable[0xC0 | (c >> 6)]
+ hexTable[0x80 | (c & 0x3F)];
continue;
}
if (c < 0xD800 || c >= 0xE000) {
arr[arr.length] = hexTable[0xE0 | (c >> 12)]
+ hexTable[0x80 | ((c >> 6) & 0x3F)]
+ hexTable[0x80 | (c & 0x3F)];
continue;
}
i += 1;
c = 0x10000 + (((c & 0x3FF) << 10) | (segment.charCodeAt(i) & 0x3FF));
arr[arr.length] = hexTable[0xF0 | (c >> 18)]
+ hexTable[0x80 | ((c >> 12) & 0x3F)]
+ hexTable[0x80 | ((c >> 6) & 0x3F)]
+ hexTable[0x80 | (c & 0x3F)];
}
out += arr.join('');
}
return out;
};
var compact = function compact(value) {
var queue = [{ obj: { o: value }, prop: 'o' }];
var refs = [];
for (var i = 0; i < queue.length; ++i) {
var item = queue[i];
var obj = item.obj[item.prop];
var keys = Object.keys(obj);
for (var j = 0; j < keys.length; ++j) {
var key = keys[j];
var val = obj[key];
if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) {
queue.push({ obj: obj, prop: key });
refs.push(val);
}
}
}
compactQueue(queue);
return value;
};
var isRegExp = function isRegExp(obj) {
return Object.prototype.toString.call(obj) === '[object RegExp]';
};
var isBuffer = function isBuffer(obj) {
if (!obj || typeof obj !== 'object') {
return false;
}
return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj));
};
var combine = function combine(a, b) {
return [].concat(a, b);
};
var maybeMap = function maybeMap(val, fn) {
if (isArray(val)) {
var mapped = [];
for (var i = 0; i < val.length; i += 1) {
mapped.push(fn(val[i]));
}
return mapped;
}
return fn(val);
};
module.exports = {
arrayToObject: arrayToObject,
assign: assign,
combine: combine,
compact: compact,
decode: decode,
encode: encode,
isBuffer: isBuffer,
isRegExp: isRegExp,
maybeMap: maybeMap,
merge: merge
};

93
server/node_modules/grant/node_modules/qs/package.json generated vendored Normal file
View File

@@ -0,0 +1,93 @@
{
"name": "qs",
"description": "A querystring parser that supports nesting and arrays, with a depth limit",
"homepage": "https://github.com/ljharb/qs",
"version": "6.14.0",
"repository": {
"type": "git",
"url": "https://github.com/ljharb/qs.git"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
},
"main": "lib/index.js",
"sideEffects": false,
"contributors": [
{
"name": "Jordan Harband",
"email": "ljharb@gmail.com",
"url": "http://ljharb.codes"
}
],
"keywords": [
"querystring",
"qs",
"query",
"url",
"parse",
"stringify"
],
"engines": {
"node": ">=0.6"
},
"dependencies": {
"side-channel": "^1.1.0"
},
"devDependencies": {
"@browserify/envify": "^6.0.0",
"@browserify/uglifyify": "^6.0.0",
"@ljharb/eslint-config": "^21.1.1",
"browserify": "^16.5.2",
"bundle-collapser": "^1.4.0",
"common-shakeify": "~1.0.0",
"eclint": "^2.8.1",
"es-value-fixtures": "^1.7.0",
"eslint": "=8.8.0",
"evalmd": "^0.0.19",
"for-each": "^0.3.3",
"glob": "=10.3.7",
"has-bigints": "^1.1.0",
"has-override-mistake": "^1.0.1",
"has-property-descriptors": "^1.0.2",
"has-proto": "^1.2.0",
"has-symbols": "^1.1.0",
"iconv-lite": "^0.5.1",
"in-publish": "^2.0.1",
"jackspeak": "=2.1.1",
"mkdirp": "^0.5.5",
"mock-property": "^1.1.0",
"module-deps": "^6.2.3",
"npmignore": "^0.3.1",
"nyc": "^10.3.2",
"object-inspect": "^1.13.3",
"qs-iconv": "^1.0.4",
"safe-publish-latest": "^2.0.0",
"safer-buffer": "^2.1.2",
"tape": "^5.9.0",
"unassertify": "^3.0.1"
},
"scripts": {
"prepack": "npmignore --auto --commentLines=autogenerated && npm run dist",
"prepublishOnly": "safe-publish-latest",
"prepublish": "not-in-publish || npm run prepublishOnly",
"pretest": "npm run --silent readme && npm run --silent lint",
"test": "npm run tests-only",
"tests-only": "nyc tape 'test/**/*.js'",
"posttest": "npx npm@'>=10.2' audit --production",
"readme": "evalmd README.md",
"postlint": "eclint check $(git ls-files | xargs find 2> /dev/null | grep -vE 'node_modules|\\.git' | grep -v dist/)",
"lint": "eslint --ext=js,mjs .",
"dist": "mkdirp dist && browserify --standalone Qs -g unassertify -g @browserify/envify -g [@browserify/uglifyify --mangle.keep_fnames --compress.keep_fnames --format.indent_level=1 --compress.arrows=false --compress.passes=4 --compress.typeofs=false] -p common-shakeify -p bundle-collapser/plugin lib/index.js > dist/qs.js"
},
"license": "BSD-3-Clause",
"publishConfig": {
"ignore": [
"!dist/*",
"bower.json",
"component.json",
".github/workflows",
"logos",
"tea.yaml"
]
}
}

View File

@@ -0,0 +1,267 @@
'use strict';
module.exports = {
emptyTestCases: [
{
input: '&',
withEmptyKeys: {},
stringifyOutput: {
brackets: '',
indices: '',
repeat: ''
},
noEmptyKeys: {}
},
{
input: '&&',
withEmptyKeys: {},
stringifyOutput: {
brackets: '',
indices: '',
repeat: ''
},
noEmptyKeys: {}
},
{
input: '&=',
withEmptyKeys: { '': '' },
stringifyOutput: {
brackets: '=',
indices: '=',
repeat: '='
},
noEmptyKeys: {}
},
{
input: '&=&',
withEmptyKeys: { '': '' },
stringifyOutput: {
brackets: '=',
indices: '=',
repeat: '='
},
noEmptyKeys: {}
},
{
input: '&=&=',
withEmptyKeys: { '': ['', ''] },
stringifyOutput: {
brackets: '[]=&[]=',
indices: '[0]=&[1]=',
repeat: '=&='
},
noEmptyKeys: {}
},
{
input: '&=&=&',
withEmptyKeys: { '': ['', ''] },
stringifyOutput: {
brackets: '[]=&[]=',
indices: '[0]=&[1]=',
repeat: '=&='
},
noEmptyKeys: {}
},
{
input: '=',
withEmptyKeys: { '': '' },
noEmptyKeys: {},
stringifyOutput: {
brackets: '=',
indices: '=',
repeat: '='
}
},
{
input: '=&',
withEmptyKeys: { '': '' },
stringifyOutput: {
brackets: '=',
indices: '=',
repeat: '='
},
noEmptyKeys: {}
},
{
input: '=&&&',
withEmptyKeys: { '': '' },
stringifyOutput: {
brackets: '=',
indices: '=',
repeat: '='
},
noEmptyKeys: {}
},
{
input: '=&=&=&',
withEmptyKeys: { '': ['', '', ''] },
stringifyOutput: {
brackets: '[]=&[]=&[]=',
indices: '[0]=&[1]=&[2]=',
repeat: '=&=&='
},
noEmptyKeys: {}
},
{
input: '=&a[]=b&a[1]=c',
withEmptyKeys: { '': '', a: ['b', 'c'] },
stringifyOutput: {
brackets: '=&a[]=b&a[]=c',
indices: '=&a[0]=b&a[1]=c',
repeat: '=&a=b&a=c'
},
noEmptyKeys: { a: ['b', 'c'] }
},
{
input: '=a',
withEmptyKeys: { '': 'a' },
noEmptyKeys: {},
stringifyOutput: {
brackets: '=a',
indices: '=a',
repeat: '=a'
}
},
{
input: 'a==a',
withEmptyKeys: { a: '=a' },
noEmptyKeys: { a: '=a' },
stringifyOutput: {
brackets: 'a==a',
indices: 'a==a',
repeat: 'a==a'
}
},
{
input: '=&a[]=b',
withEmptyKeys: { '': '', a: ['b'] },
stringifyOutput: {
brackets: '=&a[]=b',
indices: '=&a[0]=b',
repeat: '=&a=b'
},
noEmptyKeys: { a: ['b'] }
},
{
input: '=&a[]=b&a[]=c&a[2]=d',
withEmptyKeys: { '': '', a: ['b', 'c', 'd'] },
stringifyOutput: {
brackets: '=&a[]=b&a[]=c&a[]=d',
indices: '=&a[0]=b&a[1]=c&a[2]=d',
repeat: '=&a=b&a=c&a=d'
},
noEmptyKeys: { a: ['b', 'c', 'd'] }
},
{
input: '=a&=b',
withEmptyKeys: { '': ['a', 'b'] },
stringifyOutput: {
brackets: '[]=a&[]=b',
indices: '[0]=a&[1]=b',
repeat: '=a&=b'
},
noEmptyKeys: {}
},
{
input: '=a&foo=b',
withEmptyKeys: { '': 'a', foo: 'b' },
noEmptyKeys: { foo: 'b' },
stringifyOutput: {
brackets: '=a&foo=b',
indices: '=a&foo=b',
repeat: '=a&foo=b'
}
},
{
input: 'a[]=b&a=c&=',
withEmptyKeys: { '': '', a: ['b', 'c'] },
stringifyOutput: {
brackets: '=&a[]=b&a[]=c',
indices: '=&a[0]=b&a[1]=c',
repeat: '=&a=b&a=c'
},
noEmptyKeys: { a: ['b', 'c'] }
},
{
input: 'a[]=b&a=c&=',
withEmptyKeys: { '': '', a: ['b', 'c'] },
stringifyOutput: {
brackets: '=&a[]=b&a[]=c',
indices: '=&a[0]=b&a[1]=c',
repeat: '=&a=b&a=c'
},
noEmptyKeys: { a: ['b', 'c'] }
},
{
input: 'a[0]=b&a=c&=',
withEmptyKeys: { '': '', a: ['b', 'c'] },
stringifyOutput: {
brackets: '=&a[]=b&a[]=c',
indices: '=&a[0]=b&a[1]=c',
repeat: '=&a=b&a=c'
},
noEmptyKeys: { a: ['b', 'c'] }
},
{
input: 'a=b&a[]=c&=',
withEmptyKeys: { '': '', a: ['b', 'c'] },
stringifyOutput: {
brackets: '=&a[]=b&a[]=c',
indices: '=&a[0]=b&a[1]=c',
repeat: '=&a=b&a=c'
},
noEmptyKeys: { a: ['b', 'c'] }
},
{
input: 'a=b&a[0]=c&=',
withEmptyKeys: { '': '', a: ['b', 'c'] },
stringifyOutput: {
brackets: '=&a[]=b&a[]=c',
indices: '=&a[0]=b&a[1]=c',
repeat: '=&a=b&a=c'
},
noEmptyKeys: { a: ['b', 'c'] }
},
{
input: '[]=a&[]=b& []=1',
withEmptyKeys: { '': ['a', 'b'], ' ': ['1'] },
stringifyOutput: {
brackets: '[]=a&[]=b& []=1',
indices: '[0]=a&[1]=b& [0]=1',
repeat: '=a&=b& =1'
},
noEmptyKeys: { 0: 'a', 1: 'b', ' ': ['1'] }
},
{
input: '[0]=a&[1]=b&a[0]=1&a[1]=2',
withEmptyKeys: { '': ['a', 'b'], a: ['1', '2'] },
noEmptyKeys: { 0: 'a', 1: 'b', a: ['1', '2'] },
stringifyOutput: {
brackets: '[]=a&[]=b&a[]=1&a[]=2',
indices: '[0]=a&[1]=b&a[0]=1&a[1]=2',
repeat: '=a&=b&a=1&a=2'
}
},
{
input: '[deep]=a&[deep]=2',
withEmptyKeys: { '': { deep: ['a', '2'] }
},
stringifyOutput: {
brackets: '[deep][]=a&[deep][]=2',
indices: '[deep][0]=a&[deep][1]=2',
repeat: '[deep]=a&[deep]=2'
},
noEmptyKeys: { deep: ['a', '2'] }
},
{
input: '%5B0%5D=a&%5B1%5D=b',
withEmptyKeys: { '': ['a', 'b'] },
stringifyOutput: {
brackets: '[]=a&[]=b',
indices: '[0]=a&[1]=b',
repeat: '=a&=b'
},
noEmptyKeys: { 0: 'a', 1: 'b' }
}
]
};

1276
server/node_modules/grant/node_modules/qs/test/parse.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

262
server/node_modules/grant/node_modules/qs/test/utils.js generated vendored Normal file
View File

@@ -0,0 +1,262 @@
'use strict';
var test = require('tape');
var inspect = require('object-inspect');
var SaferBuffer = require('safer-buffer').Buffer;
var forEach = require('for-each');
var v = require('es-value-fixtures');
var utils = require('../lib/utils');
test('merge()', function (t) {
t.deepEqual(utils.merge(null, true), [null, true], 'merges true into null');
t.deepEqual(utils.merge(null, [42]), [null, 42], 'merges null into an array');
t.deepEqual(utils.merge({ a: 'b' }, { a: 'c' }), { a: ['b', 'c'] }, 'merges two objects with the same key');
var oneMerged = utils.merge({ foo: 'bar' }, { foo: { first: '123' } });
t.deepEqual(oneMerged, { foo: ['bar', { first: '123' }] }, 'merges a standalone and an object into an array');
var twoMerged = utils.merge({ foo: ['bar', { first: '123' }] }, { foo: { second: '456' } });
t.deepEqual(twoMerged, { foo: { 0: 'bar', 1: { first: '123' }, second: '456' } }, 'merges a standalone and two objects into an array');
var sandwiched = utils.merge({ foo: ['bar', { first: '123', second: '456' }] }, { foo: 'baz' });
t.deepEqual(sandwiched, { foo: ['bar', { first: '123', second: '456' }, 'baz'] }, 'merges an object sandwiched by two standalones into an array');
var nestedArrays = utils.merge({ foo: ['baz'] }, { foo: ['bar', 'xyzzy'] });
t.deepEqual(nestedArrays, { foo: ['baz', 'bar', 'xyzzy'] });
var noOptionsNonObjectSource = utils.merge({ foo: 'baz' }, 'bar');
t.deepEqual(noOptionsNonObjectSource, { foo: 'baz', bar: true });
var func = function f() {};
t.deepEqual(
utils.merge(func, { foo: 'bar' }),
[func, { foo: 'bar' }],
'functions can not be merged into'
);
func.bar = 'baz';
t.deepEqual(
utils.merge({ foo: 'bar' }, func),
{ foo: 'bar', bar: 'baz' },
'functions can be merge sources'
);
t.test(
'avoids invoking array setters unnecessarily',
{ skip: typeof Object.defineProperty !== 'function' },
function (st) {
var setCount = 0;
var getCount = 0;
var observed = [];
Object.defineProperty(observed, 0, {
get: function () {
getCount += 1;
return { bar: 'baz' };
},
set: function () { setCount += 1; }
});
utils.merge(observed, [null]);
st.equal(setCount, 0);
st.equal(getCount, 1);
observed[0] = observed[0]; // eslint-disable-line no-self-assign
st.equal(setCount, 1);
st.equal(getCount, 2);
st.end();
}
);
t.end();
});
test('assign()', function (t) {
var target = { a: 1, b: 2 };
var source = { b: 3, c: 4 };
var result = utils.assign(target, source);
t.equal(result, target, 'returns the target');
t.deepEqual(target, { a: 1, b: 3, c: 4 }, 'target and source are merged');
t.deepEqual(source, { b: 3, c: 4 }, 'source is untouched');
t.end();
});
test('combine()', function (t) {
t.test('both arrays', function (st) {
var a = [1];
var b = [2];
var combined = utils.combine(a, b);
st.deepEqual(a, [1], 'a is not mutated');
st.deepEqual(b, [2], 'b is not mutated');
st.notEqual(a, combined, 'a !== combined');
st.notEqual(b, combined, 'b !== combined');
st.deepEqual(combined, [1, 2], 'combined is a + b');
st.end();
});
t.test('one array, one non-array', function (st) {
var aN = 1;
var a = [aN];
var bN = 2;
var b = [bN];
var combinedAnB = utils.combine(aN, b);
st.deepEqual(b, [bN], 'b is not mutated');
st.notEqual(aN, combinedAnB, 'aN + b !== aN');
st.notEqual(a, combinedAnB, 'aN + b !== a');
st.notEqual(bN, combinedAnB, 'aN + b !== bN');
st.notEqual(b, combinedAnB, 'aN + b !== b');
st.deepEqual([1, 2], combinedAnB, 'first argument is array-wrapped when not an array');
var combinedABn = utils.combine(a, bN);
st.deepEqual(a, [aN], 'a is not mutated');
st.notEqual(aN, combinedABn, 'a + bN !== aN');
st.notEqual(a, combinedABn, 'a + bN !== a');
st.notEqual(bN, combinedABn, 'a + bN !== bN');
st.notEqual(b, combinedABn, 'a + bN !== b');
st.deepEqual([1, 2], combinedABn, 'second argument is array-wrapped when not an array');
st.end();
});
t.test('neither is an array', function (st) {
var combined = utils.combine(1, 2);
st.notEqual(1, combined, '1 + 2 !== 1');
st.notEqual(2, combined, '1 + 2 !== 2');
st.deepEqual([1, 2], combined, 'both arguments are array-wrapped when not an array');
st.end();
});
t.end();
});
test('decode', function (t) {
t.equal(
utils.decode('a+b'),
'a b',
'decodes + to space'
);
t.equal(
utils.decode('name%2Eobj'),
'name.obj',
'decodes a string'
);
t.equal(
utils.decode('name%2Eobj%2Efoo', null, 'iso-8859-1'),
'name.obj.foo',
'decodes a string in iso-8859-1'
);
t.end();
});
test('encode', function (t) {
forEach(v.nullPrimitives, function (nullish) {
t['throws'](
function () { utils.encode(nullish); },
TypeError,
inspect(nullish) + ' is not a string'
);
});
t.equal(utils.encode(''), '', 'empty string returns itself');
t.deepEqual(utils.encode([]), [], 'empty array returns itself');
t.deepEqual(utils.encode({ length: 0 }), { length: 0 }, 'empty arraylike returns itself');
t.test('symbols', { skip: !v.hasSymbols }, function (st) {
st.equal(utils.encode(Symbol('x')), 'Symbol%28x%29', 'symbol is encoded');
st.end();
});
t.equal(
utils.encode('(abc)'),
'%28abc%29',
'encodes parentheses'
);
t.equal(
utils.encode({ toString: function () { return '(abc)'; } }),
'%28abc%29',
'toStrings and encodes parentheses'
);
t.equal(
utils.encode('abc 123 💩', null, 'iso-8859-1'),
'abc%20123%20%26%2355357%3B%26%2356489%3B',
'encodes in iso-8859-1'
);
var longString = '';
var expectedString = '';
for (var i = 0; i < 1500; i++) {
longString += ' ';
expectedString += '%20';
}
t.equal(
utils.encode(longString),
expectedString,
'encodes a long string'
);
t.equal(
utils.encode('\x28\x29'),
'%28%29',
'encodes parens normally'
);
t.equal(
utils.encode('\x28\x29', null, null, null, 'RFC1738'),
'()',
'does not encode parens in RFC1738'
);
// todo RFC1738 format
t.equal(
utils.encode('Āက豈'),
'%C4%80%E1%80%80%EF%A4%80',
'encodes multibyte chars'
);
t.equal(
utils.encode('\uD83D \uDCA9'),
'%F0%9F%90%A0%F0%BA%90%80',
'encodes lone surrogates'
);
t.end();
});
test('isBuffer()', function (t) {
forEach([null, undefined, true, false, '', 'abc', 42, 0, NaN, {}, [], function () {}, /a/g], function (x) {
t.equal(utils.isBuffer(x), false, inspect(x) + ' is not a buffer');
});
var fakeBuffer = { constructor: Buffer };
t.equal(utils.isBuffer(fakeBuffer), false, 'fake buffer is not a buffer');
var saferBuffer = SaferBuffer.from('abc');
t.equal(utils.isBuffer(saferBuffer), true, 'SaferBuffer instance is a buffer');
var buffer = Buffer.from && Buffer.alloc ? Buffer.from('abc') : new Buffer('abc');
t.equal(utils.isBuffer(buffer), true, 'real Buffer instance is a buffer');
t.end();
});
test('isRegExp()', function (t) {
t.equal(utils.isRegExp(/a/g), true, 'RegExp is a RegExp');
t.equal(utils.isRegExp(new RegExp('a', 'g')), true, 'new RegExp is a RegExp');
t.equal(utils.isRegExp(new Date()), false, 'Date is not a RegExp');
forEach(v.primitives, function (primitive) {
t.equal(utils.isRegExp(primitive), false, inspect(primitive) + ' is not a RegExp');
});
t.end();
});

88
server/node_modules/grant/package.json generated vendored Normal file
View File

@@ -0,0 +1,88 @@
{
"name": "grant",
"version": "5.4.24",
"description": "OAuth Proxy",
"keywords": [
"oauth",
"oauth2",
"openid",
"openid-connect",
"authentication",
"authorization",
"proxy",
"middleware",
"lambda",
"express",
"koa",
"hapi",
"fastify",
"aws",
"azure",
"google-cloud",
"vercel"
],
"license": "MIT",
"homepage": "https://github.com/simov/grant",
"author": "Simeon Velichkov <simeonvelichkov@gmail.com> (https://simov.github.io)",
"repository": {
"type": "git",
"url": "https://github.com/simov/grant.git"
},
"dependencies": {
"qs": "^6.14.0",
"request-compose": "^2.1.7",
"request-oauth": "^1.0.1"
},
"optionalDependencies": {
"cookie": "^0.7.2",
"cookie-signature": "^1.2.2",
"jwk-to-pem": "^2.0.7",
"jws": "^4.0.0"
},
"devDependencies": {
"@curveball/bodyparser": "0.4.6",
"@curveball/core": "0.14.2",
"@curveball/router": "0.2.4",
"@curveball/session": "0.5.0",
"@fastify/cookie": "^9.4.0",
"@fastify/formbody": "^7.4.0",
"@fastify/session": "^10.9.0",
"@hapi/hapi": "^21.3.10",
"@hapi/yar": "^11.0.2",
"body-parser": "^1.20.3",
"cookie-session": "^2.1.0",
"express": "^4.21.0",
"express-session": "^1.18.0",
"fastify": "^4.28.1",
"grant-profile": "^1.0.2",
"koa": "^2.15.3",
"koa-bodyparser": "^4.4.1",
"koa-mount": "^4.0.0",
"koa-qs": "^3.0.0",
"koa-session": "^6.4.0",
"mocha": "^10.7.3",
"nyc": "^17.0.0",
"request-cookie": "^1.0.1",
"request-logs": "^2.1.5"
},
"main": "./grant.js",
"files": [
"config/",
"lib/",
"grant.js",
"grant.d.ts",
"CHANGELOG.md",
"LICENSE",
"README.md",
"package.json"
],
"types": "grant.d.ts",
"scripts": {
"test": "npm run test:ci",
"test:ci": "npx mocha --recursive",
"test:cov": "npx nyc --reporter=lcov --reporter=text-summary mocha -- --recursive"
},
"engines": {
"node": ">=12.0.0"
}
}